diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-17 00:20:39 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-17 00:20:39 -0400 |
| commit | 8d15b0ec32f20a57881dc073b2e8d11dea0ccceb (patch) | |
| tree | 8aa3d4dfd0660807c3ce2893b35292b3b0e3bf08 | |
| parent | 005411c3e9147bc3b78215390e847d688dbbc163 (diff) | |
| parent | cc8da5263fa743c33d6503f85113bcb70048e633 (diff) | |
Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
drm/radeon: switch to using late_initcall
radeon legacy chips: tv dac bg/dac adj updates
drm/radeon: introduce kernel modesetting for radeon hardware
drm: Add the TTM GPU memory manager subsystem.
drm: Memory fragmentation from lost alignment blocks
drm/radeon: fix mobility flags on new PCI IDs.
75 files changed, 41092 insertions, 46 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index f5d46e7199d4..c961fe415aef 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig | |||
| @@ -18,6 +18,14 @@ menuconfig DRM | |||
| 18 | details. You should also select and configure AGP | 18 | details. You should also select and configure AGP |
| 19 | (/dev/agpgart) support. | 19 | (/dev/agpgart) support. |
| 20 | 20 | ||
| 21 | config DRM_TTM | ||
| 22 | tristate | ||
| 23 | depends on DRM | ||
| 24 | help | ||
| 25 | GPU memory management subsystem for devices with multiple | ||
| 26 | GPU memory types. Will be enabled automatically if a device driver | ||
| 27 | uses it. | ||
| 28 | |||
| 21 | config DRM_TDFX | 29 | config DRM_TDFX |
| 22 | tristate "3dfx Banshee/Voodoo3+" | 30 | tristate "3dfx Banshee/Voodoo3+" |
| 23 | depends on DRM && PCI | 31 | depends on DRM && PCI |
| @@ -36,6 +44,11 @@ config DRM_R128 | |||
| 36 | config DRM_RADEON | 44 | config DRM_RADEON |
| 37 | tristate "ATI Radeon" | 45 | tristate "ATI Radeon" |
| 38 | depends on DRM && PCI | 46 | depends on DRM && PCI |
| 47 | select FB_CFB_FILLRECT | ||
| 48 | select FB_CFB_COPYAREA | ||
| 49 | select FB_CFB_IMAGEBLIT | ||
| 50 | select FB | ||
| 51 | select FRAMEBUFFER_CONSOLE if !EMBEDDED | ||
| 39 | help | 52 | help |
| 40 | Choose this option if you have an ATI Radeon graphics card. There | 53 | Choose this option if you have an ATI Radeon graphics card. There |
| 41 | are both PCI and AGP versions. You don't need to choose this to | 54 | are both PCI and AGP versions. You don't need to choose this to |
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 4ec5061fa584..4e89ab08b7b8 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile | |||
| @@ -26,4 +26,4 @@ obj-$(CONFIG_DRM_I915) += i915/ | |||
| 26 | obj-$(CONFIG_DRM_SIS) += sis/ | 26 | obj-$(CONFIG_DRM_SIS) += sis/ |
| 27 | obj-$(CONFIG_DRM_SAVAGE)+= savage/ | 27 | obj-$(CONFIG_DRM_SAVAGE)+= savage/ |
| 28 | obj-$(CONFIG_DRM_VIA) +=via/ | 28 | obj-$(CONFIG_DRM_VIA) +=via/ |
| 29 | 29 | obj-$(CONFIG_DRM_TTM) += ttm/ | |
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 7819fd930a51..a912a0ff11cc 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c | |||
| @@ -188,36 +188,34 @@ static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent, | |||
| 188 | 188 | ||
| 189 | 189 | ||
| 190 | 190 | ||
| 191 | struct drm_mm_node *drm_mm_get_block(struct drm_mm_node * parent, | 191 | struct drm_mm_node *drm_mm_get_block(struct drm_mm_node *node, |
| 192 | unsigned long size, unsigned alignment) | 192 | unsigned long size, unsigned alignment) |
| 193 | { | 193 | { |
| 194 | 194 | ||
| 195 | struct drm_mm_node *align_splitoff = NULL; | 195 | struct drm_mm_node *align_splitoff = NULL; |
| 196 | struct drm_mm_node *child; | ||
| 197 | unsigned tmp = 0; | 196 | unsigned tmp = 0; |
| 198 | 197 | ||
| 199 | if (alignment) | 198 | if (alignment) |
| 200 | tmp = parent->start % alignment; | 199 | tmp = node->start % alignment; |
| 201 | 200 | ||
| 202 | if (tmp) { | 201 | if (tmp) { |
| 203 | align_splitoff = | 202 | align_splitoff = |
| 204 | drm_mm_split_at_start(parent, alignment - tmp, 0); | 203 | drm_mm_split_at_start(node, alignment - tmp, 0); |
| 205 | if (unlikely(align_splitoff == NULL)) | 204 | if (unlikely(align_splitoff == NULL)) |
| 206 | return NULL; | 205 | return NULL; |
| 207 | } | 206 | } |
| 208 | 207 | ||
| 209 | if (parent->size == size) { | 208 | if (node->size == size) { |
| 210 | list_del_init(&parent->fl_entry); | 209 | list_del_init(&node->fl_entry); |
| 211 | parent->free = 0; | 210 | node->free = 0; |
| 212 | return parent; | ||
| 213 | } else { | 211 | } else { |
| 214 | child = drm_mm_split_at_start(parent, size, 0); | 212 | node = drm_mm_split_at_start(node, size, 0); |
| 215 | } | 213 | } |
| 216 | 214 | ||
| 217 | if (align_splitoff) | 215 | if (align_splitoff) |
| 218 | drm_mm_put_block(align_splitoff); | 216 | drm_mm_put_block(align_splitoff); |
| 219 | 217 | ||
| 220 | return child; | 218 | return node; |
| 221 | } | 219 | } |
| 222 | 220 | ||
| 223 | EXPORT_SYMBOL(drm_mm_get_block); | 221 | EXPORT_SYMBOL(drm_mm_get_block); |
diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig new file mode 100644 index 000000000000..2168d67f09a6 --- /dev/null +++ b/drivers/gpu/drm/radeon/Kconfig | |||
| @@ -0,0 +1,34 @@ | |||
| 1 | config DRM_RADEON_KMS | ||
| 2 | bool "Enable modesetting on radeon by default" | ||
| 3 | depends on DRM_RADEON | ||
| 4 | select DRM_TTM | ||
| 5 | help | ||
| 6 | Choose this option if you want kernel modesetting enabled by default, | ||
| 7 | and you have a new enough userspace to support this. Running old | ||
| 8 | userspaces with this enabled will cause pain. | ||
| 9 | |||
| 10 | When kernel modesetting is enabled the IOCTL of radeon/drm | ||
| 11 | driver are considered as invalid and an error message is printed | ||
| 12 | in the log and they return failure. | ||
| 13 | |||
| 14 | KMS enabled userspace will use new API to talk with the radeon/drm | ||
| 15 | driver. The new API provide functions to create/destroy/share/mmap | ||
| 16 | buffer object which are then managed by the kernel memory manager | ||
| 17 | (here TTM). In order to submit command to the GPU the userspace | ||
| 18 | provide a buffer holding the command stream, along this buffer | ||
| 19 | userspace have to provide a list of buffer object used by the | ||
| 20 | command stream. The kernel radeon driver will then place buffer | ||
| 21 | in GPU accessible memory and will update command stream to reflect | ||
| 22 | the position of the different buffers. | ||
| 23 | |||
| 24 | The kernel will also perform security check on command stream | ||
| 25 | provided by the user, we want to catch and forbid any illegal use | ||
| 26 | of the GPU such as DMA into random system memory or into memory | ||
| 27 | not owned by the process supplying the command stream. This part | ||
| 28 | of the code is still incomplete and this why we propose that patch | ||
| 29 | as a staging driver addition, future security might forbid current | ||
| 30 | experimental userspace to run. | ||
| 31 | |||
| 32 | This code support the following hardware : R1XX,R2XX,R3XX,R4XX,R5XX | ||
| 33 | (radeon up to X1950). Works is underway to provide support for R6XX, | ||
| 34 | R7XX and newer hardware (radeon from HD2XXX to HD4XXX). | ||
diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index 52ce439a0f2e..5fae1e074b4b 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile | |||
| @@ -3,7 +3,17 @@ | |||
| 3 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. | 3 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. |
| 4 | 4 | ||
| 5 | ccflags-y := -Iinclude/drm | 5 | ccflags-y := -Iinclude/drm |
| 6 | radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o r600_cp.o | 6 | radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \ |
| 7 | radeon_irq.o r300_cmdbuf.o r600_cp.o | ||
| 8 | |||
| 9 | radeon-$(CONFIG_DRM_RADEON_KMS) += radeon_device.o radeon_kms.o \ | ||
| 10 | radeon_atombios.o radeon_agp.o atombios_crtc.o radeon_combios.o \ | ||
| 11 | atom.o radeon_fence.o radeon_ttm.o radeon_object.o radeon_gart.o \ | ||
| 12 | radeon_legacy_crtc.o radeon_legacy_encoders.o radeon_connectors.o \ | ||
| 13 | radeon_encoders.o radeon_display.o radeon_cursor.o radeon_i2c.o \ | ||
| 14 | radeon_clocks.o radeon_fb.o radeon_gem.o radeon_ring.o radeon_irq_kms.o \ | ||
| 15 | radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \ | ||
| 16 | rs400.o rs600.o rs690.o rv515.o r520.o r600.o rs780.o rv770.o | ||
| 7 | 17 | ||
| 8 | radeon-$(CONFIG_COMPAT) += radeon_ioc32.o | 18 | radeon-$(CONFIG_COMPAT) += radeon_ioc32.o |
| 9 | 19 | ||
diff --git a/drivers/gpu/drm/radeon/ObjectID.h b/drivers/gpu/drm/radeon/ObjectID.h new file mode 100644 index 000000000000..6d0183c61d3b --- /dev/null +++ b/drivers/gpu/drm/radeon/ObjectID.h | |||
| @@ -0,0 +1,578 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2006-2007 Advanced Micro Devices, 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 | /* based on stg/asic_reg/drivers/inc/asic_reg/ObjectID.h ver 23 */ | ||
| 23 | |||
| 24 | #ifndef _OBJECTID_H | ||
| 25 | #define _OBJECTID_H | ||
| 26 | |||
| 27 | #if defined(_X86_) | ||
| 28 | #pragma pack(1) | ||
| 29 | #endif | ||
| 30 | |||
| 31 | /****************************************************/ | ||
| 32 | /* Graphics Object Type Definition */ | ||
| 33 | /****************************************************/ | ||
| 34 | #define GRAPH_OBJECT_TYPE_NONE 0x0 | ||
| 35 | #define GRAPH_OBJECT_TYPE_GPU 0x1 | ||
| 36 | #define GRAPH_OBJECT_TYPE_ENCODER 0x2 | ||
| 37 | #define GRAPH_OBJECT_TYPE_CONNECTOR 0x3 | ||
| 38 | #define GRAPH_OBJECT_TYPE_ROUTER 0x4 | ||
| 39 | /* deleted */ | ||
| 40 | |||
| 41 | /****************************************************/ | ||
| 42 | /* Encoder Object ID Definition */ | ||
| 43 | /****************************************************/ | ||
| 44 | #define ENCODER_OBJECT_ID_NONE 0x00 | ||
| 45 | |||
| 46 | /* Radeon Class Display Hardware */ | ||
| 47 | #define ENCODER_OBJECT_ID_INTERNAL_LVDS 0x01 | ||
| 48 | #define ENCODER_OBJECT_ID_INTERNAL_TMDS1 0x02 | ||
| 49 | #define ENCODER_OBJECT_ID_INTERNAL_TMDS2 0x03 | ||
| 50 | #define ENCODER_OBJECT_ID_INTERNAL_DAC1 0x04 | ||
| 51 | #define ENCODER_OBJECT_ID_INTERNAL_DAC2 0x05 /* TV/CV DAC */ | ||
| 52 | #define ENCODER_OBJECT_ID_INTERNAL_SDVOA 0x06 | ||
| 53 | #define ENCODER_OBJECT_ID_INTERNAL_SDVOB 0x07 | ||
| 54 | |||
| 55 | /* External Third Party Encoders */ | ||
| 56 | #define ENCODER_OBJECT_ID_SI170B 0x08 | ||
| 57 | #define ENCODER_OBJECT_ID_CH7303 0x09 | ||
| 58 | #define ENCODER_OBJECT_ID_CH7301 0x0A | ||
| 59 | #define ENCODER_OBJECT_ID_INTERNAL_DVO1 0x0B /* This belongs to Radeon Class Display Hardware */ | ||
| 60 | #define ENCODER_OBJECT_ID_EXTERNAL_SDVOA 0x0C | ||
| 61 | #define ENCODER_OBJECT_ID_EXTERNAL_SDVOB 0x0D | ||
| 62 | #define ENCODER_OBJECT_ID_TITFP513 0x0E | ||
| 63 | #define ENCODER_OBJECT_ID_INTERNAL_LVTM1 0x0F /* not used for Radeon */ | ||
| 64 | #define ENCODER_OBJECT_ID_VT1623 0x10 | ||
| 65 | #define ENCODER_OBJECT_ID_HDMI_SI1930 0x11 | ||
| 66 | #define ENCODER_OBJECT_ID_HDMI_INTERNAL 0x12 | ||
| 67 | /* Kaleidoscope (KLDSCP) Class Display Hardware (internal) */ | ||
| 68 | #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 0x13 | ||
| 69 | #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 0x14 | ||
| 70 | #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1 0x15 | ||
| 71 | #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 0x16 /* Shared with CV/TV and CRT */ | ||
| 72 | #define ENCODER_OBJECT_ID_SI178 0X17 /* External TMDS (dual link, no HDCP.) */ | ||
| 73 | #define ENCODER_OBJECT_ID_MVPU_FPGA 0x18 /* MVPU FPGA chip */ | ||
| 74 | #define ENCODER_OBJECT_ID_INTERNAL_DDI 0x19 | ||
| 75 | #define ENCODER_OBJECT_ID_VT1625 0x1A | ||
| 76 | #define ENCODER_OBJECT_ID_HDMI_SI1932 0x1B | ||
| 77 | #define ENCODER_OBJECT_ID_DP_AN9801 0x1C | ||
| 78 | #define ENCODER_OBJECT_ID_DP_DP501 0x1D | ||
| 79 | #define ENCODER_OBJECT_ID_INTERNAL_UNIPHY 0x1E | ||
| 80 | #define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA 0x1F | ||
| 81 | #define ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 0x20 | ||
| 82 | #define ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 0x21 | ||
| 83 | |||
| 84 | #define ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO 0xFF | ||
| 85 | |||
| 86 | /****************************************************/ | ||
| 87 | /* Connector Object ID Definition */ | ||
| 88 | /****************************************************/ | ||
| 89 | #define CONNECTOR_OBJECT_ID_NONE 0x00 | ||
| 90 | #define CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I 0x01 | ||
| 91 | #define CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I 0x02 | ||
| 92 | #define CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D 0x03 | ||
| 93 | #define CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D 0x04 | ||
| 94 | #define CONNECTOR_OBJECT_ID_VGA 0x05 | ||
| 95 | #define CONNECTOR_OBJECT_ID_COMPOSITE 0x06 | ||
| 96 | #define CONNECTOR_OBJECT_ID_SVIDEO 0x07 | ||
| 97 | #define CONNECTOR_OBJECT_ID_YPbPr 0x08 | ||
| 98 | #define CONNECTOR_OBJECT_ID_D_CONNECTOR 0x09 | ||
| 99 | #define CONNECTOR_OBJECT_ID_9PIN_DIN 0x0A /* Supports both CV & TV */ | ||
| 100 | #define CONNECTOR_OBJECT_ID_SCART 0x0B | ||
| 101 | #define CONNECTOR_OBJECT_ID_HDMI_TYPE_A 0x0C | ||
| 102 | #define CONNECTOR_OBJECT_ID_HDMI_TYPE_B 0x0D | ||
| 103 | #define CONNECTOR_OBJECT_ID_LVDS 0x0E | ||
| 104 | #define CONNECTOR_OBJECT_ID_7PIN_DIN 0x0F | ||
| 105 | #define CONNECTOR_OBJECT_ID_PCIE_CONNECTOR 0x10 | ||
| 106 | #define CONNECTOR_OBJECT_ID_CROSSFIRE 0x11 | ||
| 107 | #define CONNECTOR_OBJECT_ID_HARDCODE_DVI 0x12 | ||
| 108 | #define CONNECTOR_OBJECT_ID_DISPLAYPORT 0x13 | ||
| 109 | |||
| 110 | /* deleted */ | ||
| 111 | |||
| 112 | /****************************************************/ | ||
| 113 | /* Router Object ID Definition */ | ||
| 114 | /****************************************************/ | ||
| 115 | #define ROUTER_OBJECT_ID_NONE 0x00 | ||
| 116 | #define ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL 0x01 | ||
| 117 | |||
| 118 | /****************************************************/ | ||
| 119 | /* Graphics Object ENUM ID Definition */ | ||
| 120 | /****************************************************/ | ||
| 121 | #define GRAPH_OBJECT_ENUM_ID1 0x01 | ||
| 122 | #define GRAPH_OBJECT_ENUM_ID2 0x02 | ||
| 123 | #define GRAPH_OBJECT_ENUM_ID3 0x03 | ||
| 124 | #define GRAPH_OBJECT_ENUM_ID4 0x04 | ||
| 125 | #define GRAPH_OBJECT_ENUM_ID5 0x05 | ||
| 126 | #define GRAPH_OBJECT_ENUM_ID6 0x06 | ||
| 127 | |||
| 128 | /****************************************************/ | ||
| 129 | /* Graphics Object ID Bit definition */ | ||
| 130 | /****************************************************/ | ||
| 131 | #define OBJECT_ID_MASK 0x00FF | ||
| 132 | #define ENUM_ID_MASK 0x0700 | ||
| 133 | #define RESERVED1_ID_MASK 0x0800 | ||
| 134 | #define OBJECT_TYPE_MASK 0x7000 | ||
| 135 | #define RESERVED2_ID_MASK 0x8000 | ||
| 136 | |||
| 137 | #define OBJECT_ID_SHIFT 0x00 | ||
| 138 | #define ENUM_ID_SHIFT 0x08 | ||
| 139 | #define OBJECT_TYPE_SHIFT 0x0C | ||
| 140 | |||
| 141 | /****************************************************/ | ||
| 142 | /* Graphics Object family definition */ | ||
| 143 | /****************************************************/ | ||
| 144 | #define CONSTRUCTOBJECTFAMILYID(GRAPHICS_OBJECT_TYPE, GRAPHICS_OBJECT_ID) \ | ||
| 145 | (GRAPHICS_OBJECT_TYPE << OBJECT_TYPE_SHIFT | \ | ||
| 146 | GRAPHICS_OBJECT_ID << OBJECT_ID_SHIFT) | ||
| 147 | /****************************************************/ | ||
| 148 | /* GPU Object ID definition - Shared with BIOS */ | ||
| 149 | /****************************************************/ | ||
| 150 | #define GPU_ENUM_ID1 (GRAPH_OBJECT_TYPE_GPU << OBJECT_TYPE_SHIFT |\ | ||
| 151 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT) | ||
| 152 | |||
| 153 | /****************************************************/ | ||
| 154 | /* Encoder Object ID definition - Shared with BIOS */ | ||
| 155 | /****************************************************/ | ||
| 156 | /* | ||
| 157 | #define ENCODER_INTERNAL_LVDS_ENUM_ID1 0x2101 | ||
| 158 | #define ENCODER_INTERNAL_TMDS1_ENUM_ID1 0x2102 | ||
| 159 | #define ENCODER_INTERNAL_TMDS2_ENUM_ID1 0x2103 | ||
| 160 | #define ENCODER_INTERNAL_DAC1_ENUM_ID1 0x2104 | ||
| 161 | #define ENCODER_INTERNAL_DAC2_ENUM_ID1 0x2105 | ||
| 162 | #define ENCODER_INTERNAL_SDVOA_ENUM_ID1 0x2106 | ||
| 163 | #define ENCODER_INTERNAL_SDVOB_ENUM_ID1 0x2107 | ||
| 164 | #define ENCODER_SIL170B_ENUM_ID1 0x2108 | ||
| 165 | #define ENCODER_CH7303_ENUM_ID1 0x2109 | ||
| 166 | #define ENCODER_CH7301_ENUM_ID1 0x210A | ||
| 167 | #define ENCODER_INTERNAL_DVO1_ENUM_ID1 0x210B | ||
| 168 | #define ENCODER_EXTERNAL_SDVOA_ENUM_ID1 0x210C | ||
| 169 | #define ENCODER_EXTERNAL_SDVOB_ENUM_ID1 0x210D | ||
| 170 | #define ENCODER_TITFP513_ENUM_ID1 0x210E | ||
| 171 | #define ENCODER_INTERNAL_LVTM1_ENUM_ID1 0x210F | ||
| 172 | #define ENCODER_VT1623_ENUM_ID1 0x2110 | ||
| 173 | #define ENCODER_HDMI_SI1930_ENUM_ID1 0x2111 | ||
| 174 | #define ENCODER_HDMI_INTERNAL_ENUM_ID1 0x2112 | ||
| 175 | #define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1 0x2113 | ||
| 176 | #define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1 0x2114 | ||
| 177 | #define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1 0x2115 | ||
| 178 | #define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1 0x2116 | ||
| 179 | #define ENCODER_SI178_ENUM_ID1 0x2117 | ||
| 180 | #define ENCODER_MVPU_FPGA_ENUM_ID1 0x2118 | ||
| 181 | #define ENCODER_INTERNAL_DDI_ENUM_ID1 0x2119 | ||
| 182 | #define ENCODER_VT1625_ENUM_ID1 0x211A | ||
| 183 | #define ENCODER_HDMI_SI1932_ENUM_ID1 0x211B | ||
| 184 | #define ENCODER_ENCODER_DP_AN9801_ENUM_ID1 0x211C | ||
| 185 | #define ENCODER_DP_DP501_ENUM_ID1 0x211D | ||
| 186 | #define ENCODER_INTERNAL_UNIPHY_ENUM_ID1 0x211E | ||
| 187 | */ | ||
| 188 | #define ENCODER_INTERNAL_LVDS_ENUM_ID1 \ | ||
| 189 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 190 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 191 | ENCODER_OBJECT_ID_INTERNAL_LVDS << OBJECT_ID_SHIFT) | ||
| 192 | |||
| 193 | #define ENCODER_INTERNAL_TMDS1_ENUM_ID1 \ | ||
| 194 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 195 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 196 | ENCODER_OBJECT_ID_INTERNAL_TMDS1 << OBJECT_ID_SHIFT) | ||
| 197 | |||
| 198 | #define ENCODER_INTERNAL_TMDS2_ENUM_ID1 \ | ||
| 199 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 200 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 201 | ENCODER_OBJECT_ID_INTERNAL_TMDS2 << OBJECT_ID_SHIFT) | ||
| 202 | |||
| 203 | #define ENCODER_INTERNAL_DAC1_ENUM_ID1 \ | ||
| 204 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 205 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 206 | ENCODER_OBJECT_ID_INTERNAL_DAC1 << OBJECT_ID_SHIFT) | ||
| 207 | |||
| 208 | #define ENCODER_INTERNAL_DAC2_ENUM_ID1 \ | ||
| 209 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 210 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 211 | ENCODER_OBJECT_ID_INTERNAL_DAC2 << OBJECT_ID_SHIFT) | ||
| 212 | |||
| 213 | #define ENCODER_INTERNAL_SDVOA_ENUM_ID1 \ | ||
| 214 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 215 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 216 | ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT) | ||
| 217 | |||
| 218 | #define ENCODER_INTERNAL_SDVOA_ENUM_ID2 \ | ||
| 219 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 220 | GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ | ||
| 221 | ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT) | ||
| 222 | |||
| 223 | #define ENCODER_INTERNAL_SDVOB_ENUM_ID1 \ | ||
| 224 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 225 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 226 | ENCODER_OBJECT_ID_INTERNAL_SDVOB << OBJECT_ID_SHIFT) | ||
| 227 | |||
| 228 | #define ENCODER_SIL170B_ENUM_ID1 \ | ||
| 229 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 230 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 231 | ENCODER_OBJECT_ID_SI170B << OBJECT_ID_SHIFT) | ||
| 232 | |||
| 233 | #define ENCODER_CH7303_ENUM_ID1 \ | ||
| 234 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 235 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 236 | ENCODER_OBJECT_ID_CH7303 << OBJECT_ID_SHIFT) | ||
| 237 | |||
| 238 | #define ENCODER_CH7301_ENUM_ID1 \ | ||
| 239 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 240 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 241 | ENCODER_OBJECT_ID_CH7301 << OBJECT_ID_SHIFT) | ||
| 242 | |||
| 243 | #define ENCODER_INTERNAL_DVO1_ENUM_ID1 \ | ||
| 244 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 245 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 246 | ENCODER_OBJECT_ID_INTERNAL_DVO1 << OBJECT_ID_SHIFT) | ||
| 247 | |||
| 248 | #define ENCODER_EXTERNAL_SDVOA_ENUM_ID1 \ | ||
| 249 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 250 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 251 | ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT) | ||
| 252 | |||
| 253 | #define ENCODER_EXTERNAL_SDVOA_ENUM_ID2 \ | ||
| 254 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 255 | GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ | ||
| 256 | ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT) | ||
| 257 | |||
| 258 | #define ENCODER_EXTERNAL_SDVOB_ENUM_ID1 \ | ||
| 259 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 260 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 261 | ENCODER_OBJECT_ID_EXTERNAL_SDVOB << OBJECT_ID_SHIFT) | ||
| 262 | |||
| 263 | #define ENCODER_TITFP513_ENUM_ID1 \ | ||
| 264 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 265 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 266 | ENCODER_OBJECT_ID_TITFP513 << OBJECT_ID_SHIFT) | ||
| 267 | |||
| 268 | #define ENCODER_INTERNAL_LVTM1_ENUM_ID1 \ | ||
| 269 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 270 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 271 | ENCODER_OBJECT_ID_INTERNAL_LVTM1 << OBJECT_ID_SHIFT) | ||
| 272 | |||
| 273 | #define ENCODER_VT1623_ENUM_ID1 \ | ||
| 274 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 275 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 276 | ENCODER_OBJECT_ID_VT1623 << OBJECT_ID_SHIFT) | ||
| 277 | |||
| 278 | #define ENCODER_HDMI_SI1930_ENUM_ID1 \ | ||
| 279 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 280 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 281 | ENCODER_OBJECT_ID_HDMI_SI1930 << OBJECT_ID_SHIFT) | ||
| 282 | |||
| 283 | #define ENCODER_HDMI_INTERNAL_ENUM_ID1 \ | ||
| 284 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 285 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 286 | ENCODER_OBJECT_ID_HDMI_INTERNAL << OBJECT_ID_SHIFT) | ||
| 287 | |||
| 288 | #define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1 \ | ||
| 289 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 290 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 291 | ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT) | ||
| 292 | |||
| 293 | #define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID2 \ | ||
| 294 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 295 | GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ | ||
| 296 | ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT) | ||
| 297 | |||
| 298 | #define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1 \ | ||
| 299 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 300 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 301 | ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 << OBJECT_ID_SHIFT) | ||
| 302 | |||
| 303 | #define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1 \ | ||
| 304 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 305 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 306 | ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1 << OBJECT_ID_SHIFT) | ||
| 307 | |||
| 308 | #define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1 \ | ||
| 309 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 310 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 311 | ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 << OBJECT_ID_SHIFT) /* Shared with CV/TV and CRT */ | ||
| 312 | |||
| 313 | #define ENCODER_SI178_ENUM_ID1 \ | ||
| 314 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 315 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 316 | ENCODER_OBJECT_ID_SI178 << OBJECT_ID_SHIFT) | ||
| 317 | |||
| 318 | #define ENCODER_MVPU_FPGA_ENUM_ID1 \ | ||
| 319 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 320 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 321 | ENCODER_OBJECT_ID_MVPU_FPGA << OBJECT_ID_SHIFT) | ||
| 322 | |||
| 323 | #define ENCODER_INTERNAL_DDI_ENUM_ID1 \ | ||
| 324 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 325 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 326 | ENCODER_OBJECT_ID_INTERNAL_DDI << OBJECT_ID_SHIFT) | ||
| 327 | |||
| 328 | #define ENCODER_VT1625_ENUM_ID1 \ | ||
| 329 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 330 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 331 | ENCODER_OBJECT_ID_VT1625 << OBJECT_ID_SHIFT) | ||
| 332 | |||
| 333 | #define ENCODER_HDMI_SI1932_ENUM_ID1 \ | ||
| 334 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 335 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 336 | ENCODER_OBJECT_ID_HDMI_SI1932 << OBJECT_ID_SHIFT) | ||
| 337 | |||
| 338 | #define ENCODER_DP_DP501_ENUM_ID1 \ | ||
| 339 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 340 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 341 | ENCODER_OBJECT_ID_DP_DP501 << OBJECT_ID_SHIFT) | ||
| 342 | |||
| 343 | #define ENCODER_DP_AN9801_ENUM_ID1 \ | ||
| 344 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 345 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 346 | ENCODER_OBJECT_ID_DP_AN9801 << OBJECT_ID_SHIFT) | ||
| 347 | |||
| 348 | #define ENCODER_INTERNAL_UNIPHY_ENUM_ID1 \ | ||
| 349 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 350 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 351 | ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT) | ||
| 352 | |||
| 353 | #define ENCODER_INTERNAL_UNIPHY_ENUM_ID2 \ | ||
| 354 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 355 | GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ | ||
| 356 | ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT) | ||
| 357 | |||
| 358 | #define ENCODER_INTERNAL_KLDSCP_LVTMA_ENUM_ID1 \ | ||
| 359 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 360 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 361 | ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA << OBJECT_ID_SHIFT) | ||
| 362 | |||
| 363 | #define ENCODER_INTERNAL_UNIPHY1_ENUM_ID1 \ | ||
| 364 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 365 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 366 | ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT) | ||
| 367 | |||
| 368 | #define ENCODER_INTERNAL_UNIPHY1_ENUM_ID2 \ | ||
| 369 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 370 | GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ | ||
| 371 | ENCODER_OBJECT_ID_INTERNAL_UNIPHY1 << OBJECT_ID_SHIFT) | ||
| 372 | |||
| 373 | #define ENCODER_INTERNAL_UNIPHY2_ENUM_ID1 \ | ||
| 374 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 375 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 376 | ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT) | ||
| 377 | |||
| 378 | #define ENCODER_INTERNAL_UNIPHY2_ENUM_ID2 \ | ||
| 379 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 380 | GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ | ||
| 381 | ENCODER_OBJECT_ID_INTERNAL_UNIPHY2 << OBJECT_ID_SHIFT) | ||
| 382 | |||
| 383 | #define ENCODER_GENERAL_EXTERNAL_DVO_ENUM_ID1 \ | ||
| 384 | (GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\ | ||
| 385 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 386 | ENCODER_OBJECT_ID_GENERAL_EXTERNAL_DVO << OBJECT_ID_SHIFT) | ||
| 387 | |||
| 388 | /****************************************************/ | ||
| 389 | /* Connector Object ID definition - Shared with BIOS */ | ||
| 390 | /****************************************************/ | ||
| 391 | /* | ||
| 392 | #define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID1 0x3101 | ||
| 393 | #define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID1 0x3102 | ||
| 394 | #define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID1 0x3103 | ||
| 395 | #define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 0x3104 | ||
| 396 | #define CONNECTOR_VGA_ENUM_ID1 0x3105 | ||
| 397 | #define CONNECTOR_COMPOSITE_ENUM_ID1 0x3106 | ||
| 398 | #define CONNECTOR_SVIDEO_ENUM_ID1 0x3107 | ||
| 399 | #define CONNECTOR_YPbPr_ENUM_ID1 0x3108 | ||
| 400 | #define CONNECTOR_D_CONNECTORE_ENUM_ID1 0x3109 | ||
| 401 | #define CONNECTOR_9PIN_DIN_ENUM_ID1 0x310A | ||
| 402 | #define CONNECTOR_SCART_ENUM_ID1 0x310B | ||
| 403 | #define CONNECTOR_HDMI_TYPE_A_ENUM_ID1 0x310C | ||
| 404 | #define CONNECTOR_HDMI_TYPE_B_ENUM_ID1 0x310D | ||
| 405 | #define CONNECTOR_LVDS_ENUM_ID1 0x310E | ||
| 406 | #define CONNECTOR_7PIN_DIN_ENUM_ID1 0x310F | ||
| 407 | #define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1 0x3110 | ||
| 408 | */ | ||
| 409 | #define CONNECTOR_LVDS_ENUM_ID1 \ | ||
| 410 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 411 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 412 | CONNECTOR_OBJECT_ID_LVDS << OBJECT_ID_SHIFT) | ||
| 413 | |||
| 414 | #define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID1 \ | ||
| 415 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 416 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 417 | CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT) | ||
| 418 | |||
| 419 | #define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID2 \ | ||
| 420 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 421 | GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ | ||
| 422 | CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT) | ||
| 423 | |||
| 424 | #define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID1 \ | ||
| 425 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 426 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 427 | CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT) | ||
| 428 | |||
| 429 | #define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID2 \ | ||
| 430 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 431 | GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ | ||
| 432 | CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT) | ||
| 433 | |||
| 434 | #define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID1 \ | ||
| 435 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 436 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 437 | CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) | ||
| 438 | |||
| 439 | #define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID2 \ | ||
| 440 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 441 | GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ | ||
| 442 | CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT) | ||
| 443 | |||
| 444 | #define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 \ | ||
| 445 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 446 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 447 | CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT) | ||
| 448 | |||
| 449 | #define CONNECTOR_VGA_ENUM_ID1 \ | ||
| 450 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 451 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 452 | CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT) | ||
| 453 | |||
| 454 | #define CONNECTOR_VGA_ENUM_ID2 \ | ||
| 455 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 456 | GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ | ||
| 457 | CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT) | ||
| 458 | |||
| 459 | #define CONNECTOR_COMPOSITE_ENUM_ID1 \ | ||
| 460 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 461 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 462 | CONNECTOR_OBJECT_ID_COMPOSITE << OBJECT_ID_SHIFT) | ||
| 463 | |||
| 464 | #define CONNECTOR_SVIDEO_ENUM_ID1 \ | ||
| 465 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 466 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 467 | CONNECTOR_OBJECT_ID_SVIDEO << OBJECT_ID_SHIFT) | ||
| 468 | |||
| 469 | #define CONNECTOR_YPbPr_ENUM_ID1 \ | ||
| 470 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 471 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 472 | CONNECTOR_OBJECT_ID_YPbPr << OBJECT_ID_SHIFT) | ||
| 473 | |||
| 474 | #define CONNECTOR_D_CONNECTOR_ENUM_ID1 \ | ||
| 475 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 476 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 477 | CONNECTOR_OBJECT_ID_D_CONNECTOR << OBJECT_ID_SHIFT) | ||
| 478 | |||
| 479 | #define CONNECTOR_9PIN_DIN_ENUM_ID1 \ | ||
| 480 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 481 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 482 | CONNECTOR_OBJECT_ID_9PIN_DIN << OBJECT_ID_SHIFT) | ||
| 483 | |||
| 484 | #define CONNECTOR_SCART_ENUM_ID1 \ | ||
| 485 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 486 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 487 | CONNECTOR_OBJECT_ID_SCART << OBJECT_ID_SHIFT) | ||
| 488 | |||
| 489 | #define CONNECTOR_HDMI_TYPE_A_ENUM_ID1 \ | ||
| 490 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 491 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 492 | CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT) | ||
| 493 | |||
| 494 | #define CONNECTOR_HDMI_TYPE_B_ENUM_ID1 \ | ||
| 495 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 496 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 497 | CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT) | ||
| 498 | |||
| 499 | #define CONNECTOR_7PIN_DIN_ENUM_ID1 \ | ||
| 500 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 501 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 502 | CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT) | ||
| 503 | |||
| 504 | #define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1 \ | ||
| 505 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 506 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 507 | CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT) | ||
| 508 | |||
| 509 | #define CONNECTOR_PCIE_CONNECTOR_ENUM_ID2 \ | ||
| 510 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 511 | GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ | ||
| 512 | CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT) | ||
| 513 | |||
| 514 | #define CONNECTOR_CROSSFIRE_ENUM_ID1 \ | ||
| 515 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 516 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 517 | CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT) | ||
| 518 | |||
| 519 | #define CONNECTOR_CROSSFIRE_ENUM_ID2 \ | ||
| 520 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 521 | GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ | ||
| 522 | CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT) | ||
| 523 | |||
| 524 | #define CONNECTOR_HARDCODE_DVI_ENUM_ID1 \ | ||
| 525 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 526 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 527 | CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT) | ||
| 528 | |||
| 529 | #define CONNECTOR_HARDCODE_DVI_ENUM_ID2 \ | ||
| 530 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 531 | GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ | ||
| 532 | CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT) | ||
| 533 | |||
| 534 | #define CONNECTOR_DISPLAYPORT_ENUM_ID1 \ | ||
| 535 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 536 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 537 | CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) | ||
| 538 | |||
| 539 | #define CONNECTOR_DISPLAYPORT_ENUM_ID2 \ | ||
| 540 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 541 | GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\ | ||
| 542 | CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) | ||
| 543 | |||
| 544 | #define CONNECTOR_DISPLAYPORT_ENUM_ID3 \ | ||
| 545 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 546 | GRAPH_OBJECT_ENUM_ID3 << ENUM_ID_SHIFT |\ | ||
| 547 | CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) | ||
| 548 | |||
| 549 | #define CONNECTOR_DISPLAYPORT_ENUM_ID4 \ | ||
| 550 | (GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\ | ||
| 551 | GRAPH_OBJECT_ENUM_ID4 << ENUM_ID_SHIFT |\ | ||
| 552 | CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT) | ||
| 553 | |||
| 554 | /****************************************************/ | ||
| 555 | /* Router Object ID definition - Shared with BIOS */ | ||
| 556 | /****************************************************/ | ||
| 557 | #define ROUTER_I2C_EXTENDER_CNTL_ENUM_ID1 \ | ||
| 558 | (GRAPH_OBJECT_TYPE_ROUTER << OBJECT_TYPE_SHIFT |\ | ||
| 559 | GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\ | ||
| 560 | ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL << OBJECT_ID_SHIFT) | ||
| 561 | |||
| 562 | /* deleted */ | ||
| 563 | |||
| 564 | /****************************************************/ | ||
| 565 | /* Object Cap definition - Shared with BIOS */ | ||
| 566 | /****************************************************/ | ||
| 567 | #define GRAPHICS_OBJECT_CAP_I2C 0x00000001L | ||
| 568 | #define GRAPHICS_OBJECT_CAP_TABLE_ID 0x00000002L | ||
| 569 | |||
| 570 | #define GRAPHICS_OBJECT_I2CCOMMAND_TABLE_ID 0x01 | ||
| 571 | #define GRAPHICS_OBJECT_HOTPLUGDETECTIONINTERUPT_TABLE_ID 0x02 | ||
| 572 | #define GRAPHICS_OBJECT_ENCODER_OUTPUT_PROTECTION_TABLE_ID 0x03 | ||
| 573 | |||
| 574 | #if defined(_X86_) | ||
| 575 | #pragma pack() | ||
| 576 | #endif | ||
| 577 | |||
| 578 | #endif /*GRAPHICTYPE */ | ||
diff --git a/drivers/gpu/drm/radeon/atom-bits.h b/drivers/gpu/drm/radeon/atom-bits.h new file mode 100644 index 000000000000..e8fae5c77514 --- /dev/null +++ b/drivers/gpu/drm/radeon/atom-bits.h | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, 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: Stanislaw Skowronek | ||
| 23 | */ | ||
| 24 | |||
| 25 | #ifndef ATOM_BITS_H | ||
| 26 | #define ATOM_BITS_H | ||
| 27 | |||
| 28 | static inline uint8_t get_u8(void *bios, int ptr) | ||
| 29 | { | ||
| 30 | return ((unsigned char *)bios)[ptr]; | ||
| 31 | } | ||
| 32 | #define U8(ptr) get_u8(ctx->ctx->bios, (ptr)) | ||
| 33 | #define CU8(ptr) get_u8(ctx->bios, (ptr)) | ||
| 34 | static inline uint16_t get_u16(void *bios, int ptr) | ||
| 35 | { | ||
| 36 | return get_u8(bios ,ptr)|(((uint16_t)get_u8(bios, ptr+1))<<8); | ||
| 37 | } | ||
| 38 | #define U16(ptr) get_u16(ctx->ctx->bios, (ptr)) | ||
| 39 | #define CU16(ptr) get_u16(ctx->bios, (ptr)) | ||
| 40 | static inline uint32_t get_u32(void *bios, int ptr) | ||
| 41 | { | ||
| 42 | return get_u16(bios, ptr)|(((uint32_t)get_u16(bios, ptr+2))<<16); | ||
| 43 | } | ||
| 44 | #define U32(ptr) get_u32(ctx->ctx->bios, (ptr)) | ||
| 45 | #define CU32(ptr) get_u32(ctx->bios, (ptr)) | ||
| 46 | #define CSTR(ptr) (((char *)(ctx->bios))+(ptr)) | ||
| 47 | |||
| 48 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/atom-names.h b/drivers/gpu/drm/radeon/atom-names.h new file mode 100644 index 000000000000..6f907a5ffa5f --- /dev/null +++ b/drivers/gpu/drm/radeon/atom-names.h | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, 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: Stanislaw Skowronek | ||
| 23 | */ | ||
| 24 | |||
| 25 | #ifndef ATOM_NAMES_H | ||
| 26 | #define ATOM_NAMES_H | ||
| 27 | |||
| 28 | #include "atom.h" | ||
| 29 | |||
| 30 | #ifdef ATOM_DEBUG | ||
| 31 | |||
| 32 | #define ATOM_OP_NAMES_CNT 123 | ||
| 33 | static char *atom_op_names[ATOM_OP_NAMES_CNT] = { | ||
| 34 | "RESERVED", "MOVE_REG", "MOVE_PS", "MOVE_WS", "MOVE_FB", "MOVE_PLL", | ||
| 35 | "MOVE_MC", "AND_REG", "AND_PS", "AND_WS", "AND_FB", "AND_PLL", "AND_MC", | ||
| 36 | "OR_REG", "OR_PS", "OR_WS", "OR_FB", "OR_PLL", "OR_MC", "SHIFT_LEFT_REG", | ||
| 37 | "SHIFT_LEFT_PS", "SHIFT_LEFT_WS", "SHIFT_LEFT_FB", "SHIFT_LEFT_PLL", | ||
| 38 | "SHIFT_LEFT_MC", "SHIFT_RIGHT_REG", "SHIFT_RIGHT_PS", "SHIFT_RIGHT_WS", | ||
| 39 | "SHIFT_RIGHT_FB", "SHIFT_RIGHT_PLL", "SHIFT_RIGHT_MC", "MUL_REG", | ||
| 40 | "MUL_PS", "MUL_WS", "MUL_FB", "MUL_PLL", "MUL_MC", "DIV_REG", "DIV_PS", | ||
| 41 | "DIV_WS", "DIV_FB", "DIV_PLL", "DIV_MC", "ADD_REG", "ADD_PS", "ADD_WS", | ||
| 42 | "ADD_FB", "ADD_PLL", "ADD_MC", "SUB_REG", "SUB_PS", "SUB_WS", "SUB_FB", | ||
| 43 | "SUB_PLL", "SUB_MC", "SET_ATI_PORT", "SET_PCI_PORT", "SET_SYS_IO_PORT", | ||
| 44 | "SET_REG_BLOCK", "SET_FB_BASE", "COMPARE_REG", "COMPARE_PS", | ||
| 45 | "COMPARE_WS", "COMPARE_FB", "COMPARE_PLL", "COMPARE_MC", "SWITCH", | ||
| 46 | "JUMP", "JUMP_EQUAL", "JUMP_BELOW", "JUMP_ABOVE", "JUMP_BELOW_OR_EQUAL", | ||
| 47 | "JUMP_ABOVE_OR_EQUAL", "JUMP_NOT_EQUAL", "TEST_REG", "TEST_PS", "TEST_WS", | ||
| 48 | "TEST_FB", "TEST_PLL", "TEST_MC", "DELAY_MILLISEC", "DELAY_MICROSEC", | ||
| 49 | "CALL_TABLE", "REPEAT", "CLEAR_REG", "CLEAR_PS", "CLEAR_WS", "CLEAR_FB", | ||
| 50 | "CLEAR_PLL", "CLEAR_MC", "NOP", "EOT", "MASK_REG", "MASK_PS", "MASK_WS", | ||
| 51 | "MASK_FB", "MASK_PLL", "MASK_MC", "POST_CARD", "BEEP", "SAVE_REG", | ||
| 52 | "RESTORE_REG", "SET_DATA_BLOCK", "XOR_REG", "XOR_PS", "XOR_WS", "XOR_FB", | ||
| 53 | "XOR_PLL", "XOR_MC", "SHL_REG", "SHL_PS", "SHL_WS", "SHL_FB", "SHL_PLL", | ||
| 54 | "SHL_MC", "SHR_REG", "SHR_PS", "SHR_WS", "SHR_FB", "SHR_PLL", "SHR_MC", | ||
| 55 | "DEBUG", "CTB_DS", | ||
| 56 | }; | ||
| 57 | |||
| 58 | #define ATOM_TABLE_NAMES_CNT 74 | ||
| 59 | static char *atom_table_names[ATOM_TABLE_NAMES_CNT] = { | ||
| 60 | "ASIC_Init", "GetDisplaySurfaceSize", "ASIC_RegistersInit", | ||
| 61 | "VRAM_BlockVenderDetection", "SetClocksRatio", "MemoryControllerInit", | ||
| 62 | "GPIO_PinInit", "MemoryParamAdjust", "DVOEncoderControl", | ||
| 63 | "GPIOPinControl", "SetEngineClock", "SetMemoryClock", "SetPixelClock", | ||
| 64 | "DynamicClockGating", "ResetMemoryDLL", "ResetMemoryDevice", | ||
| 65 | "MemoryPLLInit", "EnableMemorySelfRefresh", "AdjustMemoryController", | ||
| 66 | "EnableASIC_StaticPwrMgt", "ASIC_StaticPwrMgtStatusChange", | ||
| 67 | "DAC_LoadDetection", "TMDS2EncoderControl", "LCD1OutputControl", | ||
| 68 | "DAC1EncoderControl", "DAC2EncoderControl", "DVOOutputControl", | ||
| 69 | "CV1OutputControl", "SetCRTC_DPM_State", "TVEncoderControl", | ||
| 70 | "TMDS1EncoderControl", "LVDSEncoderControl", "TV1OutputControl", | ||
| 71 | "EnableScaler", "BlankCRTC", "EnableCRTC", "GetPixelClock", | ||
| 72 | "EnableVGA_Render", "EnableVGA_Access", "SetCRTC_Timing", | ||
| 73 | "SetCRTC_OverScan", "SetCRTC_Replication", "SelectCRTC_Source", | ||
| 74 | "EnableGraphSurfaces", "UpdateCRTC_DoubleBufferRegisters", | ||
| 75 | "LUT_AutoFill", "EnableHW_IconCursor", "GetMemoryClock", | ||
| 76 | "GetEngineClock", "SetCRTC_UsingDTDTiming", "TVBootUpStdPinDetection", | ||
| 77 | "DFP2OutputControl", "VRAM_BlockDetectionByStrap", "MemoryCleanUp", | ||
| 78 | "ReadEDIDFromHWAssistedI2C", "WriteOneByteToHWAssistedI2C", | ||
| 79 | "ReadHWAssistedI2CStatus", "SpeedFanControl", "PowerConnectorDetection", | ||
| 80 | "MC_Synchronization", "ComputeMemoryEnginePLL", "MemoryRefreshConversion", | ||
| 81 | "VRAM_GetCurrentInfoBlock", "DynamicMemorySettings", "MemoryTraining", | ||
| 82 | "EnableLVDS_SS", "DFP1OutputControl", "SetVoltage", "CRT1OutputControl", | ||
| 83 | "CRT2OutputControl", "SetupHWAssistedI2CStatus", "ClockSource", | ||
| 84 | "MemoryDeviceInit", "EnableYUV", | ||
| 85 | }; | ||
| 86 | |||
| 87 | #define ATOM_IO_NAMES_CNT 5 | ||
| 88 | static char *atom_io_names[ATOM_IO_NAMES_CNT] = { | ||
| 89 | "MM", "PLL", "MC", "PCIE", "PCIE PORT", | ||
| 90 | }; | ||
| 91 | |||
| 92 | #else | ||
| 93 | |||
| 94 | #define ATOM_OP_NAMES_CNT 0 | ||
| 95 | #define ATOM_TABLE_NAMES_CNT 0 | ||
| 96 | #define ATOM_IO_NAMES_CNT 0 | ||
| 97 | |||
| 98 | #endif | ||
| 99 | |||
| 100 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/atom-types.h b/drivers/gpu/drm/radeon/atom-types.h new file mode 100644 index 000000000000..1125b866cdb0 --- /dev/null +++ b/drivers/gpu/drm/radeon/atom-types.h | |||
| @@ -0,0 +1,42 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 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: Dave Airlie | ||
| 23 | */ | ||
| 24 | |||
| 25 | #ifndef ATOM_TYPES_H | ||
| 26 | #define ATOM_TYPES_H | ||
| 27 | |||
| 28 | /* sync atom types to kernel types */ | ||
| 29 | |||
| 30 | typedef uint16_t USHORT; | ||
| 31 | typedef uint32_t ULONG; | ||
| 32 | typedef uint8_t UCHAR; | ||
| 33 | |||
| 34 | |||
| 35 | #ifndef ATOM_BIG_ENDIAN | ||
| 36 | #if defined(__BIG_ENDIAN) | ||
| 37 | #define ATOM_BIG_ENDIAN 1 | ||
| 38 | #else | ||
| 39 | #define ATOM_BIG_ENDIAN 0 | ||
| 40 | #endif | ||
| 41 | #endif | ||
| 42 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c new file mode 100644 index 000000000000..901befe03da2 --- /dev/null +++ b/drivers/gpu/drm/radeon/atom.c | |||
| @@ -0,0 +1,1215 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, 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: Stanislaw Skowronek | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/sched.h> | ||
| 27 | |||
| 28 | #define ATOM_DEBUG | ||
| 29 | |||
| 30 | #include "atom.h" | ||
| 31 | #include "atom-names.h" | ||
| 32 | #include "atom-bits.h" | ||
| 33 | |||
| 34 | #define ATOM_COND_ABOVE 0 | ||
| 35 | #define ATOM_COND_ABOVEOREQUAL 1 | ||
| 36 | #define ATOM_COND_ALWAYS 2 | ||
| 37 | #define ATOM_COND_BELOW 3 | ||
| 38 | #define ATOM_COND_BELOWOREQUAL 4 | ||
| 39 | #define ATOM_COND_EQUAL 5 | ||
| 40 | #define ATOM_COND_NOTEQUAL 6 | ||
| 41 | |||
| 42 | #define ATOM_PORT_ATI 0 | ||
| 43 | #define ATOM_PORT_PCI 1 | ||
| 44 | #define ATOM_PORT_SYSIO 2 | ||
| 45 | |||
| 46 | #define ATOM_UNIT_MICROSEC 0 | ||
| 47 | #define ATOM_UNIT_MILLISEC 1 | ||
| 48 | |||
| 49 | #define PLL_INDEX 2 | ||
| 50 | #define PLL_DATA 3 | ||
| 51 | |||
| 52 | typedef struct { | ||
| 53 | struct atom_context *ctx; | ||
| 54 | |||
| 55 | uint32_t *ps, *ws; | ||
| 56 | int ps_shift; | ||
| 57 | uint16_t start; | ||
| 58 | } atom_exec_context; | ||
| 59 | |||
| 60 | int atom_debug = 0; | ||
| 61 | void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params); | ||
| 62 | |||
| 63 | static uint32_t atom_arg_mask[8] = | ||
| 64 | { 0xFFFFFFFF, 0xFFFF, 0xFFFF00, 0xFFFF0000, 0xFF, 0xFF00, 0xFF0000, | ||
| 65 | 0xFF000000 }; | ||
| 66 | static int atom_arg_shift[8] = { 0, 0, 8, 16, 0, 8, 16, 24 }; | ||
| 67 | |||
| 68 | static int atom_dst_to_src[8][4] = { | ||
| 69 | /* translate destination alignment field to the source alignment encoding */ | ||
| 70 | {0, 0, 0, 0}, | ||
| 71 | {1, 2, 3, 0}, | ||
| 72 | {1, 2, 3, 0}, | ||
| 73 | {1, 2, 3, 0}, | ||
| 74 | {4, 5, 6, 7}, | ||
| 75 | {4, 5, 6, 7}, | ||
| 76 | {4, 5, 6, 7}, | ||
| 77 | {4, 5, 6, 7}, | ||
| 78 | }; | ||
| 79 | static int atom_def_dst[8] = { 0, 0, 1, 2, 0, 1, 2, 3 }; | ||
| 80 | |||
| 81 | static int debug_depth = 0; | ||
| 82 | #ifdef ATOM_DEBUG | ||
| 83 | static void debug_print_spaces(int n) | ||
| 84 | { | ||
| 85 | while (n--) | ||
| 86 | printk(" "); | ||
| 87 | } | ||
| 88 | |||
| 89 | #define DEBUG(...) do if (atom_debug) { printk(KERN_DEBUG __VA_ARGS__); } while (0) | ||
| 90 | #define SDEBUG(...) do if (atom_debug) { printk(KERN_DEBUG); debug_print_spaces(debug_depth); printk(__VA_ARGS__); } while (0) | ||
| 91 | #else | ||
| 92 | #define DEBUG(...) do { } while (0) | ||
| 93 | #define SDEBUG(...) do { } while (0) | ||
| 94 | #endif | ||
| 95 | |||
| 96 | static uint32_t atom_iio_execute(struct atom_context *ctx, int base, | ||
| 97 | uint32_t index, uint32_t data) | ||
| 98 | { | ||
| 99 | uint32_t temp = 0xCDCDCDCD; | ||
| 100 | while (1) | ||
| 101 | switch (CU8(base)) { | ||
| 102 | case ATOM_IIO_NOP: | ||
| 103 | base++; | ||
| 104 | break; | ||
| 105 | case ATOM_IIO_READ: | ||
| 106 | temp = ctx->card->reg_read(ctx->card, CU16(base + 1)); | ||
| 107 | base += 3; | ||
| 108 | break; | ||
| 109 | case ATOM_IIO_WRITE: | ||
| 110 | ctx->card->reg_write(ctx->card, CU16(base + 1), temp); | ||
| 111 | base += 3; | ||
| 112 | break; | ||
| 113 | case ATOM_IIO_CLEAR: | ||
| 114 | temp &= | ||
| 115 | ~((0xFFFFFFFF >> (32 - CU8(base + 1))) << | ||
| 116 | CU8(base + 2)); | ||
| 117 | base += 3; | ||
| 118 | break; | ||
| 119 | case ATOM_IIO_SET: | ||
| 120 | temp |= | ||
| 121 | (0xFFFFFFFF >> (32 - CU8(base + 1))) << CU8(base + | ||
| 122 | 2); | ||
| 123 | base += 3; | ||
| 124 | break; | ||
| 125 | case ATOM_IIO_MOVE_INDEX: | ||
| 126 | temp &= | ||
| 127 | ~((0xFFFFFFFF >> (32 - CU8(base + 1))) << | ||
| 128 | CU8(base + 2)); | ||
| 129 | temp |= | ||
| 130 | ((index >> CU8(base + 2)) & | ||
| 131 | (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base + | ||
| 132 | 3); | ||
| 133 | base += 4; | ||
| 134 | break; | ||
| 135 | case ATOM_IIO_MOVE_DATA: | ||
| 136 | temp &= | ||
| 137 | ~((0xFFFFFFFF >> (32 - CU8(base + 1))) << | ||
| 138 | CU8(base + 2)); | ||
| 139 | temp |= | ||
| 140 | ((data >> CU8(base + 2)) & | ||
| 141 | (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base + | ||
| 142 | 3); | ||
| 143 | base += 4; | ||
| 144 | break; | ||
| 145 | case ATOM_IIO_MOVE_ATTR: | ||
| 146 | temp &= | ||
| 147 | ~((0xFFFFFFFF >> (32 - CU8(base + 1))) << | ||
| 148 | CU8(base + 2)); | ||
| 149 | temp |= | ||
| 150 | ((ctx-> | ||
| 151 | io_attr >> CU8(base + 2)) & (0xFFFFFFFF >> (32 - | ||
| 152 | CU8 | ||
| 153 | (base | ||
| 154 | + | ||
| 155 | 1)))) | ||
| 156 | << CU8(base + 3); | ||
| 157 | base += 4; | ||
| 158 | break; | ||
| 159 | case ATOM_IIO_END: | ||
| 160 | return temp; | ||
| 161 | default: | ||
| 162 | printk(KERN_INFO "Unknown IIO opcode.\n"); | ||
| 163 | return 0; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr, | ||
| 168 | int *ptr, uint32_t *saved, int print) | ||
| 169 | { | ||
| 170 | uint32_t idx, val = 0xCDCDCDCD, align, arg; | ||
| 171 | struct atom_context *gctx = ctx->ctx; | ||
| 172 | arg = attr & 7; | ||
| 173 | align = (attr >> 3) & 7; | ||
| 174 | switch (arg) { | ||
| 175 | case ATOM_ARG_REG: | ||
| 176 | idx = U16(*ptr); | ||
| 177 | (*ptr) += 2; | ||
| 178 | if (print) | ||
| 179 | DEBUG("REG[0x%04X]", idx); | ||
| 180 | idx += gctx->reg_block; | ||
| 181 | switch (gctx->io_mode) { | ||
| 182 | case ATOM_IO_MM: | ||
| 183 | val = gctx->card->reg_read(gctx->card, idx); | ||
| 184 | break; | ||
| 185 | case ATOM_IO_PCI: | ||
| 186 | printk(KERN_INFO | ||
| 187 | "PCI registers are not implemented.\n"); | ||
| 188 | return 0; | ||
| 189 | case ATOM_IO_SYSIO: | ||
| 190 | printk(KERN_INFO | ||
| 191 | "SYSIO registers are not implemented.\n"); | ||
| 192 | return 0; | ||
| 193 | default: | ||
| 194 | if (!(gctx->io_mode & 0x80)) { | ||
| 195 | printk(KERN_INFO "Bad IO mode.\n"); | ||
| 196 | return 0; | ||
| 197 | } | ||
| 198 | if (!gctx->iio[gctx->io_mode & 0x7F]) { | ||
| 199 | printk(KERN_INFO | ||
| 200 | "Undefined indirect IO read method %d.\n", | ||
| 201 | gctx->io_mode & 0x7F); | ||
| 202 | return 0; | ||
| 203 | } | ||
| 204 | val = | ||
| 205 | atom_iio_execute(gctx, | ||
| 206 | gctx->iio[gctx->io_mode & 0x7F], | ||
| 207 | idx, 0); | ||
| 208 | } | ||
| 209 | break; | ||
| 210 | case ATOM_ARG_PS: | ||
| 211 | idx = U8(*ptr); | ||
| 212 | (*ptr)++; | ||
| 213 | val = le32_to_cpu(ctx->ps[idx]); | ||
| 214 | if (print) | ||
| 215 | DEBUG("PS[0x%02X,0x%04X]", idx, val); | ||
| 216 | break; | ||
| 217 | case ATOM_ARG_WS: | ||
| 218 | idx = U8(*ptr); | ||
| 219 | (*ptr)++; | ||
| 220 | if (print) | ||
| 221 | DEBUG("WS[0x%02X]", idx); | ||
| 222 | switch (idx) { | ||
| 223 | case ATOM_WS_QUOTIENT: | ||
| 224 | val = gctx->divmul[0]; | ||
| 225 | break; | ||
| 226 | case ATOM_WS_REMAINDER: | ||
| 227 | val = gctx->divmul[1]; | ||
| 228 | break; | ||
| 229 | case ATOM_WS_DATAPTR: | ||
| 230 | val = gctx->data_block; | ||
| 231 | break; | ||
| 232 | case ATOM_WS_SHIFT: | ||
| 233 | val = gctx->shift; | ||
| 234 | break; | ||
| 235 | case ATOM_WS_OR_MASK: | ||
| 236 | val = 1 << gctx->shift; | ||
| 237 | break; | ||
| 238 | case ATOM_WS_AND_MASK: | ||
| 239 | val = ~(1 << gctx->shift); | ||
| 240 | break; | ||
| 241 | case ATOM_WS_FB_WINDOW: | ||
| 242 | val = gctx->fb_base; | ||
| 243 | break; | ||
| 244 | case ATOM_WS_ATTRIBUTES: | ||
| 245 | val = gctx->io_attr; | ||
| 246 | break; | ||
| 247 | default: | ||
| 248 | val = ctx->ws[idx]; | ||
| 249 | } | ||
| 250 | break; | ||
| 251 | case ATOM_ARG_ID: | ||
| 252 | idx = U16(*ptr); | ||
| 253 | (*ptr) += 2; | ||
| 254 | if (print) { | ||
| 255 | if (gctx->data_block) | ||
| 256 | DEBUG("ID[0x%04X+%04X]", idx, gctx->data_block); | ||
| 257 | else | ||
| 258 | DEBUG("ID[0x%04X]", idx); | ||
| 259 | } | ||
| 260 | val = U32(idx + gctx->data_block); | ||
| 261 | break; | ||
| 262 | case ATOM_ARG_FB: | ||
| 263 | idx = U8(*ptr); | ||
| 264 | (*ptr)++; | ||
| 265 | if (print) | ||
| 266 | DEBUG("FB[0x%02X]", idx); | ||
| 267 | printk(KERN_INFO "FB access is not implemented.\n"); | ||
| 268 | return 0; | ||
| 269 | case ATOM_ARG_IMM: | ||
| 270 | switch (align) { | ||
| 271 | case ATOM_SRC_DWORD: | ||
| 272 | val = U32(*ptr); | ||
| 273 | (*ptr) += 4; | ||
| 274 | if (print) | ||
| 275 | DEBUG("IMM 0x%08X\n", val); | ||
| 276 | return val; | ||
| 277 | case ATOM_SRC_WORD0: | ||
| 278 | case ATOM_SRC_WORD8: | ||
| 279 | case ATOM_SRC_WORD16: | ||
| 280 | val = U16(*ptr); | ||
| 281 | (*ptr) += 2; | ||
| 282 | if (print) | ||
| 283 | DEBUG("IMM 0x%04X\n", val); | ||
| 284 | return val; | ||
| 285 | case ATOM_SRC_BYTE0: | ||
| 286 | case ATOM_SRC_BYTE8: | ||
| 287 | case ATOM_SRC_BYTE16: | ||
| 288 | case ATOM_SRC_BYTE24: | ||
| 289 | val = U8(*ptr); | ||
| 290 | (*ptr)++; | ||
| 291 | if (print) | ||
| 292 | DEBUG("IMM 0x%02X\n", val); | ||
| 293 | return val; | ||
| 294 | } | ||
| 295 | return 0; | ||
| 296 | case ATOM_ARG_PLL: | ||
| 297 | idx = U8(*ptr); | ||
| 298 | (*ptr)++; | ||
| 299 | if (print) | ||
| 300 | DEBUG("PLL[0x%02X]", idx); | ||
| 301 | val = gctx->card->pll_read(gctx->card, idx); | ||
| 302 | break; | ||
| 303 | case ATOM_ARG_MC: | ||
| 304 | idx = U8(*ptr); | ||
| 305 | (*ptr)++; | ||
| 306 | if (print) | ||
| 307 | DEBUG("MC[0x%02X]", idx); | ||
| 308 | val = gctx->card->mc_read(gctx->card, idx); | ||
| 309 | break; | ||
| 310 | } | ||
| 311 | if (saved) | ||
| 312 | *saved = val; | ||
| 313 | val &= atom_arg_mask[align]; | ||
| 314 | val >>= atom_arg_shift[align]; | ||
| 315 | if (print) | ||
| 316 | switch (align) { | ||
| 317 | case ATOM_SRC_DWORD: | ||
| 318 | DEBUG(".[31:0] -> 0x%08X\n", val); | ||
| 319 | break; | ||
| 320 | case ATOM_SRC_WORD0: | ||
| 321 | DEBUG(".[15:0] -> 0x%04X\n", val); | ||
| 322 | break; | ||
| 323 | case ATOM_SRC_WORD8: | ||
| 324 | DEBUG(".[23:8] -> 0x%04X\n", val); | ||
| 325 | break; | ||
| 326 | case ATOM_SRC_WORD16: | ||
| 327 | DEBUG(".[31:16] -> 0x%04X\n", val); | ||
| 328 | break; | ||
| 329 | case ATOM_SRC_BYTE0: | ||
| 330 | DEBUG(".[7:0] -> 0x%02X\n", val); | ||
| 331 | break; | ||
| 332 | case ATOM_SRC_BYTE8: | ||
| 333 | DEBUG(".[15:8] -> 0x%02X\n", val); | ||
| 334 | break; | ||
| 335 | case ATOM_SRC_BYTE16: | ||
| 336 | DEBUG(".[23:16] -> 0x%02X\n", val); | ||
| 337 | break; | ||
| 338 | case ATOM_SRC_BYTE24: | ||
| 339 | DEBUG(".[31:24] -> 0x%02X\n", val); | ||
| 340 | break; | ||
| 341 | } | ||
| 342 | return val; | ||
| 343 | } | ||
| 344 | |||
| 345 | static void atom_skip_src_int(atom_exec_context *ctx, uint8_t attr, int *ptr) | ||
| 346 | { | ||
| 347 | uint32_t align = (attr >> 3) & 7, arg = attr & 7; | ||
| 348 | switch (arg) { | ||
| 349 | case ATOM_ARG_REG: | ||
| 350 | case ATOM_ARG_ID: | ||
| 351 | (*ptr) += 2; | ||
| 352 | break; | ||
| 353 | case ATOM_ARG_PLL: | ||
| 354 | case ATOM_ARG_MC: | ||
| 355 | case ATOM_ARG_PS: | ||
| 356 | case ATOM_ARG_WS: | ||
| 357 | case ATOM_ARG_FB: | ||
| 358 | (*ptr)++; | ||
| 359 | break; | ||
| 360 | case ATOM_ARG_IMM: | ||
| 361 | switch (align) { | ||
| 362 | case ATOM_SRC_DWORD: | ||
| 363 | (*ptr) += 4; | ||
| 364 | return; | ||
| 365 | case ATOM_SRC_WORD0: | ||
| 366 | case ATOM_SRC_WORD8: | ||
| 367 | case ATOM_SRC_WORD16: | ||
| 368 | (*ptr) += 2; | ||
| 369 | return; | ||
| 370 | case ATOM_SRC_BYTE0: | ||
| 371 | case ATOM_SRC_BYTE8: | ||
| 372 | case ATOM_SRC_BYTE16: | ||
| 373 | case ATOM_SRC_BYTE24: | ||
| 374 | (*ptr)++; | ||
| 375 | return; | ||
| 376 | } | ||
| 377 | return; | ||
| 378 | } | ||
| 379 | } | ||
| 380 | |||
| 381 | static uint32_t atom_get_src(atom_exec_context *ctx, uint8_t attr, int *ptr) | ||
| 382 | { | ||
| 383 | return atom_get_src_int(ctx, attr, ptr, NULL, 1); | ||
| 384 | } | ||
| 385 | |||
| 386 | static uint32_t atom_get_dst(atom_exec_context *ctx, int arg, uint8_t attr, | ||
| 387 | int *ptr, uint32_t *saved, int print) | ||
| 388 | { | ||
| 389 | return atom_get_src_int(ctx, | ||
| 390 | arg | atom_dst_to_src[(attr >> 3) & | ||
| 391 | 7][(attr >> 6) & 3] << 3, | ||
| 392 | ptr, saved, print); | ||
| 393 | } | ||
| 394 | |||
| 395 | static void atom_skip_dst(atom_exec_context *ctx, int arg, uint8_t attr, int *ptr) | ||
| 396 | { | ||
| 397 | atom_skip_src_int(ctx, | ||
| 398 | arg | atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & | ||
| 399 | 3] << 3, ptr); | ||
| 400 | } | ||
| 401 | |||
| 402 | static void atom_put_dst(atom_exec_context *ctx, int arg, uint8_t attr, | ||
| 403 | int *ptr, uint32_t val, uint32_t saved) | ||
| 404 | { | ||
| 405 | uint32_t align = | ||
| 406 | atom_dst_to_src[(attr >> 3) & 7][(attr >> 6) & 3], old_val = | ||
| 407 | val, idx; | ||
| 408 | struct atom_context *gctx = ctx->ctx; | ||
| 409 | old_val &= atom_arg_mask[align] >> atom_arg_shift[align]; | ||
| 410 | val <<= atom_arg_shift[align]; | ||
| 411 | val &= atom_arg_mask[align]; | ||
| 412 | saved &= ~atom_arg_mask[align]; | ||
| 413 | val |= saved; | ||
| 414 | switch (arg) { | ||
| 415 | case ATOM_ARG_REG: | ||
| 416 | idx = U16(*ptr); | ||
| 417 | (*ptr) += 2; | ||
| 418 | DEBUG("REG[0x%04X]", idx); | ||
| 419 | idx += gctx->reg_block; | ||
| 420 | switch (gctx->io_mode) { | ||
| 421 | case ATOM_IO_MM: | ||
| 422 | if (idx == 0) | ||
| 423 | gctx->card->reg_write(gctx->card, idx, | ||
| 424 | val << 2); | ||
| 425 | else | ||
| 426 | gctx->card->reg_write(gctx->card, idx, val); | ||
| 427 | break; | ||
| 428 | case ATOM_IO_PCI: | ||
| 429 | printk(KERN_INFO | ||
| 430 | "PCI registers are not implemented.\n"); | ||
| 431 | return; | ||
| 432 | case ATOM_IO_SYSIO: | ||
| 433 | printk(KERN_INFO | ||
| 434 | "SYSIO registers are not implemented.\n"); | ||
| 435 | return; | ||
| 436 | default: | ||
| 437 | if (!(gctx->io_mode & 0x80)) { | ||
| 438 | printk(KERN_INFO "Bad IO mode.\n"); | ||
| 439 | return; | ||
| 440 | } | ||
| 441 | if (!gctx->iio[gctx->io_mode & 0xFF]) { | ||
| 442 | printk(KERN_INFO | ||
| 443 | "Undefined indirect IO write method %d.\n", | ||
| 444 | gctx->io_mode & 0x7F); | ||
| 445 | return; | ||
| 446 | } | ||
| 447 | atom_iio_execute(gctx, gctx->iio[gctx->io_mode & 0xFF], | ||
| 448 | idx, val); | ||
| 449 | } | ||
| 450 | break; | ||
| 451 | case ATOM_ARG_PS: | ||
| 452 | idx = U8(*ptr); | ||
| 453 | (*ptr)++; | ||
| 454 | DEBUG("PS[0x%02X]", idx); | ||
| 455 | ctx->ps[idx] = cpu_to_le32(val); | ||
| 456 | break; | ||
| 457 | case ATOM_ARG_WS: | ||
| 458 | idx = U8(*ptr); | ||
| 459 | (*ptr)++; | ||
| 460 | DEBUG("WS[0x%02X]", idx); | ||
| 461 | switch (idx) { | ||
| 462 | case ATOM_WS_QUOTIENT: | ||
| 463 | gctx->divmul[0] = val; | ||
| 464 | break; | ||
| 465 | case ATOM_WS_REMAINDER: | ||
| 466 | gctx->divmul[1] = val; | ||
| 467 | break; | ||
| 468 | case ATOM_WS_DATAPTR: | ||
| 469 | gctx->data_block = val; | ||
| 470 | break; | ||
| 471 | case ATOM_WS_SHIFT: | ||
| 472 | gctx->shift = val; | ||
| 473 | break; | ||
| 474 | case ATOM_WS_OR_MASK: | ||
| 475 | case ATOM_WS_AND_MASK: | ||
| 476 | break; | ||
| 477 | case ATOM_WS_FB_WINDOW: | ||
| 478 | gctx->fb_base = val; | ||
| 479 | break; | ||
| 480 | case ATOM_WS_ATTRIBUTES: | ||
| 481 | gctx->io_attr = val; | ||
| 482 | break; | ||
| 483 | default: | ||
| 484 | ctx->ws[idx] = val; | ||
| 485 | } | ||
| 486 | break; | ||
| 487 | case ATOM_ARG_FB: | ||
| 488 | idx = U8(*ptr); | ||
| 489 | (*ptr)++; | ||
| 490 | DEBUG("FB[0x%02X]", idx); | ||
| 491 | printk(KERN_INFO "FB access is not implemented.\n"); | ||
| 492 | return; | ||
| 493 | case ATOM_ARG_PLL: | ||
| 494 | idx = U8(*ptr); | ||
| 495 | (*ptr)++; | ||
| 496 | DEBUG("PLL[0x%02X]", idx); | ||
| 497 | gctx->card->pll_write(gctx->card, idx, val); | ||
| 498 | break; | ||
| 499 | case ATOM_ARG_MC: | ||
| 500 | idx = U8(*ptr); | ||
| 501 | (*ptr)++; | ||
| 502 | DEBUG("MC[0x%02X]", idx); | ||
| 503 | gctx->card->mc_write(gctx->card, idx, val); | ||
| 504 | return; | ||
| 505 | } | ||
| 506 | switch (align) { | ||
| 507 | case ATOM_SRC_DWORD: | ||
| 508 | DEBUG(".[31:0] <- 0x%08X\n", old_val); | ||
| 509 | break; | ||
| 510 | case ATOM_SRC_WORD0: | ||
| 511 | DEBUG(".[15:0] <- 0x%04X\n", old_val); | ||
| 512 | break; | ||
| 513 | case ATOM_SRC_WORD8: | ||
| 514 | DEBUG(".[23:8] <- 0x%04X\n", old_val); | ||
| 515 | break; | ||
| 516 | case ATOM_SRC_WORD16: | ||
| 517 | DEBUG(".[31:16] <- 0x%04X\n", old_val); | ||
| 518 | break; | ||
| 519 | case ATOM_SRC_BYTE0: | ||
| 520 | DEBUG(".[7:0] <- 0x%02X\n", old_val); | ||
| 521 | break; | ||
| 522 | case ATOM_SRC_BYTE8: | ||
| 523 | DEBUG(".[15:8] <- 0x%02X\n", old_val); | ||
| 524 | break; | ||
| 525 | case ATOM_SRC_BYTE16: | ||
| 526 | DEBUG(".[23:16] <- 0x%02X\n", old_val); | ||
| 527 | break; | ||
| 528 | case ATOM_SRC_BYTE24: | ||
| 529 | DEBUG(".[31:24] <- 0x%02X\n", old_val); | ||
| 530 | break; | ||
| 531 | } | ||
| 532 | } | ||
| 533 | |||
| 534 | static void atom_op_add(atom_exec_context *ctx, int *ptr, int arg) | ||
| 535 | { | ||
| 536 | uint8_t attr = U8((*ptr)++); | ||
| 537 | uint32_t dst, src, saved; | ||
| 538 | int dptr = *ptr; | ||
| 539 | SDEBUG(" dst: "); | ||
| 540 | dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); | ||
| 541 | SDEBUG(" src: "); | ||
| 542 | src = atom_get_src(ctx, attr, ptr); | ||
| 543 | dst += src; | ||
| 544 | SDEBUG(" dst: "); | ||
| 545 | atom_put_dst(ctx, arg, attr, &dptr, dst, saved); | ||
| 546 | } | ||
| 547 | |||
| 548 | static void atom_op_and(atom_exec_context *ctx, int *ptr, int arg) | ||
| 549 | { | ||
| 550 | uint8_t attr = U8((*ptr)++); | ||
| 551 | uint32_t dst, src, saved; | ||
| 552 | int dptr = *ptr; | ||
| 553 | SDEBUG(" dst: "); | ||
| 554 | dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); | ||
| 555 | SDEBUG(" src: "); | ||
| 556 | src = atom_get_src(ctx, attr, ptr); | ||
| 557 | dst &= src; | ||
| 558 | SDEBUG(" dst: "); | ||
| 559 | atom_put_dst(ctx, arg, attr, &dptr, dst, saved); | ||
| 560 | } | ||
| 561 | |||
| 562 | static void atom_op_beep(atom_exec_context *ctx, int *ptr, int arg) | ||
| 563 | { | ||
| 564 | printk("ATOM BIOS beeped!\n"); | ||
| 565 | } | ||
| 566 | |||
| 567 | static void atom_op_calltable(atom_exec_context *ctx, int *ptr, int arg) | ||
| 568 | { | ||
| 569 | int idx = U8((*ptr)++); | ||
| 570 | if (idx < ATOM_TABLE_NAMES_CNT) | ||
| 571 | SDEBUG(" table: %d (%s)\n", idx, atom_table_names[idx]); | ||
| 572 | else | ||
| 573 | SDEBUG(" table: %d\n", idx); | ||
| 574 | if (U16(ctx->ctx->cmd_table + 4 + 2 * idx)) | ||
| 575 | atom_execute_table(ctx->ctx, idx, ctx->ps + ctx->ps_shift); | ||
| 576 | } | ||
| 577 | |||
| 578 | static void atom_op_clear(atom_exec_context *ctx, int *ptr, int arg) | ||
| 579 | { | ||
| 580 | uint8_t attr = U8((*ptr)++); | ||
| 581 | uint32_t saved; | ||
| 582 | int dptr = *ptr; | ||
| 583 | attr &= 0x38; | ||
| 584 | attr |= atom_def_dst[attr >> 3] << 6; | ||
| 585 | atom_get_dst(ctx, arg, attr, ptr, &saved, 0); | ||
| 586 | SDEBUG(" dst: "); | ||
| 587 | atom_put_dst(ctx, arg, attr, &dptr, 0, saved); | ||
| 588 | } | ||
| 589 | |||
| 590 | static void atom_op_compare(atom_exec_context *ctx, int *ptr, int arg) | ||
| 591 | { | ||
| 592 | uint8_t attr = U8((*ptr)++); | ||
| 593 | uint32_t dst, src; | ||
| 594 | SDEBUG(" src1: "); | ||
| 595 | dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1); | ||
| 596 | SDEBUG(" src2: "); | ||
| 597 | src = atom_get_src(ctx, attr, ptr); | ||
| 598 | ctx->ctx->cs_equal = (dst == src); | ||
| 599 | ctx->ctx->cs_above = (dst > src); | ||
| 600 | SDEBUG(" result: %s %s\n", ctx->ctx->cs_equal ? "EQ" : "NE", | ||
| 601 | ctx->ctx->cs_above ? "GT" : "LE"); | ||
| 602 | } | ||
| 603 | |||
| 604 | static void atom_op_delay(atom_exec_context *ctx, int *ptr, int arg) | ||
| 605 | { | ||
| 606 | uint8_t count = U8((*ptr)++); | ||
| 607 | SDEBUG(" count: %d\n", count); | ||
| 608 | if (arg == ATOM_UNIT_MICROSEC) | ||
| 609 | schedule_timeout_uninterruptible(usecs_to_jiffies(count)); | ||
| 610 | else | ||
| 611 | schedule_timeout_uninterruptible(msecs_to_jiffies(count)); | ||
| 612 | } | ||
| 613 | |||
| 614 | static void atom_op_div(atom_exec_context *ctx, int *ptr, int arg) | ||
| 615 | { | ||
| 616 | uint8_t attr = U8((*ptr)++); | ||
| 617 | uint32_t dst, src; | ||
| 618 | SDEBUG(" src1: "); | ||
| 619 | dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1); | ||
| 620 | SDEBUG(" src2: "); | ||
| 621 | src = atom_get_src(ctx, attr, ptr); | ||
| 622 | if (src != 0) { | ||
| 623 | ctx->ctx->divmul[0] = dst / src; | ||
| 624 | ctx->ctx->divmul[1] = dst % src; | ||
| 625 | } else { | ||
| 626 | ctx->ctx->divmul[0] = 0; | ||
| 627 | ctx->ctx->divmul[1] = 0; | ||
| 628 | } | ||
| 629 | } | ||
| 630 | |||
| 631 | static void atom_op_eot(atom_exec_context *ctx, int *ptr, int arg) | ||
| 632 | { | ||
| 633 | /* functionally, a nop */ | ||
| 634 | } | ||
| 635 | |||
| 636 | static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg) | ||
| 637 | { | ||
| 638 | int execute = 0, target = U16(*ptr); | ||
| 639 | (*ptr) += 2; | ||
| 640 | switch (arg) { | ||
| 641 | case ATOM_COND_ABOVE: | ||
| 642 | execute = ctx->ctx->cs_above; | ||
| 643 | break; | ||
| 644 | case ATOM_COND_ABOVEOREQUAL: | ||
| 645 | execute = ctx->ctx->cs_above || ctx->ctx->cs_equal; | ||
| 646 | break; | ||
| 647 | case ATOM_COND_ALWAYS: | ||
| 648 | execute = 1; | ||
| 649 | break; | ||
| 650 | case ATOM_COND_BELOW: | ||
| 651 | execute = !(ctx->ctx->cs_above || ctx->ctx->cs_equal); | ||
| 652 | break; | ||
| 653 | case ATOM_COND_BELOWOREQUAL: | ||
| 654 | execute = !ctx->ctx->cs_above; | ||
| 655 | break; | ||
| 656 | case ATOM_COND_EQUAL: | ||
| 657 | execute = ctx->ctx->cs_equal; | ||
| 658 | break; | ||
| 659 | case ATOM_COND_NOTEQUAL: | ||
| 660 | execute = !ctx->ctx->cs_equal; | ||
| 661 | break; | ||
| 662 | } | ||
| 663 | if (arg != ATOM_COND_ALWAYS) | ||
| 664 | SDEBUG(" taken: %s\n", execute ? "yes" : "no"); | ||
| 665 | SDEBUG(" target: 0x%04X\n", target); | ||
| 666 | if (execute) | ||
| 667 | *ptr = ctx->start + target; | ||
| 668 | } | ||
| 669 | |||
| 670 | static void atom_op_mask(atom_exec_context *ctx, int *ptr, int arg) | ||
| 671 | { | ||
| 672 | uint8_t attr = U8((*ptr)++); | ||
| 673 | uint32_t dst, src1, src2, saved; | ||
| 674 | int dptr = *ptr; | ||
| 675 | SDEBUG(" dst: "); | ||
| 676 | dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); | ||
| 677 | SDEBUG(" src1: "); | ||
| 678 | src1 = atom_get_src(ctx, attr, ptr); | ||
| 679 | SDEBUG(" src2: "); | ||
| 680 | src2 = atom_get_src(ctx, attr, ptr); | ||
| 681 | dst &= src1; | ||
| 682 | dst |= src2; | ||
| 683 | SDEBUG(" dst: "); | ||
| 684 | atom_put_dst(ctx, arg, attr, &dptr, dst, saved); | ||
| 685 | } | ||
| 686 | |||
| 687 | static void atom_op_move(atom_exec_context *ctx, int *ptr, int arg) | ||
| 688 | { | ||
| 689 | uint8_t attr = U8((*ptr)++); | ||
| 690 | uint32_t src, saved; | ||
| 691 | int dptr = *ptr; | ||
| 692 | if (((attr >> 3) & 7) != ATOM_SRC_DWORD) | ||
| 693 | atom_get_dst(ctx, arg, attr, ptr, &saved, 0); | ||
| 694 | else { | ||
| 695 | atom_skip_dst(ctx, arg, attr, ptr); | ||
| 696 | saved = 0xCDCDCDCD; | ||
| 697 | } | ||
| 698 | SDEBUG(" src: "); | ||
| 699 | src = atom_get_src(ctx, attr, ptr); | ||
| 700 | SDEBUG(" dst: "); | ||
| 701 | atom_put_dst(ctx, arg, attr, &dptr, src, saved); | ||
| 702 | } | ||
| 703 | |||
| 704 | static void atom_op_mul(atom_exec_context *ctx, int *ptr, int arg) | ||
| 705 | { | ||
| 706 | uint8_t attr = U8((*ptr)++); | ||
| 707 | uint32_t dst, src; | ||
| 708 | SDEBUG(" src1: "); | ||
| 709 | dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1); | ||
| 710 | SDEBUG(" src2: "); | ||
| 711 | src = atom_get_src(ctx, attr, ptr); | ||
| 712 | ctx->ctx->divmul[0] = dst * src; | ||
| 713 | } | ||
| 714 | |||
| 715 | static void atom_op_nop(atom_exec_context *ctx, int *ptr, int arg) | ||
| 716 | { | ||
| 717 | /* nothing */ | ||
| 718 | } | ||
| 719 | |||
| 720 | static void atom_op_or(atom_exec_context *ctx, int *ptr, int arg) | ||
| 721 | { | ||
| 722 | uint8_t attr = U8((*ptr)++); | ||
| 723 | uint32_t dst, src, saved; | ||
| 724 | int dptr = *ptr; | ||
| 725 | SDEBUG(" dst: "); | ||
| 726 | dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); | ||
| 727 | SDEBUG(" src: "); | ||
| 728 | src = atom_get_src(ctx, attr, ptr); | ||
| 729 | dst |= src; | ||
| 730 | SDEBUG(" dst: "); | ||
| 731 | atom_put_dst(ctx, arg, attr, &dptr, dst, saved); | ||
| 732 | } | ||
| 733 | |||
| 734 | static void atom_op_postcard(atom_exec_context *ctx, int *ptr, int arg) | ||
| 735 | { | ||
| 736 | uint8_t val = U8((*ptr)++); | ||
| 737 | SDEBUG("POST card output: 0x%02X\n", val); | ||
| 738 | } | ||
| 739 | |||
| 740 | static void atom_op_repeat(atom_exec_context *ctx, int *ptr, int arg) | ||
| 741 | { | ||
| 742 | printk(KERN_INFO "unimplemented!\n"); | ||
| 743 | } | ||
| 744 | |||
| 745 | static void atom_op_restorereg(atom_exec_context *ctx, int *ptr, int arg) | ||
| 746 | { | ||
| 747 | printk(KERN_INFO "unimplemented!\n"); | ||
| 748 | } | ||
| 749 | |||
| 750 | static void atom_op_savereg(atom_exec_context *ctx, int *ptr, int arg) | ||
| 751 | { | ||
| 752 | printk(KERN_INFO "unimplemented!\n"); | ||
| 753 | } | ||
| 754 | |||
| 755 | static void atom_op_setdatablock(atom_exec_context *ctx, int *ptr, int arg) | ||
| 756 | { | ||
| 757 | int idx = U8(*ptr); | ||
| 758 | (*ptr)++; | ||
| 759 | SDEBUG(" block: %d\n", idx); | ||
| 760 | if (!idx) | ||
| 761 | ctx->ctx->data_block = 0; | ||
| 762 | else if (idx == 255) | ||
| 763 | ctx->ctx->data_block = ctx->start; | ||
| 764 | else | ||
| 765 | ctx->ctx->data_block = U16(ctx->ctx->data_table + 4 + 2 * idx); | ||
| 766 | SDEBUG(" base: 0x%04X\n", ctx->ctx->data_block); | ||
| 767 | } | ||
| 768 | |||
| 769 | static void atom_op_setfbbase(atom_exec_context *ctx, int *ptr, int arg) | ||
| 770 | { | ||
| 771 | uint8_t attr = U8((*ptr)++); | ||
| 772 | SDEBUG(" fb_base: "); | ||
| 773 | ctx->ctx->fb_base = atom_get_src(ctx, attr, ptr); | ||
| 774 | } | ||
| 775 | |||
| 776 | static void atom_op_setport(atom_exec_context *ctx, int *ptr, int arg) | ||
| 777 | { | ||
| 778 | int port; | ||
| 779 | switch (arg) { | ||
| 780 | case ATOM_PORT_ATI: | ||
| 781 | port = U16(*ptr); | ||
| 782 | if (port < ATOM_IO_NAMES_CNT) | ||
| 783 | SDEBUG(" port: %d (%s)\n", port, atom_io_names[port]); | ||
| 784 | else | ||
| 785 | SDEBUG(" port: %d\n", port); | ||
| 786 | if (!port) | ||
| 787 | ctx->ctx->io_mode = ATOM_IO_MM; | ||
| 788 | else | ||
| 789 | ctx->ctx->io_mode = ATOM_IO_IIO | port; | ||
| 790 | (*ptr) += 2; | ||
| 791 | break; | ||
| 792 | case ATOM_PORT_PCI: | ||
| 793 | ctx->ctx->io_mode = ATOM_IO_PCI; | ||
| 794 | (*ptr)++; | ||
| 795 | break; | ||
| 796 | case ATOM_PORT_SYSIO: | ||
| 797 | ctx->ctx->io_mode = ATOM_IO_SYSIO; | ||
| 798 | (*ptr)++; | ||
| 799 | break; | ||
| 800 | } | ||
| 801 | } | ||
| 802 | |||
| 803 | static void atom_op_setregblock(atom_exec_context *ctx, int *ptr, int arg) | ||
| 804 | { | ||
| 805 | ctx->ctx->reg_block = U16(*ptr); | ||
| 806 | (*ptr) += 2; | ||
| 807 | SDEBUG(" base: 0x%04X\n", ctx->ctx->reg_block); | ||
| 808 | } | ||
| 809 | |||
| 810 | static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg) | ||
| 811 | { | ||
| 812 | uint8_t attr = U8((*ptr)++), shift; | ||
| 813 | uint32_t saved, dst; | ||
| 814 | int dptr = *ptr; | ||
| 815 | attr &= 0x38; | ||
| 816 | attr |= atom_def_dst[attr >> 3] << 6; | ||
| 817 | SDEBUG(" dst: "); | ||
| 818 | dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); | ||
| 819 | shift = U8((*ptr)++); | ||
| 820 | SDEBUG(" shift: %d\n", shift); | ||
| 821 | dst <<= shift; | ||
| 822 | SDEBUG(" dst: "); | ||
| 823 | atom_put_dst(ctx, arg, attr, &dptr, dst, saved); | ||
| 824 | } | ||
| 825 | |||
| 826 | static void atom_op_shr(atom_exec_context *ctx, int *ptr, int arg) | ||
| 827 | { | ||
| 828 | uint8_t attr = U8((*ptr)++), shift; | ||
| 829 | uint32_t saved, dst; | ||
| 830 | int dptr = *ptr; | ||
| 831 | attr &= 0x38; | ||
| 832 | attr |= atom_def_dst[attr >> 3] << 6; | ||
| 833 | SDEBUG(" dst: "); | ||
| 834 | dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); | ||
| 835 | shift = U8((*ptr)++); | ||
| 836 | SDEBUG(" shift: %d\n", shift); | ||
| 837 | dst >>= shift; | ||
| 838 | SDEBUG(" dst: "); | ||
| 839 | atom_put_dst(ctx, arg, attr, &dptr, dst, saved); | ||
| 840 | } | ||
| 841 | |||
| 842 | static void atom_op_sub(atom_exec_context *ctx, int *ptr, int arg) | ||
| 843 | { | ||
| 844 | uint8_t attr = U8((*ptr)++); | ||
| 845 | uint32_t dst, src, saved; | ||
| 846 | int dptr = *ptr; | ||
| 847 | SDEBUG(" dst: "); | ||
| 848 | dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); | ||
| 849 | SDEBUG(" src: "); | ||
| 850 | src = atom_get_src(ctx, attr, ptr); | ||
| 851 | dst -= src; | ||
| 852 | SDEBUG(" dst: "); | ||
| 853 | atom_put_dst(ctx, arg, attr, &dptr, dst, saved); | ||
| 854 | } | ||
| 855 | |||
| 856 | static void atom_op_switch(atom_exec_context *ctx, int *ptr, int arg) | ||
| 857 | { | ||
| 858 | uint8_t attr = U8((*ptr)++); | ||
| 859 | uint32_t src, val, target; | ||
| 860 | SDEBUG(" switch: "); | ||
| 861 | src = atom_get_src(ctx, attr, ptr); | ||
| 862 | while (U16(*ptr) != ATOM_CASE_END) | ||
| 863 | if (U8(*ptr) == ATOM_CASE_MAGIC) { | ||
| 864 | (*ptr)++; | ||
| 865 | SDEBUG(" case: "); | ||
| 866 | val = | ||
| 867 | atom_get_src(ctx, (attr & 0x38) | ATOM_ARG_IMM, | ||
| 868 | ptr); | ||
| 869 | target = U16(*ptr); | ||
| 870 | if (val == src) { | ||
| 871 | SDEBUG(" target: %04X\n", target); | ||
| 872 | *ptr = ctx->start + target; | ||
| 873 | return; | ||
| 874 | } | ||
| 875 | (*ptr) += 2; | ||
| 876 | } else { | ||
| 877 | printk(KERN_INFO "Bad case.\n"); | ||
| 878 | return; | ||
| 879 | } | ||
| 880 | (*ptr) += 2; | ||
| 881 | } | ||
| 882 | |||
| 883 | static void atom_op_test(atom_exec_context *ctx, int *ptr, int arg) | ||
| 884 | { | ||
| 885 | uint8_t attr = U8((*ptr)++); | ||
| 886 | uint32_t dst, src; | ||
| 887 | SDEBUG(" src1: "); | ||
| 888 | dst = atom_get_dst(ctx, arg, attr, ptr, NULL, 1); | ||
| 889 | SDEBUG(" src2: "); | ||
| 890 | src = atom_get_src(ctx, attr, ptr); | ||
| 891 | ctx->ctx->cs_equal = ((dst & src) == 0); | ||
| 892 | SDEBUG(" result: %s\n", ctx->ctx->cs_equal ? "EQ" : "NE"); | ||
| 893 | } | ||
| 894 | |||
| 895 | static void atom_op_xor(atom_exec_context *ctx, int *ptr, int arg) | ||
| 896 | { | ||
| 897 | uint8_t attr = U8((*ptr)++); | ||
| 898 | uint32_t dst, src, saved; | ||
| 899 | int dptr = *ptr; | ||
| 900 | SDEBUG(" dst: "); | ||
| 901 | dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); | ||
| 902 | SDEBUG(" src: "); | ||
| 903 | src = atom_get_src(ctx, attr, ptr); | ||
| 904 | dst ^= src; | ||
| 905 | SDEBUG(" dst: "); | ||
| 906 | atom_put_dst(ctx, arg, attr, &dptr, dst, saved); | ||
| 907 | } | ||
| 908 | |||
| 909 | static void atom_op_debug(atom_exec_context *ctx, int *ptr, int arg) | ||
| 910 | { | ||
| 911 | printk(KERN_INFO "unimplemented!\n"); | ||
| 912 | } | ||
| 913 | |||
| 914 | static struct { | ||
| 915 | void (*func) (atom_exec_context *, int *, int); | ||
| 916 | int arg; | ||
| 917 | } opcode_table[ATOM_OP_CNT] = { | ||
| 918 | { | ||
| 919 | NULL, 0}, { | ||
| 920 | atom_op_move, ATOM_ARG_REG}, { | ||
| 921 | atom_op_move, ATOM_ARG_PS}, { | ||
| 922 | atom_op_move, ATOM_ARG_WS}, { | ||
| 923 | atom_op_move, ATOM_ARG_FB}, { | ||
| 924 | atom_op_move, ATOM_ARG_PLL}, { | ||
| 925 | atom_op_move, ATOM_ARG_MC}, { | ||
| 926 | atom_op_and, ATOM_ARG_REG}, { | ||
| 927 | atom_op_and, ATOM_ARG_PS}, { | ||
| 928 | atom_op_and, ATOM_ARG_WS}, { | ||
| 929 | atom_op_and, ATOM_ARG_FB}, { | ||
| 930 | atom_op_and, ATOM_ARG_PLL}, { | ||
| 931 | atom_op_and, ATOM_ARG_MC}, { | ||
| 932 | atom_op_or, ATOM_ARG_REG}, { | ||
| 933 | atom_op_or, ATOM_ARG_PS}, { | ||
| 934 | atom_op_or, ATOM_ARG_WS}, { | ||
| 935 | atom_op_or, ATOM_ARG_FB}, { | ||
| 936 | atom_op_or, ATOM_ARG_PLL}, { | ||
| 937 | atom_op_or, ATOM_ARG_MC}, { | ||
| 938 | atom_op_shl, ATOM_ARG_REG}, { | ||
| 939 | atom_op_shl, ATOM_ARG_PS}, { | ||
| 940 | atom_op_shl, ATOM_ARG_WS}, { | ||
| 941 | atom_op_shl, ATOM_ARG_FB}, { | ||
| 942 | atom_op_shl, ATOM_ARG_PLL}, { | ||
| 943 | atom_op_shl, ATOM_ARG_MC}, { | ||
| 944 | atom_op_shr, ATOM_ARG_REG}, { | ||
| 945 | atom_op_shr, ATOM_ARG_PS}, { | ||
| 946 | atom_op_shr, ATOM_ARG_WS}, { | ||
| 947 | atom_op_shr, ATOM_ARG_FB}, { | ||
| 948 | atom_op_shr, ATOM_ARG_PLL}, { | ||
| 949 | atom_op_shr, ATOM_ARG_MC}, { | ||
| 950 | atom_op_mul, ATOM_ARG_REG}, { | ||
| 951 | atom_op_mul, ATOM_ARG_PS}, { | ||
| 952 | atom_op_mul, ATOM_ARG_WS}, { | ||
| 953 | atom_op_mul, ATOM_ARG_FB}, { | ||
| 954 | atom_op_mul, ATOM_ARG_PLL}, { | ||
| 955 | atom_op_mul, ATOM_ARG_MC}, { | ||
| 956 | atom_op_div, ATOM_ARG_REG}, { | ||
| 957 | atom_op_div, ATOM_ARG_PS}, { | ||
| 958 | atom_op_div, ATOM_ARG_WS}, { | ||
| 959 | atom_op_div, ATOM_ARG_FB}, { | ||
| 960 | atom_op_div, ATOM_ARG_PLL}, { | ||
| 961 | atom_op_div, ATOM_ARG_MC}, { | ||
| 962 | atom_op_add, ATOM_ARG_REG}, { | ||
| 963 | atom_op_add, ATOM_ARG_PS}, { | ||
| 964 | atom_op_add, ATOM_ARG_WS}, { | ||
| 965 | atom_op_add, ATOM_ARG_FB}, { | ||
| 966 | atom_op_add, ATOM_ARG_PLL}, { | ||
| 967 | atom_op_add, ATOM_ARG_MC}, { | ||
| 968 | atom_op_sub, ATOM_ARG_REG}, { | ||
| 969 | atom_op_sub, ATOM_ARG_PS}, { | ||
| 970 | atom_op_sub, ATOM_ARG_WS}, { | ||
| 971 | atom_op_sub, ATOM_ARG_FB}, { | ||
| 972 | atom_op_sub, ATOM_ARG_PLL}, { | ||
| 973 | atom_op_sub, ATOM_ARG_MC}, { | ||
| 974 | atom_op_setport, ATOM_PORT_ATI}, { | ||
| 975 | atom_op_setport, ATOM_PORT_PCI}, { | ||
| 976 | atom_op_setport, ATOM_PORT_SYSIO}, { | ||
| 977 | atom_op_setregblock, 0}, { | ||
| 978 | atom_op_setfbbase, 0}, { | ||
| 979 | atom_op_compare, ATOM_ARG_REG}, { | ||
| 980 | atom_op_compare, ATOM_ARG_PS}, { | ||
| 981 | atom_op_compare, ATOM_ARG_WS}, { | ||
| 982 | atom_op_compare, ATOM_ARG_FB}, { | ||
| 983 | atom_op_compare, ATOM_ARG_PLL}, { | ||
| 984 | atom_op_compare, ATOM_ARG_MC}, { | ||
| 985 | atom_op_switch, 0}, { | ||
| 986 | atom_op_jump, ATOM_COND_ALWAYS}, { | ||
| 987 | atom_op_jump, ATOM_COND_EQUAL}, { | ||
| 988 | atom_op_jump, ATOM_COND_BELOW}, { | ||
| 989 | atom_op_jump, ATOM_COND_ABOVE}, { | ||
| 990 | atom_op_jump, ATOM_COND_BELOWOREQUAL}, { | ||
| 991 | atom_op_jump, ATOM_COND_ABOVEOREQUAL}, { | ||
| 992 | atom_op_jump, ATOM_COND_NOTEQUAL}, { | ||
| 993 | atom_op_test, ATOM_ARG_REG}, { | ||
| 994 | atom_op_test, ATOM_ARG_PS}, { | ||
| 995 | atom_op_test, ATOM_ARG_WS}, { | ||
| 996 | atom_op_test, ATOM_ARG_FB}, { | ||
| 997 | atom_op_test, ATOM_ARG_PLL}, { | ||
| 998 | atom_op_test, ATOM_ARG_MC}, { | ||
| 999 | atom_op_delay, ATOM_UNIT_MILLISEC}, { | ||
| 1000 | atom_op_delay, ATOM_UNIT_MICROSEC}, { | ||
| 1001 | atom_op_calltable, 0}, { | ||
| 1002 | atom_op_repeat, 0}, { | ||
| 1003 | atom_op_clear, ATOM_ARG_REG}, { | ||
| 1004 | atom_op_clear, ATOM_ARG_PS}, { | ||
| 1005 | atom_op_clear, ATOM_ARG_WS}, { | ||
| 1006 | atom_op_clear, ATOM_ARG_FB}, { | ||
| 1007 | atom_op_clear, ATOM_ARG_PLL}, { | ||
| 1008 | atom_op_clear, ATOM_ARG_MC}, { | ||
| 1009 | atom_op_nop, 0}, { | ||
| 1010 | atom_op_eot, 0}, { | ||
| 1011 | atom_op_mask, ATOM_ARG_REG}, { | ||
| 1012 | atom_op_mask, ATOM_ARG_PS}, { | ||
| 1013 | atom_op_mask, ATOM_ARG_WS}, { | ||
| 1014 | atom_op_mask, ATOM_ARG_FB}, { | ||
| 1015 | atom_op_mask, ATOM_ARG_PLL}, { | ||
| 1016 | atom_op_mask, ATOM_ARG_MC}, { | ||
| 1017 | atom_op_postcard, 0}, { | ||
| 1018 | atom_op_beep, 0}, { | ||
| 1019 | atom_op_savereg, 0}, { | ||
| 1020 | atom_op_restorereg, 0}, { | ||
| 1021 | atom_op_setdatablock, 0}, { | ||
| 1022 | atom_op_xor, ATOM_ARG_REG}, { | ||
| 1023 | atom_op_xor, ATOM_ARG_PS}, { | ||
| 1024 | atom_op_xor, ATOM_ARG_WS}, { | ||
| 1025 | atom_op_xor, ATOM_ARG_FB}, { | ||
| 1026 | atom_op_xor, ATOM_ARG_PLL}, { | ||
| 1027 | atom_op_xor, ATOM_ARG_MC}, { | ||
| 1028 | atom_op_shl, ATOM_ARG_REG}, { | ||
| 1029 | atom_op_shl, ATOM_ARG_PS}, { | ||
| 1030 | atom_op_shl, ATOM_ARG_WS}, { | ||
| 1031 | atom_op_shl, ATOM_ARG_FB}, { | ||
| 1032 | atom_op_shl, ATOM_ARG_PLL}, { | ||
| 1033 | atom_op_shl, ATOM_ARG_MC}, { | ||
| 1034 | atom_op_shr, ATOM_ARG_REG}, { | ||
| 1035 | atom_op_shr, ATOM_ARG_PS}, { | ||
| 1036 | atom_op_shr, ATOM_ARG_WS}, { | ||
| 1037 | atom_op_shr, ATOM_ARG_FB}, { | ||
| 1038 | atom_op_shr, ATOM_ARG_PLL}, { | ||
| 1039 | atom_op_shr, ATOM_ARG_MC}, { | ||
| 1040 | atom_op_debug, 0},}; | ||
| 1041 | |||
| 1042 | void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) | ||
| 1043 | { | ||
| 1044 | int base = CU16(ctx->cmd_table + 4 + 2 * index); | ||
| 1045 | int len, ws, ps, ptr; | ||
| 1046 | unsigned char op; | ||
| 1047 | atom_exec_context ectx; | ||
| 1048 | |||
| 1049 | if (!base) | ||
| 1050 | return; | ||
| 1051 | |||
| 1052 | len = CU16(base + ATOM_CT_SIZE_PTR); | ||
| 1053 | ws = CU8(base + ATOM_CT_WS_PTR); | ||
| 1054 | ps = CU8(base + ATOM_CT_PS_PTR) & ATOM_CT_PS_MASK; | ||
| 1055 | ptr = base + ATOM_CT_CODE_PTR; | ||
| 1056 | |||
| 1057 | SDEBUG(">> execute %04X (len %d, WS %d, PS %d)\n", base, len, ws, ps); | ||
| 1058 | |||
| 1059 | /* reset reg block */ | ||
| 1060 | ctx->reg_block = 0; | ||
| 1061 | ectx.ctx = ctx; | ||
| 1062 | ectx.ps_shift = ps / 4; | ||
| 1063 | ectx.start = base; | ||
| 1064 | ectx.ps = params; | ||
| 1065 | if (ws) | ||
| 1066 | ectx.ws = kzalloc(4 * ws, GFP_KERNEL); | ||
| 1067 | else | ||
| 1068 | ectx.ws = NULL; | ||
| 1069 | |||
| 1070 | debug_depth++; | ||
| 1071 | while (1) { | ||
| 1072 | op = CU8(ptr++); | ||
| 1073 | if (op < ATOM_OP_NAMES_CNT) | ||
| 1074 | SDEBUG("%s @ 0x%04X\n", atom_op_names[op], ptr - 1); | ||
| 1075 | else | ||
| 1076 | SDEBUG("[%d] @ 0x%04X\n", op, ptr - 1); | ||
| 1077 | |||
| 1078 | if (op < ATOM_OP_CNT && op > 0) | ||
| 1079 | opcode_table[op].func(&ectx, &ptr, | ||
| 1080 | opcode_table[op].arg); | ||
| 1081 | else | ||
| 1082 | break; | ||
| 1083 | |||
| 1084 | if (op == ATOM_OP_EOT) | ||
| 1085 | break; | ||
| 1086 | } | ||
| 1087 | debug_depth--; | ||
| 1088 | SDEBUG("<<\n"); | ||
| 1089 | |||
| 1090 | if (ws) | ||
| 1091 | kfree(ectx.ws); | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 }; | ||
| 1095 | |||
| 1096 | static void atom_index_iio(struct atom_context *ctx, int base) | ||
| 1097 | { | ||
| 1098 | ctx->iio = kzalloc(2 * 256, GFP_KERNEL); | ||
| 1099 | while (CU8(base) == ATOM_IIO_START) { | ||
| 1100 | ctx->iio[CU8(base + 1)] = base + 2; | ||
| 1101 | base += 2; | ||
| 1102 | while (CU8(base) != ATOM_IIO_END) | ||
| 1103 | base += atom_iio_len[CU8(base)]; | ||
| 1104 | base += 3; | ||
| 1105 | } | ||
| 1106 | } | ||
| 1107 | |||
| 1108 | struct atom_context *atom_parse(struct card_info *card, void *bios) | ||
| 1109 | { | ||
| 1110 | int base; | ||
| 1111 | struct atom_context *ctx = | ||
| 1112 | kzalloc(sizeof(struct atom_context), GFP_KERNEL); | ||
| 1113 | char *str; | ||
| 1114 | char name[512]; | ||
| 1115 | int i; | ||
| 1116 | |||
| 1117 | ctx->card = card; | ||
| 1118 | ctx->bios = bios; | ||
| 1119 | |||
| 1120 | if (CU16(0) != ATOM_BIOS_MAGIC) { | ||
| 1121 | printk(KERN_INFO "Invalid BIOS magic.\n"); | ||
| 1122 | kfree(ctx); | ||
| 1123 | return NULL; | ||
| 1124 | } | ||
| 1125 | if (strncmp | ||
| 1126 | (CSTR(ATOM_ATI_MAGIC_PTR), ATOM_ATI_MAGIC, | ||
| 1127 | strlen(ATOM_ATI_MAGIC))) { | ||
| 1128 | printk(KERN_INFO "Invalid ATI magic.\n"); | ||
| 1129 | kfree(ctx); | ||
| 1130 | return NULL; | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | base = CU16(ATOM_ROM_TABLE_PTR); | ||
| 1134 | if (strncmp | ||
| 1135 | (CSTR(base + ATOM_ROM_MAGIC_PTR), ATOM_ROM_MAGIC, | ||
| 1136 | strlen(ATOM_ROM_MAGIC))) { | ||
| 1137 | printk(KERN_INFO "Invalid ATOM magic.\n"); | ||
| 1138 | kfree(ctx); | ||
| 1139 | return NULL; | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | ctx->cmd_table = CU16(base + ATOM_ROM_CMD_PTR); | ||
| 1143 | ctx->data_table = CU16(base + ATOM_ROM_DATA_PTR); | ||
| 1144 | atom_index_iio(ctx, CU16(ctx->data_table + ATOM_DATA_IIO_PTR) + 4); | ||
| 1145 | |||
| 1146 | str = CSTR(CU16(base + ATOM_ROM_MSG_PTR)); | ||
| 1147 | while (*str && ((*str == '\n') || (*str == '\r'))) | ||
| 1148 | str++; | ||
| 1149 | /* name string isn't always 0 terminated */ | ||
| 1150 | for (i = 0; i < 511; i++) { | ||
| 1151 | name[i] = str[i]; | ||
| 1152 | if (name[i] < '.' || name[i] > 'z') { | ||
| 1153 | name[i] = 0; | ||
| 1154 | break; | ||
| 1155 | } | ||
| 1156 | } | ||
| 1157 | printk(KERN_INFO "ATOM BIOS: %s\n", name); | ||
| 1158 | |||
| 1159 | return ctx; | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | int atom_asic_init(struct atom_context *ctx) | ||
| 1163 | { | ||
| 1164 | int hwi = CU16(ctx->data_table + ATOM_DATA_FWI_PTR); | ||
| 1165 | uint32_t ps[16]; | ||
| 1166 | memset(ps, 0, 64); | ||
| 1167 | |||
| 1168 | ps[0] = cpu_to_le32(CU32(hwi + ATOM_FWI_DEFSCLK_PTR)); | ||
| 1169 | ps[1] = cpu_to_le32(CU32(hwi + ATOM_FWI_DEFMCLK_PTR)); | ||
| 1170 | if (!ps[0] || !ps[1]) | ||
| 1171 | return 1; | ||
| 1172 | |||
| 1173 | if (!CU16(ctx->cmd_table + 4 + 2 * ATOM_CMD_INIT)) | ||
| 1174 | return 1; | ||
| 1175 | atom_execute_table(ctx, ATOM_CMD_INIT, ps); | ||
| 1176 | |||
| 1177 | return 0; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | void atom_destroy(struct atom_context *ctx) | ||
| 1181 | { | ||
| 1182 | if (ctx->iio) | ||
| 1183 | kfree(ctx->iio); | ||
| 1184 | kfree(ctx); | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | void atom_parse_data_header(struct atom_context *ctx, int index, | ||
| 1188 | uint16_t * size, uint8_t * frev, uint8_t * crev, | ||
| 1189 | uint16_t * data_start) | ||
| 1190 | { | ||
| 1191 | int offset = index * 2 + 4; | ||
| 1192 | int idx = CU16(ctx->data_table + offset); | ||
| 1193 | |||
| 1194 | if (size) | ||
| 1195 | *size = CU16(idx); | ||
| 1196 | if (frev) | ||
| 1197 | *frev = CU8(idx + 2); | ||
| 1198 | if (crev) | ||
| 1199 | *crev = CU8(idx + 3); | ||
| 1200 | *data_start = idx; | ||
| 1201 | return; | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t * frev, | ||
| 1205 | uint8_t * crev) | ||
| 1206 | { | ||
| 1207 | int offset = index * 2 + 4; | ||
| 1208 | int idx = CU16(ctx->cmd_table + offset); | ||
| 1209 | |||
| 1210 | if (frev) | ||
| 1211 | *frev = CU8(idx + 2); | ||
| 1212 | if (crev) | ||
| 1213 | *crev = CU8(idx + 3); | ||
| 1214 | return; | ||
| 1215 | } | ||
diff --git a/drivers/gpu/drm/radeon/atom.h b/drivers/gpu/drm/radeon/atom.h new file mode 100644 index 000000000000..e6eb38f2bcae --- /dev/null +++ b/drivers/gpu/drm/radeon/atom.h | |||
| @@ -0,0 +1,149 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, 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: Stanislaw Skowronek | ||
| 23 | */ | ||
| 24 | |||
| 25 | #ifndef ATOM_H | ||
| 26 | #define ATOM_H | ||
| 27 | |||
| 28 | #include <linux/types.h> | ||
| 29 | #include "drmP.h" | ||
| 30 | |||
| 31 | #define ATOM_BIOS_MAGIC 0xAA55 | ||
| 32 | #define ATOM_ATI_MAGIC_PTR 0x30 | ||
| 33 | #define ATOM_ATI_MAGIC " 761295520" | ||
| 34 | #define ATOM_ROM_TABLE_PTR 0x48 | ||
| 35 | |||
| 36 | #define ATOM_ROM_MAGIC "ATOM" | ||
| 37 | #define ATOM_ROM_MAGIC_PTR 4 | ||
| 38 | |||
| 39 | #define ATOM_ROM_MSG_PTR 0x10 | ||
| 40 | #define ATOM_ROM_CMD_PTR 0x1E | ||
| 41 | #define ATOM_ROM_DATA_PTR 0x20 | ||
| 42 | |||
| 43 | #define ATOM_CMD_INIT 0 | ||
| 44 | #define ATOM_CMD_SETSCLK 0x0A | ||
| 45 | #define ATOM_CMD_SETMCLK 0x0B | ||
| 46 | #define ATOM_CMD_SETPCLK 0x0C | ||
| 47 | |||
| 48 | #define ATOM_DATA_FWI_PTR 0xC | ||
| 49 | #define ATOM_DATA_IIO_PTR 0x32 | ||
| 50 | |||
| 51 | #define ATOM_FWI_DEFSCLK_PTR 8 | ||
| 52 | #define ATOM_FWI_DEFMCLK_PTR 0xC | ||
| 53 | #define ATOM_FWI_MAXSCLK_PTR 0x24 | ||
| 54 | #define ATOM_FWI_MAXMCLK_PTR 0x28 | ||
| 55 | |||
| 56 | #define ATOM_CT_SIZE_PTR 0 | ||
| 57 | #define ATOM_CT_WS_PTR 4 | ||
| 58 | #define ATOM_CT_PS_PTR 5 | ||
| 59 | #define ATOM_CT_PS_MASK 0x7F | ||
| 60 | #define ATOM_CT_CODE_PTR 6 | ||
| 61 | |||
| 62 | #define ATOM_OP_CNT 123 | ||
| 63 | #define ATOM_OP_EOT 91 | ||
| 64 | |||
| 65 | #define ATOM_CASE_MAGIC 0x63 | ||
| 66 | #define ATOM_CASE_END 0x5A5A | ||
| 67 | |||
| 68 | #define ATOM_ARG_REG 0 | ||
| 69 | #define ATOM_ARG_PS 1 | ||
| 70 | #define ATOM_ARG_WS 2 | ||
| 71 | #define ATOM_ARG_FB 3 | ||
| 72 | #define ATOM_ARG_ID 4 | ||
| 73 | #define ATOM_ARG_IMM 5 | ||
| 74 | #define ATOM_ARG_PLL 6 | ||
| 75 | #define ATOM_ARG_MC 7 | ||
| 76 | |||
| 77 | #define ATOM_SRC_DWORD 0 | ||
| 78 | #define ATOM_SRC_WORD0 1 | ||
| 79 | #define ATOM_SRC_WORD8 2 | ||
| 80 | #define ATOM_SRC_WORD16 3 | ||
| 81 | #define ATOM_SRC_BYTE0 4 | ||
| 82 | #define ATOM_SRC_BYTE8 5 | ||
| 83 | #define ATOM_SRC_BYTE16 6 | ||
| 84 | #define ATOM_SRC_BYTE24 7 | ||
| 85 | |||
| 86 | #define ATOM_WS_QUOTIENT 0x40 | ||
| 87 | #define ATOM_WS_REMAINDER 0x41 | ||
| 88 | #define ATOM_WS_DATAPTR 0x42 | ||
| 89 | #define ATOM_WS_SHIFT 0x43 | ||
| 90 | #define ATOM_WS_OR_MASK 0x44 | ||
| 91 | #define ATOM_WS_AND_MASK 0x45 | ||
| 92 | #define ATOM_WS_FB_WINDOW 0x46 | ||
| 93 | #define ATOM_WS_ATTRIBUTES 0x47 | ||
| 94 | |||
| 95 | #define ATOM_IIO_NOP 0 | ||
| 96 | #define ATOM_IIO_START 1 | ||
| 97 | #define ATOM_IIO_READ 2 | ||
| 98 | #define ATOM_IIO_WRITE 3 | ||
| 99 | #define ATOM_IIO_CLEAR 4 | ||
| 100 | #define ATOM_IIO_SET 5 | ||
| 101 | #define ATOM_IIO_MOVE_INDEX 6 | ||
| 102 | #define ATOM_IIO_MOVE_ATTR 7 | ||
| 103 | #define ATOM_IIO_MOVE_DATA 8 | ||
| 104 | #define ATOM_IIO_END 9 | ||
| 105 | |||
| 106 | #define ATOM_IO_MM 0 | ||
| 107 | #define ATOM_IO_PCI 1 | ||
| 108 | #define ATOM_IO_SYSIO 2 | ||
| 109 | #define ATOM_IO_IIO 0x80 | ||
| 110 | |||
| 111 | struct card_info { | ||
| 112 | struct drm_device *dev; | ||
| 113 | void (* reg_write)(struct card_info *, uint32_t, uint32_t); /* filled by driver */ | ||
| 114 | uint32_t (* reg_read)(struct card_info *, uint32_t); /* filled by driver */ | ||
| 115 | void (* mc_write)(struct card_info *, uint32_t, uint32_t); /* filled by driver */ | ||
| 116 | uint32_t (* mc_read)(struct card_info *, uint32_t); /* filled by driver */ | ||
| 117 | void (* pll_write)(struct card_info *, uint32_t, uint32_t); /* filled by driver */ | ||
| 118 | uint32_t (* pll_read)(struct card_info *, uint32_t); /* filled by driver */ | ||
| 119 | }; | ||
| 120 | |||
| 121 | struct atom_context { | ||
| 122 | struct card_info *card; | ||
| 123 | void *bios; | ||
| 124 | uint32_t cmd_table, data_table; | ||
| 125 | uint16_t *iio; | ||
| 126 | |||
| 127 | uint16_t data_block; | ||
| 128 | uint32_t fb_base; | ||
| 129 | uint32_t divmul[2]; | ||
| 130 | uint16_t io_attr; | ||
| 131 | uint16_t reg_block; | ||
| 132 | uint8_t shift; | ||
| 133 | int cs_equal, cs_above; | ||
| 134 | int io_mode; | ||
| 135 | }; | ||
| 136 | |||
| 137 | extern int atom_debug; | ||
| 138 | |||
| 139 | struct atom_context *atom_parse(struct card_info *, void *); | ||
| 140 | void atom_execute_table(struct atom_context *, int, uint32_t *); | ||
| 141 | int atom_asic_init(struct atom_context *); | ||
| 142 | void atom_destroy(struct atom_context *); | ||
| 143 | void atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size, uint8_t *frev, uint8_t *crev, uint16_t *data_start); | ||
| 144 | void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t *frev, uint8_t *crev); | ||
| 145 | #include "atom-types.h" | ||
| 146 | #include "atombios.h" | ||
| 147 | #include "ObjectID.h" | ||
| 148 | |||
| 149 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h new file mode 100644 index 000000000000..cf67928abbc8 --- /dev/null +++ b/drivers/gpu/drm/radeon/atombios.h | |||
| @@ -0,0 +1,4785 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2006-2007 Advanced Micro Devices, 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 | |||
| 23 | /****************************************************************************/ | ||
| 24 | /*Portion I: Definitions shared between VBIOS and Driver */ | ||
| 25 | /****************************************************************************/ | ||
| 26 | |||
| 27 | #ifndef _ATOMBIOS_H | ||
| 28 | #define _ATOMBIOS_H | ||
| 29 | |||
| 30 | #define ATOM_VERSION_MAJOR 0x00020000 | ||
| 31 | #define ATOM_VERSION_MINOR 0x00000002 | ||
| 32 | |||
| 33 | #define ATOM_HEADER_VERSION (ATOM_VERSION_MAJOR | ATOM_VERSION_MINOR) | ||
| 34 | |||
| 35 | /* Endianness should be specified before inclusion, | ||
| 36 | * default to little endian | ||
| 37 | */ | ||
| 38 | #ifndef ATOM_BIG_ENDIAN | ||
| 39 | #error Endian not specified | ||
| 40 | #endif | ||
| 41 | |||
| 42 | #ifdef _H2INC | ||
| 43 | #ifndef ULONG | ||
| 44 | typedef unsigned long ULONG; | ||
| 45 | #endif | ||
| 46 | |||
| 47 | #ifndef UCHAR | ||
| 48 | typedef unsigned char UCHAR; | ||
| 49 | #endif | ||
| 50 | |||
| 51 | #ifndef USHORT | ||
| 52 | typedef unsigned short USHORT; | ||
| 53 | #endif | ||
| 54 | #endif | ||
| 55 | |||
| 56 | #define ATOM_DAC_A 0 | ||
| 57 | #define ATOM_DAC_B 1 | ||
| 58 | #define ATOM_EXT_DAC 2 | ||
| 59 | |||
| 60 | #define ATOM_CRTC1 0 | ||
| 61 | #define ATOM_CRTC2 1 | ||
| 62 | |||
| 63 | #define ATOM_DIGA 0 | ||
| 64 | #define ATOM_DIGB 1 | ||
| 65 | |||
| 66 | #define ATOM_PPLL1 0 | ||
| 67 | #define ATOM_PPLL2 1 | ||
| 68 | |||
| 69 | #define ATOM_SCALER1 0 | ||
| 70 | #define ATOM_SCALER2 1 | ||
| 71 | |||
| 72 | #define ATOM_SCALER_DISABLE 0 | ||
| 73 | #define ATOM_SCALER_CENTER 1 | ||
| 74 | #define ATOM_SCALER_EXPANSION 2 | ||
| 75 | #define ATOM_SCALER_MULTI_EX 3 | ||
| 76 | |||
| 77 | #define ATOM_DISABLE 0 | ||
| 78 | #define ATOM_ENABLE 1 | ||
| 79 | #define ATOM_LCD_BLOFF (ATOM_DISABLE+2) | ||
| 80 | #define ATOM_LCD_BLON (ATOM_ENABLE+2) | ||
| 81 | #define ATOM_LCD_BL_BRIGHTNESS_CONTROL (ATOM_ENABLE+3) | ||
| 82 | #define ATOM_LCD_SELFTEST_START (ATOM_DISABLE+5) | ||
| 83 | #define ATOM_LCD_SELFTEST_STOP (ATOM_ENABLE+5) | ||
| 84 | #define ATOM_ENCODER_INIT (ATOM_DISABLE+7) | ||
| 85 | |||
| 86 | #define ATOM_BLANKING 1 | ||
| 87 | #define ATOM_BLANKING_OFF 0 | ||
| 88 | |||
| 89 | #define ATOM_CURSOR1 0 | ||
| 90 | #define ATOM_CURSOR2 1 | ||
| 91 | |||
| 92 | #define ATOM_ICON1 0 | ||
| 93 | #define ATOM_ICON2 1 | ||
| 94 | |||
| 95 | #define ATOM_CRT1 0 | ||
| 96 | #define ATOM_CRT2 1 | ||
| 97 | |||
| 98 | #define ATOM_TV_NTSC 1 | ||
| 99 | #define ATOM_TV_NTSCJ 2 | ||
| 100 | #define ATOM_TV_PAL 3 | ||
| 101 | #define ATOM_TV_PALM 4 | ||
| 102 | #define ATOM_TV_PALCN 5 | ||
| 103 | #define ATOM_TV_PALN 6 | ||
| 104 | #define ATOM_TV_PAL60 7 | ||
| 105 | #define ATOM_TV_SECAM 8 | ||
| 106 | #define ATOM_TV_CV 16 | ||
| 107 | |||
| 108 | #define ATOM_DAC1_PS2 1 | ||
| 109 | #define ATOM_DAC1_CV 2 | ||
| 110 | #define ATOM_DAC1_NTSC 3 | ||
| 111 | #define ATOM_DAC1_PAL 4 | ||
| 112 | |||
| 113 | #define ATOM_DAC2_PS2 ATOM_DAC1_PS2 | ||
| 114 | #define ATOM_DAC2_CV ATOM_DAC1_CV | ||
| 115 | #define ATOM_DAC2_NTSC ATOM_DAC1_NTSC | ||
| 116 | #define ATOM_DAC2_PAL ATOM_DAC1_PAL | ||
| 117 | |||
| 118 | #define ATOM_PM_ON 0 | ||
| 119 | #define ATOM_PM_STANDBY 1 | ||
| 120 | #define ATOM_PM_SUSPEND 2 | ||
| 121 | #define ATOM_PM_OFF 3 | ||
| 122 | |||
| 123 | /* Bit0:{=0:single, =1:dual}, | ||
| 124 | Bit1 {=0:666RGB, =1:888RGB}, | ||
| 125 | Bit2:3:{Grey level} | ||
| 126 | Bit4:{=0:LDI format for RGB888, =1 FPDI format for RGB888}*/ | ||
| 127 | |||
| 128 | #define ATOM_PANEL_MISC_DUAL 0x00000001 | ||
| 129 | #define ATOM_PANEL_MISC_888RGB 0x00000002 | ||
| 130 | #define ATOM_PANEL_MISC_GREY_LEVEL 0x0000000C | ||
| 131 | #define ATOM_PANEL_MISC_FPDI 0x00000010 | ||
| 132 | #define ATOM_PANEL_MISC_GREY_LEVEL_SHIFT 2 | ||
| 133 | #define ATOM_PANEL_MISC_SPATIAL 0x00000020 | ||
| 134 | #define ATOM_PANEL_MISC_TEMPORAL 0x00000040 | ||
| 135 | #define ATOM_PANEL_MISC_API_ENABLED 0x00000080 | ||
| 136 | |||
| 137 | #define MEMTYPE_DDR1 "DDR1" | ||
| 138 | #define MEMTYPE_DDR2 "DDR2" | ||
| 139 | #define MEMTYPE_DDR3 "DDR3" | ||
| 140 | #define MEMTYPE_DDR4 "DDR4" | ||
| 141 | |||
| 142 | #define ASIC_BUS_TYPE_PCI "PCI" | ||
| 143 | #define ASIC_BUS_TYPE_AGP "AGP" | ||
| 144 | #define ASIC_BUS_TYPE_PCIE "PCI_EXPRESS" | ||
| 145 | |||
| 146 | /* Maximum size of that FireGL flag string */ | ||
| 147 | |||
| 148 | #define ATOM_FIREGL_FLAG_STRING "FGL" /* Flag used to enable FireGL Support */ | ||
| 149 | #define ATOM_MAX_SIZE_OF_FIREGL_FLAG_STRING 3 /* sizeof( ATOM_FIREGL_FLAG_STRING ) */ | ||
| 150 | |||
| 151 | #define ATOM_FAKE_DESKTOP_STRING "DSK" /* Flag used to enable mobile ASIC on Desktop */ | ||
| 152 | #define ATOM_MAX_SIZE_OF_FAKE_DESKTOP_STRING ATOM_MAX_SIZE_OF_FIREGL_FLAG_STRING | ||
| 153 | |||
| 154 | #define ATOM_M54T_FLAG_STRING "M54T" /* Flag used to enable M54T Support */ | ||
| 155 | #define ATOM_MAX_SIZE_OF_M54T_FLAG_STRING 4 /* sizeof( ATOM_M54T_FLAG_STRING ) */ | ||
| 156 | |||
| 157 | #define HW_ASSISTED_I2C_STATUS_FAILURE 2 | ||
| 158 | #define HW_ASSISTED_I2C_STATUS_SUCCESS 1 | ||
| 159 | |||
| 160 | #pragma pack(1) /* BIOS data must use byte aligment */ | ||
| 161 | |||
| 162 | /* Define offset to location of ROM header. */ | ||
| 163 | |||
| 164 | #define OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER 0x00000048L | ||
| 165 | #define OFFSET_TO_ATOM_ROM_IMAGE_SIZE 0x00000002L | ||
| 166 | |||
| 167 | #define OFFSET_TO_ATOMBIOS_ASIC_BUS_MEM_TYPE 0x94 | ||
| 168 | #define MAXSIZE_OF_ATOMBIOS_ASIC_BUS_MEM_TYPE 20 /* including the terminator 0x0! */ | ||
| 169 | #define OFFSET_TO_GET_ATOMBIOS_STRINGS_NUMBER 0x002f | ||
| 170 | #define OFFSET_TO_GET_ATOMBIOS_STRINGS_START 0x006e | ||
| 171 | |||
| 172 | /* Common header for all ROM Data tables. | ||
| 173 | Every table pointed _ATOM_MASTER_DATA_TABLE has this common header. | ||
| 174 | And the pointer actually points to this header. */ | ||
| 175 | |||
| 176 | typedef struct _ATOM_COMMON_TABLE_HEADER { | ||
| 177 | USHORT usStructureSize; | ||
| 178 | UCHAR ucTableFormatRevision; /*Change it when the Parser is not backward compatible */ | ||
| 179 | UCHAR ucTableContentRevision; /*Change it only when the table needs to change but the firmware */ | ||
| 180 | /*Image can't be updated, while Driver needs to carry the new table! */ | ||
| 181 | } ATOM_COMMON_TABLE_HEADER; | ||
| 182 | |||
| 183 | typedef struct _ATOM_ROM_HEADER { | ||
| 184 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 185 | UCHAR uaFirmWareSignature[4]; /*Signature to distinguish between Atombios and non-atombios, | ||
| 186 | atombios should init it as "ATOM", don't change the position */ | ||
| 187 | USHORT usBiosRuntimeSegmentAddress; | ||
| 188 | USHORT usProtectedModeInfoOffset; | ||
| 189 | USHORT usConfigFilenameOffset; | ||
| 190 | USHORT usCRC_BlockOffset; | ||
| 191 | USHORT usBIOS_BootupMessageOffset; | ||
| 192 | USHORT usInt10Offset; | ||
| 193 | USHORT usPciBusDevInitCode; | ||
| 194 | USHORT usIoBaseAddress; | ||
| 195 | USHORT usSubsystemVendorID; | ||
| 196 | USHORT usSubsystemID; | ||
| 197 | USHORT usPCI_InfoOffset; | ||
| 198 | USHORT usMasterCommandTableOffset; /*Offset for SW to get all command table offsets, Don't change the position */ | ||
| 199 | USHORT usMasterDataTableOffset; /*Offset for SW to get all data table offsets, Don't change the position */ | ||
| 200 | UCHAR ucExtendedFunctionCode; | ||
| 201 | UCHAR ucReserved; | ||
| 202 | } ATOM_ROM_HEADER; | ||
| 203 | |||
| 204 | /*==============================Command Table Portion==================================== */ | ||
| 205 | |||
| 206 | #ifdef UEFI_BUILD | ||
| 207 | #define UTEMP USHORT | ||
| 208 | #define USHORT void* | ||
| 209 | #endif | ||
| 210 | |||
| 211 | typedef struct _ATOM_MASTER_LIST_OF_COMMAND_TABLES { | ||
| 212 | USHORT ASIC_Init; /* Function Table, used by various SW components,latest version 1.1 */ | ||
| 213 | USHORT GetDisplaySurfaceSize; /* Atomic Table, Used by Bios when enabling HW ICON */ | ||
| 214 | USHORT ASIC_RegistersInit; /* Atomic Table, indirectly used by various SW components,called from ASIC_Init */ | ||
| 215 | USHORT VRAM_BlockVenderDetection; /* Atomic Table, used only by Bios */ | ||
| 216 | USHORT DIGxEncoderControl; /* Only used by Bios */ | ||
| 217 | USHORT MemoryControllerInit; /* Atomic Table, indirectly used by various SW components,called from ASIC_Init */ | ||
| 218 | USHORT EnableCRTCMemReq; /* Function Table,directly used by various SW components,latest version 2.1 */ | ||
| 219 | USHORT MemoryParamAdjust; /* Atomic Table, indirectly used by various SW components,called from SetMemoryClock if needed */ | ||
| 220 | USHORT DVOEncoderControl; /* Function Table,directly used by various SW components,latest version 1.2 */ | ||
| 221 | USHORT GPIOPinControl; /* Atomic Table, only used by Bios */ | ||
| 222 | USHORT SetEngineClock; /*Function Table,directly used by various SW components,latest version 1.1 */ | ||
| 223 | USHORT SetMemoryClock; /* Function Table,directly used by various SW components,latest version 1.1 */ | ||
| 224 | USHORT SetPixelClock; /*Function Table,directly used by various SW components,latest version 1.2 */ | ||
| 225 | USHORT DynamicClockGating; /* Atomic Table, indirectly used by various SW components,called from ASIC_Init */ | ||
| 226 | USHORT ResetMemoryDLL; /* Atomic Table, indirectly used by various SW components,called from SetMemoryClock */ | ||
| 227 | USHORT ResetMemoryDevice; /* Atomic Table, indirectly used by various SW components,called from SetMemoryClock */ | ||
| 228 | USHORT MemoryPLLInit; | ||
| 229 | USHORT AdjustDisplayPll; /* only used by Bios */ | ||
| 230 | USHORT AdjustMemoryController; /* Atomic Table, indirectly used by various SW components,called from SetMemoryClock */ | ||
| 231 | USHORT EnableASIC_StaticPwrMgt; /* Atomic Table, only used by Bios */ | ||
| 232 | USHORT ASIC_StaticPwrMgtStatusChange; /* Obsolete, only used by Bios */ | ||
| 233 | USHORT DAC_LoadDetection; /* Atomic Table, directly used by various SW components,latest version 1.2 */ | ||
| 234 | USHORT LVTMAEncoderControl; /* Atomic Table,directly used by various SW components,latest version 1.3 */ | ||
| 235 | USHORT LCD1OutputControl; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 236 | USHORT DAC1EncoderControl; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 237 | USHORT DAC2EncoderControl; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 238 | USHORT DVOOutputControl; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 239 | USHORT CV1OutputControl; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 240 | USHORT GetConditionalGoldenSetting; /* only used by Bios */ | ||
| 241 | USHORT TVEncoderControl; /* Function Table,directly used by various SW components,latest version 1.1 */ | ||
| 242 | USHORT TMDSAEncoderControl; /* Atomic Table, directly used by various SW components,latest version 1.3 */ | ||
| 243 | USHORT LVDSEncoderControl; /* Atomic Table, directly used by various SW components,latest version 1.3 */ | ||
| 244 | USHORT TV1OutputControl; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 245 | USHORT EnableScaler; /* Atomic Table, used only by Bios */ | ||
| 246 | USHORT BlankCRTC; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 247 | USHORT EnableCRTC; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 248 | USHORT GetPixelClock; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 249 | USHORT EnableVGA_Render; /* Function Table,directly used by various SW components,latest version 1.1 */ | ||
| 250 | USHORT EnableVGA_Access; /* Obsolete , only used by Bios */ | ||
| 251 | USHORT SetCRTC_Timing; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 252 | USHORT SetCRTC_OverScan; /* Atomic Table, used by various SW components,latest version 1.1 */ | ||
| 253 | USHORT SetCRTC_Replication; /* Atomic Table, used only by Bios */ | ||
| 254 | USHORT SelectCRTC_Source; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 255 | USHORT EnableGraphSurfaces; /* Atomic Table, used only by Bios */ | ||
| 256 | USHORT UpdateCRTC_DoubleBufferRegisters; | ||
| 257 | USHORT LUT_AutoFill; /* Atomic Table, only used by Bios */ | ||
| 258 | USHORT EnableHW_IconCursor; /* Atomic Table, only used by Bios */ | ||
| 259 | USHORT GetMemoryClock; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 260 | USHORT GetEngineClock; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 261 | USHORT SetCRTC_UsingDTDTiming; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 262 | USHORT ExternalEncoderControl; /* Atomic Table, directly used by various SW components,latest version 2.1 */ | ||
| 263 | USHORT LVTMAOutputControl; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 264 | USHORT VRAM_BlockDetectionByStrap; /* Atomic Table, used only by Bios */ | ||
| 265 | USHORT MemoryCleanUp; /* Atomic Table, only used by Bios */ | ||
| 266 | USHORT ProcessI2cChannelTransaction; /* Function Table,only used by Bios */ | ||
| 267 | USHORT WriteOneByteToHWAssistedI2C; /* Function Table,indirectly used by various SW components */ | ||
| 268 | USHORT ReadHWAssistedI2CStatus; /* Atomic Table, indirectly used by various SW components */ | ||
| 269 | USHORT SpeedFanControl; /* Function Table,indirectly used by various SW components,called from ASIC_Init */ | ||
| 270 | USHORT PowerConnectorDetection; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 271 | USHORT MC_Synchronization; /* Atomic Table, indirectly used by various SW components,called from SetMemoryClock */ | ||
| 272 | USHORT ComputeMemoryEnginePLL; /* Atomic Table, indirectly used by various SW components,called from SetMemory/EngineClock */ | ||
| 273 | USHORT MemoryRefreshConversion; /* Atomic Table, indirectly used by various SW components,called from SetMemory or SetEngineClock */ | ||
| 274 | USHORT VRAM_GetCurrentInfoBlock; /* Atomic Table, used only by Bios */ | ||
| 275 | USHORT DynamicMemorySettings; /* Atomic Table, indirectly used by various SW components,called from SetMemoryClock */ | ||
| 276 | USHORT MemoryTraining; /* Atomic Table, used only by Bios */ | ||
| 277 | USHORT EnableSpreadSpectrumOnPPLL; /* Atomic Table, directly used by various SW components,latest version 1.2 */ | ||
| 278 | USHORT TMDSAOutputControl; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 279 | USHORT SetVoltage; /* Function Table,directly and/or indirectly used by various SW components,latest version 1.1 */ | ||
| 280 | USHORT DAC1OutputControl; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 281 | USHORT DAC2OutputControl; /* Atomic Table, directly used by various SW components,latest version 1.1 */ | ||
| 282 | USHORT SetupHWAssistedI2CStatus; /* Function Table,only used by Bios, obsolete soon.Switch to use "ReadEDIDFromHWAssistedI2C" */ | ||
| 283 | USHORT ClockSource; /* Atomic Table, indirectly used by various SW components,called from ASIC_Init */ | ||
| 284 | USHORT MemoryDeviceInit; /* Atomic Table, indirectly used by various SW components,called from SetMemoryClock */ | ||
| 285 | USHORT EnableYUV; /* Atomic Table, indirectly used by various SW components,called from EnableVGARender */ | ||
| 286 | USHORT DIG1EncoderControl; /* Atomic Table,directly used by various SW components,latest version 1.1 */ | ||
| 287 | USHORT DIG2EncoderControl; /* Atomic Table,directly used by various SW components,latest version 1.1 */ | ||
| 288 | USHORT DIG1TransmitterControl; /* Atomic Table,directly used by various SW components,latest version 1.1 */ | ||
| 289 | USHORT DIG2TransmitterControl; /* Atomic Table,directly used by various SW components,latest version 1.1 */ | ||
| 290 | USHORT ProcessAuxChannelTransaction; /* Function Table,only used by Bios */ | ||
| 291 | USHORT DPEncoderService; /* Function Table,only used by Bios */ | ||
| 292 | } ATOM_MASTER_LIST_OF_COMMAND_TABLES; | ||
| 293 | |||
| 294 | /* For backward compatible */ | ||
| 295 | #define ReadEDIDFromHWAssistedI2C ProcessI2cChannelTransaction | ||
| 296 | #define UNIPHYTransmitterControl DIG1TransmitterControl | ||
| 297 | #define LVTMATransmitterControl DIG2TransmitterControl | ||
| 298 | #define SetCRTC_DPM_State GetConditionalGoldenSetting | ||
| 299 | #define SetUniphyInstance ASIC_StaticPwrMgtStatusChange | ||
| 300 | |||
| 301 | typedef struct _ATOM_MASTER_COMMAND_TABLE { | ||
| 302 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 303 | ATOM_MASTER_LIST_OF_COMMAND_TABLES ListOfCommandTables; | ||
| 304 | } ATOM_MASTER_COMMAND_TABLE; | ||
| 305 | |||
| 306 | /****************************************************************************/ | ||
| 307 | /* Structures used in every command table */ | ||
| 308 | /****************************************************************************/ | ||
| 309 | typedef struct _ATOM_TABLE_ATTRIBUTE { | ||
| 310 | #if ATOM_BIG_ENDIAN | ||
| 311 | USHORT UpdatedByUtility:1; /* [15]=Table updated by utility flag */ | ||
| 312 | USHORT PS_SizeInBytes:7; /* [14:8]=Size of parameter space in Bytes (multiple of a dword), */ | ||
| 313 | USHORT WS_SizeInBytes:8; /* [7:0]=Size of workspace in Bytes (in multiple of a dword), */ | ||
| 314 | #else | ||
| 315 | USHORT WS_SizeInBytes:8; /* [7:0]=Size of workspace in Bytes (in multiple of a dword), */ | ||
| 316 | USHORT PS_SizeInBytes:7; /* [14:8]=Size of parameter space in Bytes (multiple of a dword), */ | ||
| 317 | USHORT UpdatedByUtility:1; /* [15]=Table updated by utility flag */ | ||
| 318 | #endif | ||
| 319 | } ATOM_TABLE_ATTRIBUTE; | ||
| 320 | |||
| 321 | typedef union _ATOM_TABLE_ATTRIBUTE_ACCESS { | ||
| 322 | ATOM_TABLE_ATTRIBUTE sbfAccess; | ||
| 323 | USHORT susAccess; | ||
| 324 | } ATOM_TABLE_ATTRIBUTE_ACCESS; | ||
| 325 | |||
| 326 | /****************************************************************************/ | ||
| 327 | /* Common header for all command tables. */ | ||
| 328 | /* Every table pointed by _ATOM_MASTER_COMMAND_TABLE has this common header. */ | ||
| 329 | /* And the pointer actually points to this header. */ | ||
| 330 | /****************************************************************************/ | ||
| 331 | typedef struct _ATOM_COMMON_ROM_COMMAND_TABLE_HEADER { | ||
| 332 | ATOM_COMMON_TABLE_HEADER CommonHeader; | ||
| 333 | ATOM_TABLE_ATTRIBUTE TableAttribute; | ||
| 334 | } ATOM_COMMON_ROM_COMMAND_TABLE_HEADER; | ||
| 335 | |||
| 336 | /****************************************************************************/ | ||
| 337 | /* Structures used by ComputeMemoryEnginePLLTable */ | ||
| 338 | /****************************************************************************/ | ||
| 339 | #define COMPUTE_MEMORY_PLL_PARAM 1 | ||
| 340 | #define COMPUTE_ENGINE_PLL_PARAM 2 | ||
| 341 | |||
| 342 | typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS { | ||
| 343 | ULONG ulClock; /* When returen, it's the re-calculated clock based on given Fb_div Post_Div and ref_div */ | ||
| 344 | UCHAR ucAction; /* 0:reserved //1:Memory //2:Engine */ | ||
| 345 | UCHAR ucReserved; /* may expand to return larger Fbdiv later */ | ||
| 346 | UCHAR ucFbDiv; /* return value */ | ||
| 347 | UCHAR ucPostDiv; /* return value */ | ||
| 348 | } COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS; | ||
| 349 | |||
| 350 | typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V2 { | ||
| 351 | ULONG ulClock; /* When return, [23:0] return real clock */ | ||
| 352 | UCHAR ucAction; /* 0:reserved;COMPUTE_MEMORY_PLL_PARAM:Memory;COMPUTE_ENGINE_PLL_PARAM:Engine. it return ref_div to be written to register */ | ||
| 353 | USHORT usFbDiv; /* return Feedback value to be written to register */ | ||
| 354 | UCHAR ucPostDiv; /* return post div to be written to register */ | ||
| 355 | } COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V2; | ||
| 356 | #define COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_PS_ALLOCATION COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS | ||
| 357 | |||
| 358 | #define SET_CLOCK_FREQ_MASK 0x00FFFFFF /* Clock change tables only take bit [23:0] as the requested clock value */ | ||
| 359 | #define USE_NON_BUS_CLOCK_MASK 0x01000000 /* Applicable to both memory and engine clock change, when set, it uses another clock as the temporary clock (engine uses memory and vice versa) */ | ||
| 360 | #define USE_MEMORY_SELF_REFRESH_MASK 0x02000000 /* Only applicable to memory clock change, when set, using memory self refresh during clock transition */ | ||
| 361 | #define SKIP_INTERNAL_MEMORY_PARAMETER_CHANGE 0x04000000 /* Only applicable to memory clock change, when set, the table will skip predefined internal memory parameter change */ | ||
| 362 | #define FIRST_TIME_CHANGE_CLOCK 0x08000000 /* Applicable to both memory and engine clock change,when set, it means this is 1st time to change clock after ASIC bootup */ | ||
| 363 | #define SKIP_SW_PROGRAM_PLL 0x10000000 /* Applicable to both memory and engine clock change, when set, it means the table will not program SPLL/MPLL */ | ||
| 364 | #define USE_SS_ENABLED_PIXEL_CLOCK USE_NON_BUS_CLOCK_MASK | ||
| 365 | |||
| 366 | #define b3USE_NON_BUS_CLOCK_MASK 0x01 /* Applicable to both memory and engine clock change, when set, it uses another clock as the temporary clock (engine uses memory and vice versa) */ | ||
| 367 | #define b3USE_MEMORY_SELF_REFRESH 0x02 /* Only applicable to memory clock change, when set, using memory self refresh during clock transition */ | ||
| 368 | #define b3SKIP_INTERNAL_MEMORY_PARAMETER_CHANGE 0x04 /* Only applicable to memory clock change, when set, the table will skip predefined internal memory parameter change */ | ||
| 369 | #define b3FIRST_TIME_CHANGE_CLOCK 0x08 /* Applicable to both memory and engine clock change,when set, it means this is 1st time to change clock after ASIC bootup */ | ||
| 370 | #define b3SKIP_SW_PROGRAM_PLL 0x10 /* Applicable to both memory and engine clock change, when set, it means the table will not program SPLL/MPLL */ | ||
| 371 | |||
| 372 | typedef struct _ATOM_COMPUTE_CLOCK_FREQ { | ||
| 373 | #if ATOM_BIG_ENDIAN | ||
| 374 | ULONG ulComputeClockFlag:8; /* =1: COMPUTE_MEMORY_PLL_PARAM, =2: COMPUTE_ENGINE_PLL_PARAM */ | ||
| 375 | ULONG ulClockFreq:24; /* in unit of 10kHz */ | ||
| 376 | #else | ||
| 377 | ULONG ulClockFreq:24; /* in unit of 10kHz */ | ||
| 378 | ULONG ulComputeClockFlag:8; /* =1: COMPUTE_MEMORY_PLL_PARAM, =2: COMPUTE_ENGINE_PLL_PARAM */ | ||
| 379 | #endif | ||
| 380 | } ATOM_COMPUTE_CLOCK_FREQ; | ||
| 381 | |||
| 382 | typedef struct _ATOM_S_MPLL_FB_DIVIDER { | ||
| 383 | USHORT usFbDivFrac; | ||
| 384 | USHORT usFbDiv; | ||
| 385 | } ATOM_S_MPLL_FB_DIVIDER; | ||
| 386 | |||
| 387 | typedef struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3 { | ||
| 388 | union { | ||
| 389 | ATOM_COMPUTE_CLOCK_FREQ ulClock; /* Input Parameter */ | ||
| 390 | ATOM_S_MPLL_FB_DIVIDER ulFbDiv; /* Output Parameter */ | ||
| 391 | }; | ||
| 392 | UCHAR ucRefDiv; /* Output Parameter */ | ||
| 393 | UCHAR ucPostDiv; /* Output Parameter */ | ||
| 394 | UCHAR ucCntlFlag; /* Output Parameter */ | ||
| 395 | UCHAR ucReserved; | ||
| 396 | } COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3; | ||
| 397 | |||
| 398 | /* ucCntlFlag */ | ||
| 399 | #define ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN 1 | ||
| 400 | #define ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE 2 | ||
| 401 | #define ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE 4 | ||
| 402 | |||
| 403 | typedef struct _DYNAMICE_MEMORY_SETTINGS_PARAMETER { | ||
| 404 | ATOM_COMPUTE_CLOCK_FREQ ulClock; | ||
| 405 | ULONG ulReserved[2]; | ||
| 406 | } DYNAMICE_MEMORY_SETTINGS_PARAMETER; | ||
| 407 | |||
| 408 | typedef struct _DYNAMICE_ENGINE_SETTINGS_PARAMETER { | ||
| 409 | ATOM_COMPUTE_CLOCK_FREQ ulClock; | ||
| 410 | ULONG ulMemoryClock; | ||
| 411 | ULONG ulReserved; | ||
| 412 | } DYNAMICE_ENGINE_SETTINGS_PARAMETER; | ||
| 413 | |||
| 414 | /****************************************************************************/ | ||
| 415 | /* Structures used by SetEngineClockTable */ | ||
| 416 | /****************************************************************************/ | ||
| 417 | typedef struct _SET_ENGINE_CLOCK_PARAMETERS { | ||
| 418 | ULONG ulTargetEngineClock; /* In 10Khz unit */ | ||
| 419 | } SET_ENGINE_CLOCK_PARAMETERS; | ||
| 420 | |||
| 421 | typedef struct _SET_ENGINE_CLOCK_PS_ALLOCATION { | ||
| 422 | ULONG ulTargetEngineClock; /* In 10Khz unit */ | ||
| 423 | COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_PS_ALLOCATION sReserved; | ||
| 424 | } SET_ENGINE_CLOCK_PS_ALLOCATION; | ||
| 425 | |||
| 426 | /****************************************************************************/ | ||
| 427 | /* Structures used by SetMemoryClockTable */ | ||
| 428 | /****************************************************************************/ | ||
| 429 | typedef struct _SET_MEMORY_CLOCK_PARAMETERS { | ||
| 430 | ULONG ulTargetMemoryClock; /* In 10Khz unit */ | ||
| 431 | } SET_MEMORY_CLOCK_PARAMETERS; | ||
| 432 | |||
| 433 | typedef struct _SET_MEMORY_CLOCK_PS_ALLOCATION { | ||
| 434 | ULONG ulTargetMemoryClock; /* In 10Khz unit */ | ||
| 435 | COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_PS_ALLOCATION sReserved; | ||
| 436 | } SET_MEMORY_CLOCK_PS_ALLOCATION; | ||
| 437 | |||
| 438 | /****************************************************************************/ | ||
| 439 | /* Structures used by ASIC_Init.ctb */ | ||
| 440 | /****************************************************************************/ | ||
| 441 | typedef struct _ASIC_INIT_PARAMETERS { | ||
| 442 | ULONG ulDefaultEngineClock; /* In 10Khz unit */ | ||
| 443 | ULONG ulDefaultMemoryClock; /* In 10Khz unit */ | ||
| 444 | } ASIC_INIT_PARAMETERS; | ||
| 445 | |||
| 446 | typedef struct _ASIC_INIT_PS_ALLOCATION { | ||
| 447 | ASIC_INIT_PARAMETERS sASICInitClocks; | ||
| 448 | SET_ENGINE_CLOCK_PS_ALLOCATION sReserved; /* Caller doesn't need to init this structure */ | ||
| 449 | } ASIC_INIT_PS_ALLOCATION; | ||
| 450 | |||
| 451 | /****************************************************************************/ | ||
| 452 | /* Structure used by DynamicClockGatingTable.ctb */ | ||
| 453 | /****************************************************************************/ | ||
| 454 | typedef struct _DYNAMIC_CLOCK_GATING_PARAMETERS { | ||
| 455 | UCHAR ucEnable; /* ATOM_ENABLE or ATOM_DISABLE */ | ||
| 456 | UCHAR ucPadding[3]; | ||
| 457 | } DYNAMIC_CLOCK_GATING_PARAMETERS; | ||
| 458 | #define DYNAMIC_CLOCK_GATING_PS_ALLOCATION DYNAMIC_CLOCK_GATING_PARAMETERS | ||
| 459 | |||
| 460 | /****************************************************************************/ | ||
| 461 | /* Structure used by EnableASIC_StaticPwrMgtTable.ctb */ | ||
| 462 | /****************************************************************************/ | ||
| 463 | typedef struct _ENABLE_ASIC_STATIC_PWR_MGT_PARAMETERS { | ||
| 464 | UCHAR ucEnable; /* ATOM_ENABLE or ATOM_DISABLE */ | ||
| 465 | UCHAR ucPadding[3]; | ||
| 466 | } ENABLE_ASIC_STATIC_PWR_MGT_PARAMETERS; | ||
| 467 | #define ENABLE_ASIC_STATIC_PWR_MGT_PS_ALLOCATION ENABLE_ASIC_STATIC_PWR_MGT_PARAMETERS | ||
| 468 | |||
| 469 | /****************************************************************************/ | ||
| 470 | /* Structures used by DAC_LoadDetectionTable.ctb */ | ||
| 471 | /****************************************************************************/ | ||
| 472 | typedef struct _DAC_LOAD_DETECTION_PARAMETERS { | ||
| 473 | USHORT usDeviceID; /* {ATOM_DEVICE_CRTx_SUPPORT,ATOM_DEVICE_TVx_SUPPORT,ATOM_DEVICE_CVx_SUPPORT} */ | ||
| 474 | UCHAR ucDacType; /* {ATOM_DAC_A,ATOM_DAC_B, ATOM_EXT_DAC} */ | ||
| 475 | UCHAR ucMisc; /* Valid only when table revision =1.3 and above */ | ||
| 476 | } DAC_LOAD_DETECTION_PARAMETERS; | ||
| 477 | |||
| 478 | /* DAC_LOAD_DETECTION_PARAMETERS.ucMisc */ | ||
| 479 | #define DAC_LOAD_MISC_YPrPb 0x01 | ||
| 480 | |||
| 481 | typedef struct _DAC_LOAD_DETECTION_PS_ALLOCATION { | ||
| 482 | DAC_LOAD_DETECTION_PARAMETERS sDacload; | ||
| 483 | ULONG Reserved[2]; /* Don't set this one, allocation for EXT DAC */ | ||
| 484 | } DAC_LOAD_DETECTION_PS_ALLOCATION; | ||
| 485 | |||
| 486 | /****************************************************************************/ | ||
| 487 | /* Structures used by DAC1EncoderControlTable.ctb and DAC2EncoderControlTable.ctb */ | ||
| 488 | /****************************************************************************/ | ||
| 489 | typedef struct _DAC_ENCODER_CONTROL_PARAMETERS { | ||
| 490 | USHORT usPixelClock; /* in 10KHz; for bios convenient */ | ||
| 491 | UCHAR ucDacStandard; /* See definition of ATOM_DACx_xxx, For DEC3.0, bit 7 used as internal flag to indicate DAC2 (==1) or DAC1 (==0) */ | ||
| 492 | UCHAR ucAction; /* 0: turn off encoder */ | ||
| 493 | /* 1: setup and turn on encoder */ | ||
| 494 | /* 7: ATOM_ENCODER_INIT Initialize DAC */ | ||
| 495 | } DAC_ENCODER_CONTROL_PARAMETERS; | ||
| 496 | |||
| 497 | #define DAC_ENCODER_CONTROL_PS_ALLOCATION DAC_ENCODER_CONTROL_PARAMETERS | ||
| 498 | |||
| 499 | /****************************************************************************/ | ||
| 500 | /* Structures used by DIG1EncoderControlTable */ | ||
| 501 | /* DIG2EncoderControlTable */ | ||
| 502 | /* ExternalEncoderControlTable */ | ||
| 503 | /****************************************************************************/ | ||
| 504 | typedef struct _DIG_ENCODER_CONTROL_PARAMETERS { | ||
| 505 | USHORT usPixelClock; /* in 10KHz; for bios convenient */ | ||
| 506 | UCHAR ucConfig; | ||
| 507 | /* [2] Link Select: */ | ||
| 508 | /* =0: PHY linkA if bfLane<3 */ | ||
| 509 | /* =1: PHY linkB if bfLanes<3 */ | ||
| 510 | /* =0: PHY linkA+B if bfLanes=3 */ | ||
| 511 | /* [3] Transmitter Sel */ | ||
| 512 | /* =0: UNIPHY or PCIEPHY */ | ||
| 513 | /* =1: LVTMA */ | ||
| 514 | UCHAR ucAction; /* =0: turn off encoder */ | ||
| 515 | /* =1: turn on encoder */ | ||
| 516 | UCHAR ucEncoderMode; | ||
| 517 | /* =0: DP encoder */ | ||
| 518 | /* =1: LVDS encoder */ | ||
| 519 | /* =2: DVI encoder */ | ||
| 520 | /* =3: HDMI encoder */ | ||
| 521 | /* =4: SDVO encoder */ | ||
| 522 | UCHAR ucLaneNum; /* how many lanes to enable */ | ||
| 523 | UCHAR ucReserved[2]; | ||
| 524 | } DIG_ENCODER_CONTROL_PARAMETERS; | ||
| 525 | #define DIG_ENCODER_CONTROL_PS_ALLOCATION DIG_ENCODER_CONTROL_PARAMETERS | ||
| 526 | #define EXTERNAL_ENCODER_CONTROL_PARAMETER DIG_ENCODER_CONTROL_PARAMETERS | ||
| 527 | |||
| 528 | /* ucConfig */ | ||
| 529 | #define ATOM_ENCODER_CONFIG_DPLINKRATE_MASK 0x01 | ||
| 530 | #define ATOM_ENCODER_CONFIG_DPLINKRATE_1_62GHZ 0x00 | ||
| 531 | #define ATOM_ENCODER_CONFIG_DPLINKRATE_2_70GHZ 0x01 | ||
| 532 | #define ATOM_ENCODER_CONFIG_LINK_SEL_MASK 0x04 | ||
| 533 | #define ATOM_ENCODER_CONFIG_LINKA 0x00 | ||
| 534 | #define ATOM_ENCODER_CONFIG_LINKB 0x04 | ||
| 535 | #define ATOM_ENCODER_CONFIG_LINKA_B ATOM_TRANSMITTER_CONFIG_LINKA | ||
| 536 | #define ATOM_ENCODER_CONFIG_LINKB_A ATOM_ENCODER_CONFIG_LINKB | ||
| 537 | #define ATOM_ENCODER_CONFIG_TRANSMITTER_SEL_MASK 0x08 | ||
| 538 | #define ATOM_ENCODER_CONFIG_UNIPHY 0x00 | ||
| 539 | #define ATOM_ENCODER_CONFIG_LVTMA 0x08 | ||
| 540 | #define ATOM_ENCODER_CONFIG_TRANSMITTER1 0x00 | ||
| 541 | #define ATOM_ENCODER_CONFIG_TRANSMITTER2 0x08 | ||
| 542 | #define ATOM_ENCODER_CONFIG_DIGB 0x80 /* VBIOS Internal use, outside SW should set this bit=0 */ | ||
| 543 | /* ucAction */ | ||
| 544 | /* ATOM_ENABLE: Enable Encoder */ | ||
| 545 | /* ATOM_DISABLE: Disable Encoder */ | ||
| 546 | |||
| 547 | /* ucEncoderMode */ | ||
| 548 | #define ATOM_ENCODER_MODE_DP 0 | ||
| 549 | #define ATOM_ENCODER_MODE_LVDS 1 | ||
| 550 | #define ATOM_ENCODER_MODE_DVI 2 | ||
| 551 | #define ATOM_ENCODER_MODE_HDMI 3 | ||
| 552 | #define ATOM_ENCODER_MODE_SDVO 4 | ||
| 553 | #define ATOM_ENCODER_MODE_TV 13 | ||
| 554 | #define ATOM_ENCODER_MODE_CV 14 | ||
| 555 | #define ATOM_ENCODER_MODE_CRT 15 | ||
| 556 | |||
| 557 | typedef struct _ATOM_DIG_ENCODER_CONFIG_V2 { | ||
| 558 | #if ATOM_BIG_ENDIAN | ||
| 559 | UCHAR ucReserved1:2; | ||
| 560 | UCHAR ucTransmitterSel:2; /* =0: UniphyAB, =1: UniphyCD =2: UniphyEF */ | ||
| 561 | UCHAR ucLinkSel:1; /* =0: linkA/C/E =1: linkB/D/F */ | ||
| 562 | UCHAR ucReserved:1; | ||
| 563 | UCHAR ucDPLinkRate:1; /* =0: 1.62Ghz, =1: 2.7Ghz */ | ||
| 564 | #else | ||
| 565 | UCHAR ucDPLinkRate:1; /* =0: 1.62Ghz, =1: 2.7Ghz */ | ||
| 566 | UCHAR ucReserved:1; | ||
| 567 | UCHAR ucLinkSel:1; /* =0: linkA/C/E =1: linkB/D/F */ | ||
| 568 | UCHAR ucTransmitterSel:2; /* =0: UniphyAB, =1: UniphyCD =2: UniphyEF */ | ||
| 569 | UCHAR ucReserved1:2; | ||
| 570 | #endif | ||
| 571 | } ATOM_DIG_ENCODER_CONFIG_V2; | ||
| 572 | |||
| 573 | typedef struct _DIG_ENCODER_CONTROL_PARAMETERS_V2 { | ||
| 574 | USHORT usPixelClock; /* in 10KHz; for bios convenient */ | ||
| 575 | ATOM_DIG_ENCODER_CONFIG_V2 acConfig; | ||
| 576 | UCHAR ucAction; | ||
| 577 | UCHAR ucEncoderMode; | ||
| 578 | /* =0: DP encoder */ | ||
| 579 | /* =1: LVDS encoder */ | ||
| 580 | /* =2: DVI encoder */ | ||
| 581 | /* =3: HDMI encoder */ | ||
| 582 | /* =4: SDVO encoder */ | ||
| 583 | UCHAR ucLaneNum; /* how many lanes to enable */ | ||
| 584 | UCHAR ucReserved[2]; | ||
| 585 | } DIG_ENCODER_CONTROL_PARAMETERS_V2; | ||
| 586 | |||
| 587 | /* ucConfig */ | ||
| 588 | #define ATOM_ENCODER_CONFIG_V2_DPLINKRATE_MASK 0x01 | ||
| 589 | #define ATOM_ENCODER_CONFIG_V2_DPLINKRATE_1_62GHZ 0x00 | ||
| 590 | #define ATOM_ENCODER_CONFIG_V2_DPLINKRATE_2_70GHZ 0x01 | ||
| 591 | #define ATOM_ENCODER_CONFIG_V2_LINK_SEL_MASK 0x04 | ||
| 592 | #define ATOM_ENCODER_CONFIG_V2_LINKA 0x00 | ||
| 593 | #define ATOM_ENCODER_CONFIG_V2_LINKB 0x04 | ||
| 594 | #define ATOM_ENCODER_CONFIG_V2_TRANSMITTER_SEL_MASK 0x18 | ||
| 595 | #define ATOM_ENCODER_CONFIG_V2_TRANSMITTER1 0x00 | ||
| 596 | #define ATOM_ENCODER_CONFIG_V2_TRANSMITTER2 0x08 | ||
| 597 | #define ATOM_ENCODER_CONFIG_V2_TRANSMITTER3 0x10 | ||
| 598 | |||
| 599 | /****************************************************************************/ | ||
| 600 | /* Structures used by UNIPHYTransmitterControlTable */ | ||
| 601 | /* LVTMATransmitterControlTable */ | ||
| 602 | /* DVOOutputControlTable */ | ||
| 603 | /****************************************************************************/ | ||
| 604 | typedef struct _ATOM_DP_VS_MODE { | ||
| 605 | UCHAR ucLaneSel; | ||
| 606 | UCHAR ucLaneSet; | ||
| 607 | } ATOM_DP_VS_MODE; | ||
| 608 | |||
| 609 | typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS { | ||
| 610 | union { | ||
| 611 | USHORT usPixelClock; /* in 10KHz; for bios convenient */ | ||
| 612 | USHORT usInitInfo; /* when init uniphy,lower 8bit is used for connector type defined in objectid.h */ | ||
| 613 | ATOM_DP_VS_MODE asMode; /* DP Voltage swing mode */ | ||
| 614 | }; | ||
| 615 | UCHAR ucConfig; | ||
| 616 | /* [0]=0: 4 lane Link, */ | ||
| 617 | /* =1: 8 lane Link ( Dual Links TMDS ) */ | ||
| 618 | /* [1]=0: InCoherent mode */ | ||
| 619 | /* =1: Coherent Mode */ | ||
| 620 | /* [2] Link Select: */ | ||
| 621 | /* =0: PHY linkA if bfLane<3 */ | ||
| 622 | /* =1: PHY linkB if bfLanes<3 */ | ||
| 623 | /* =0: PHY linkA+B if bfLanes=3 */ | ||
| 624 | /* [5:4]PCIE lane Sel */ | ||
| 625 | /* =0: lane 0~3 or 0~7 */ | ||
| 626 | /* =1: lane 4~7 */ | ||
| 627 | /* =2: lane 8~11 or 8~15 */ | ||
| 628 | /* =3: lane 12~15 */ | ||
| 629 | UCHAR ucAction; /* =0: turn off encoder */ | ||
| 630 | /* =1: turn on encoder */ | ||
| 631 | UCHAR ucReserved[4]; | ||
| 632 | } DIG_TRANSMITTER_CONTROL_PARAMETERS; | ||
| 633 | |||
| 634 | #define DIG_TRANSMITTER_CONTROL_PS_ALLOCATION DIG_TRANSMITTER_CONTROL_PARAMETERS | ||
| 635 | |||
| 636 | /* ucInitInfo */ | ||
| 637 | #define ATOM_TRAMITTER_INITINFO_CONNECTOR_MASK 0x00ff | ||
| 638 | |||
| 639 | /* ucConfig */ | ||
| 640 | #define ATOM_TRANSMITTER_CONFIG_8LANE_LINK 0x01 | ||
| 641 | #define ATOM_TRANSMITTER_CONFIG_COHERENT 0x02 | ||
| 642 | #define ATOM_TRANSMITTER_CONFIG_LINK_SEL_MASK 0x04 | ||
| 643 | #define ATOM_TRANSMITTER_CONFIG_LINKA 0x00 | ||
| 644 | #define ATOM_TRANSMITTER_CONFIG_LINKB 0x04 | ||
| 645 | #define ATOM_TRANSMITTER_CONFIG_LINKA_B 0x00 | ||
| 646 | #define ATOM_TRANSMITTER_CONFIG_LINKB_A 0x04 | ||
| 647 | |||
| 648 | #define ATOM_TRANSMITTER_CONFIG_ENCODER_SEL_MASK 0x08 /* only used when ATOM_TRANSMITTER_ACTION_ENABLE */ | ||
| 649 | #define ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER 0x00 /* only used when ATOM_TRANSMITTER_ACTION_ENABLE */ | ||
| 650 | #define ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER 0x08 /* only used when ATOM_TRANSMITTER_ACTION_ENABLE */ | ||
| 651 | |||
| 652 | #define ATOM_TRANSMITTER_CONFIG_CLKSRC_MASK 0x30 | ||
| 653 | #define ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL 0x00 | ||
| 654 | #define ATOM_TRANSMITTER_CONFIG_CLKSRC_PCIE 0x20 | ||
| 655 | #define ATOM_TRANSMITTER_CONFIG_CLKSRC_XTALIN 0x30 | ||
| 656 | #define ATOM_TRANSMITTER_CONFIG_LANE_SEL_MASK 0xc0 | ||
| 657 | #define ATOM_TRANSMITTER_CONFIG_LANE_0_3 0x00 | ||
| 658 | #define ATOM_TRANSMITTER_CONFIG_LANE_0_7 0x00 | ||
| 659 | #define ATOM_TRANSMITTER_CONFIG_LANE_4_7 0x40 | ||
| 660 | #define ATOM_TRANSMITTER_CONFIG_LANE_8_11 0x80 | ||
| 661 | #define ATOM_TRANSMITTER_CONFIG_LANE_8_15 0x80 | ||
| 662 | #define ATOM_TRANSMITTER_CONFIG_LANE_12_15 0xc0 | ||
| 663 | |||
| 664 | /* ucAction */ | ||
| 665 | #define ATOM_TRANSMITTER_ACTION_DISABLE 0 | ||
| 666 | #define ATOM_TRANSMITTER_ACTION_ENABLE 1 | ||
| 667 | #define ATOM_TRANSMITTER_ACTION_LCD_BLOFF 2 | ||
| 668 | #define ATOM_TRANSMITTER_ACTION_LCD_BLON 3 | ||
| 669 | #define ATOM_TRANSMITTER_ACTION_BL_BRIGHTNESS_CONTROL 4 | ||
| 670 | #define ATOM_TRANSMITTER_ACTION_LCD_SELFTEST_START 5 | ||
| 671 | #define ATOM_TRANSMITTER_ACTION_LCD_SELFTEST_STOP 6 | ||
| 672 | #define ATOM_TRANSMITTER_ACTION_INIT 7 | ||
| 673 | #define ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT 8 | ||
| 674 | #define ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT 9 | ||
| 675 | #define ATOM_TRANSMITTER_ACTION_SETUP 10 | ||
| 676 | #define ATOM_TRANSMITTER_ACTION_SETUP_VSEMPH 11 | ||
| 677 | |||
| 678 | /* Following are used for DigTransmitterControlTable ver1.2 */ | ||
| 679 | typedef struct _ATOM_DIG_TRANSMITTER_CONFIG_V2 { | ||
| 680 | #if ATOM_BIG_ENDIAN | ||
| 681 | UCHAR ucTransmitterSel:2; /* bit7:6: =0 Dig Transmitter 1 ( Uniphy AB ) */ | ||
| 682 | /* =1 Dig Transmitter 2 ( Uniphy CD ) */ | ||
| 683 | /* =2 Dig Transmitter 3 ( Uniphy EF ) */ | ||
| 684 | UCHAR ucReserved:1; | ||
| 685 | UCHAR fDPConnector:1; /* bit4=0: DP connector =1: None DP connector */ | ||
| 686 | UCHAR ucEncoderSel:1; /* bit3=0: Data/Clk path source from DIGA( DIG inst0 ). =1: Data/clk path source from DIGB ( DIG inst1 ) */ | ||
| 687 | UCHAR ucLinkSel:1; /* bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E */ | ||
| 688 | /* =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F */ | ||
| 689 | |||
| 690 | UCHAR fCoherentMode:1; /* bit1=1: Coherent Mode ( for DVI/HDMI mode ) */ | ||
| 691 | UCHAR fDualLinkConnector:1; /* bit0=1: Dual Link DVI connector */ | ||
| 692 | #else | ||
| 693 | UCHAR fDualLinkConnector:1; /* bit0=1: Dual Link DVI connector */ | ||
| 694 | UCHAR fCoherentMode:1; /* bit1=1: Coherent Mode ( for DVI/HDMI mode ) */ | ||
| 695 | UCHAR ucLinkSel:1; /* bit2=0: Uniphy LINKA or C or E when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is A or C or E */ | ||
| 696 | /* =1: Uniphy LINKB or D or F when fDualLinkConnector=0. when fDualLinkConnector=1, it means master link of dual link is B or D or F */ | ||
| 697 | UCHAR ucEncoderSel:1; /* bit3=0: Data/Clk path source from DIGA( DIG inst0 ). =1: Data/clk path source from DIGB ( DIG inst1 ) */ | ||
| 698 | UCHAR fDPConnector:1; /* bit4=0: DP connector =1: None DP connector */ | ||
| 699 | UCHAR ucReserved:1; | ||
| 700 | UCHAR ucTransmitterSel:2; /* bit7:6: =0 Dig Transmitter 1 ( Uniphy AB ) */ | ||
| 701 | /* =1 Dig Transmitter 2 ( Uniphy CD ) */ | ||
| 702 | /* =2 Dig Transmitter 3 ( Uniphy EF ) */ | ||
| 703 | #endif | ||
| 704 | } ATOM_DIG_TRANSMITTER_CONFIG_V2; | ||
| 705 | |||
| 706 | /* ucConfig */ | ||
| 707 | /* Bit0 */ | ||
| 708 | #define ATOM_TRANSMITTER_CONFIG_V2_DUAL_LINK_CONNECTOR 0x01 | ||
| 709 | |||
| 710 | /* Bit1 */ | ||
| 711 | #define ATOM_TRANSMITTER_CONFIG_V2_COHERENT 0x02 | ||
| 712 | |||
| 713 | /* Bit2 */ | ||
| 714 | #define ATOM_TRANSMITTER_CONFIG_V2_LINK_SEL_MASK 0x04 | ||
| 715 | #define ATOM_TRANSMITTER_CONFIG_V2_LINKA 0x00 | ||
| 716 | #define ATOM_TRANSMITTER_CONFIG_V2_LINKB 0x04 | ||
| 717 | |||
| 718 | /* Bit3 */ | ||
| 719 | #define ATOM_TRANSMITTER_CONFIG_V2_ENCODER_SEL_MASK 0x08 | ||
| 720 | #define ATOM_TRANSMITTER_CONFIG_V2_DIG1_ENCODER 0x00 /* only used when ucAction == ATOM_TRANSMITTER_ACTION_ENABLE or ATOM_TRANSMITTER_ACTION_SETUP */ | ||
| 721 | #define ATOM_TRANSMITTER_CONFIG_V2_DIG2_ENCODER 0x08 /* only used when ucAction == ATOM_TRANSMITTER_ACTION_ENABLE or ATOM_TRANSMITTER_ACTION_SETUP */ | ||
| 722 | |||
| 723 | /* Bit4 */ | ||
| 724 | #define ATOM_TRASMITTER_CONFIG_V2_DP_CONNECTOR 0x10 | ||
| 725 | |||
| 726 | /* Bit7:6 */ | ||
| 727 | #define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER_SEL_MASK 0xC0 | ||
| 728 | #define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER1 0x00 /* AB */ | ||
| 729 | #define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER2 0x40 /* CD */ | ||
| 730 | #define ATOM_TRANSMITTER_CONFIG_V2_TRANSMITTER3 0x80 /* EF */ | ||
| 731 | |||
| 732 | typedef struct _DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 { | ||
| 733 | union { | ||
| 734 | USHORT usPixelClock; /* in 10KHz; for bios convenient */ | ||
| 735 | USHORT usInitInfo; /* when init uniphy,lower 8bit is used for connector type defined in objectid.h */ | ||
| 736 | ATOM_DP_VS_MODE asMode; /* DP Voltage swing mode */ | ||
| 737 | }; | ||
| 738 | ATOM_DIG_TRANSMITTER_CONFIG_V2 acConfig; | ||
| 739 | UCHAR ucAction; /* define as ATOM_TRANSMITER_ACTION_XXX */ | ||
| 740 | UCHAR ucReserved[4]; | ||
| 741 | } DIG_TRANSMITTER_CONTROL_PARAMETERS_V2; | ||
| 742 | |||
| 743 | /****************************************************************************/ | ||
| 744 | /* Structures used by DAC1OuputControlTable */ | ||
| 745 | /* DAC2OuputControlTable */ | ||
| 746 | /* LVTMAOutputControlTable (Before DEC30) */ | ||
| 747 | /* TMDSAOutputControlTable (Before DEC30) */ | ||
| 748 | /****************************************************************************/ | ||
| 749 | typedef struct _DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS { | ||
| 750 | UCHAR ucAction; /* Possible input:ATOM_ENABLE||ATOMDISABLE */ | ||
| 751 | /* When the display is LCD, in addition to above: */ | ||
| 752 | /* ATOM_LCD_BLOFF|| ATOM_LCD_BLON ||ATOM_LCD_BL_BRIGHTNESS_CONTROL||ATOM_LCD_SELFTEST_START|| */ | ||
| 753 | /* ATOM_LCD_SELFTEST_STOP */ | ||
| 754 | |||
| 755 | UCHAR aucPadding[3]; /* padding to DWORD aligned */ | ||
| 756 | } DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS; | ||
| 757 | |||
| 758 | #define DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS | ||
| 759 | |||
| 760 | #define CRT1_OUTPUT_CONTROL_PARAMETERS DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS | ||
| 761 | #define CRT1_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION | ||
| 762 | |||
| 763 | #define CRT2_OUTPUT_CONTROL_PARAMETERS DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS | ||
| 764 | #define CRT2_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION | ||
| 765 | |||
| 766 | #define CV1_OUTPUT_CONTROL_PARAMETERS DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS | ||
| 767 | #define CV1_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION | ||
| 768 | |||
| 769 | #define TV1_OUTPUT_CONTROL_PARAMETERS DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS | ||
| 770 | #define TV1_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION | ||
| 771 | |||
| 772 | #define DFP1_OUTPUT_CONTROL_PARAMETERS DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS | ||
| 773 | #define DFP1_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION | ||
| 774 | |||
| 775 | #define DFP2_OUTPUT_CONTROL_PARAMETERS DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS | ||
| 776 | #define DFP2_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION | ||
| 777 | |||
| 778 | #define LCD1_OUTPUT_CONTROL_PARAMETERS DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS | ||
| 779 | #define LCD1_OUTPUT_CONTROL_PS_ALLOCATION DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION | ||
| 780 | |||
| 781 | #define DVO_OUTPUT_CONTROL_PARAMETERS DISPLAY_DEVICE_OUTPUT_CONTROL_PARAMETERS | ||
| 782 | #define DVO_OUTPUT_CONTROL_PS_ALLOCATION DIG_TRANSMITTER_CONTROL_PS_ALLOCATION | ||
| 783 | #define DVO_OUTPUT_CONTROL_PARAMETERS_V3 DIG_TRANSMITTER_CONTROL_PARAMETERS | ||
| 784 | |||
| 785 | /****************************************************************************/ | ||
| 786 | /* Structures used by BlankCRTCTable */ | ||
| 787 | /****************************************************************************/ | ||
| 788 | typedef struct _BLANK_CRTC_PARAMETERS { | ||
| 789 | UCHAR ucCRTC; /* ATOM_CRTC1 or ATOM_CRTC2 */ | ||
| 790 | UCHAR ucBlanking; /* ATOM_BLANKING or ATOM_BLANKINGOFF */ | ||
| 791 | USHORT usBlackColorRCr; | ||
| 792 | USHORT usBlackColorGY; | ||
| 793 | USHORT usBlackColorBCb; | ||
| 794 | } BLANK_CRTC_PARAMETERS; | ||
| 795 | #define BLANK_CRTC_PS_ALLOCATION BLANK_CRTC_PARAMETERS | ||
| 796 | |||
| 797 | /****************************************************************************/ | ||
| 798 | /* Structures used by EnableCRTCTable */ | ||
| 799 | /* EnableCRTCMemReqTable */ | ||
| 800 | /* UpdateCRTC_DoubleBufferRegistersTable */ | ||
| 801 | /****************************************************************************/ | ||
| 802 | typedef struct _ENABLE_CRTC_PARAMETERS { | ||
| 803 | UCHAR ucCRTC; /* ATOM_CRTC1 or ATOM_CRTC2 */ | ||
| 804 | UCHAR ucEnable; /* ATOM_ENABLE or ATOM_DISABLE */ | ||
| 805 | UCHAR ucPadding[2]; | ||
| 806 | } ENABLE_CRTC_PARAMETERS; | ||
| 807 | #define ENABLE_CRTC_PS_ALLOCATION ENABLE_CRTC_PARAMETERS | ||
| 808 | |||
| 809 | /****************************************************************************/ | ||
| 810 | /* Structures used by SetCRTC_OverScanTable */ | ||
| 811 | /****************************************************************************/ | ||
| 812 | typedef struct _SET_CRTC_OVERSCAN_PARAMETERS { | ||
| 813 | USHORT usOverscanRight; /* right */ | ||
| 814 | USHORT usOverscanLeft; /* left */ | ||
| 815 | USHORT usOverscanBottom; /* bottom */ | ||
| 816 | USHORT usOverscanTop; /* top */ | ||
| 817 | UCHAR ucCRTC; /* ATOM_CRTC1 or ATOM_CRTC2 */ | ||
| 818 | UCHAR ucPadding[3]; | ||
| 819 | } SET_CRTC_OVERSCAN_PARAMETERS; | ||
| 820 | #define SET_CRTC_OVERSCAN_PS_ALLOCATION SET_CRTC_OVERSCAN_PARAMETERS | ||
| 821 | |||
| 822 | /****************************************************************************/ | ||
| 823 | /* Structures used by SetCRTC_ReplicationTable */ | ||
| 824 | /****************************************************************************/ | ||
| 825 | typedef struct _SET_CRTC_REPLICATION_PARAMETERS { | ||
| 826 | UCHAR ucH_Replication; /* horizontal replication */ | ||
| 827 | UCHAR ucV_Replication; /* vertical replication */ | ||
| 828 | UCHAR usCRTC; /* ATOM_CRTC1 or ATOM_CRTC2 */ | ||
| 829 | UCHAR ucPadding; | ||
| 830 | } SET_CRTC_REPLICATION_PARAMETERS; | ||
| 831 | #define SET_CRTC_REPLICATION_PS_ALLOCATION SET_CRTC_REPLICATION_PARAMETERS | ||
| 832 | |||
| 833 | /****************************************************************************/ | ||
| 834 | /* Structures used by SelectCRTC_SourceTable */ | ||
| 835 | /****************************************************************************/ | ||
| 836 | typedef struct _SELECT_CRTC_SOURCE_PARAMETERS { | ||
| 837 | UCHAR ucCRTC; /* ATOM_CRTC1 or ATOM_CRTC2 */ | ||
| 838 | UCHAR ucDevice; /* ATOM_DEVICE_CRT1|ATOM_DEVICE_CRT2|.... */ | ||
| 839 | UCHAR ucPadding[2]; | ||
| 840 | } SELECT_CRTC_SOURCE_PARAMETERS; | ||
| 841 | #define SELECT_CRTC_SOURCE_PS_ALLOCATION SELECT_CRTC_SOURCE_PARAMETERS | ||
| 842 | |||
| 843 | typedef struct _SELECT_CRTC_SOURCE_PARAMETERS_V2 { | ||
| 844 | UCHAR ucCRTC; /* ATOM_CRTC1 or ATOM_CRTC2 */ | ||
| 845 | UCHAR ucEncoderID; /* DAC1/DAC2/TVOUT/DIG1/DIG2/DVO */ | ||
| 846 | UCHAR ucEncodeMode; /* Encoding mode, only valid when using DIG1/DIG2/DVO */ | ||
| 847 | UCHAR ucPadding; | ||
| 848 | } SELECT_CRTC_SOURCE_PARAMETERS_V2; | ||
| 849 | |||
| 850 | /* ucEncoderID */ | ||
| 851 | /* #define ASIC_INT_DAC1_ENCODER_ID 0x00 */ | ||
| 852 | /* #define ASIC_INT_TV_ENCODER_ID 0x02 */ | ||
| 853 | /* #define ASIC_INT_DIG1_ENCODER_ID 0x03 */ | ||
| 854 | /* #define ASIC_INT_DAC2_ENCODER_ID 0x04 */ | ||
| 855 | /* #define ASIC_EXT_TV_ENCODER_ID 0x06 */ | ||
| 856 | /* #define ASIC_INT_DVO_ENCODER_ID 0x07 */ | ||
| 857 | /* #define ASIC_INT_DIG2_ENCODER_ID 0x09 */ | ||
| 858 | /* #define ASIC_EXT_DIG_ENCODER_ID 0x05 */ | ||
| 859 | |||
| 860 | /* ucEncodeMode */ | ||
| 861 | /* #define ATOM_ENCODER_MODE_DP 0 */ | ||
| 862 | /* #define ATOM_ENCODER_MODE_LVDS 1 */ | ||
| 863 | /* #define ATOM_ENCODER_MODE_DVI 2 */ | ||
| 864 | /* #define ATOM_ENCODER_MODE_HDMI 3 */ | ||
| 865 | /* #define ATOM_ENCODER_MODE_SDVO 4 */ | ||
| 866 | /* #define ATOM_ENCODER_MODE_TV 13 */ | ||
| 867 | /* #define ATOM_ENCODER_MODE_CV 14 */ | ||
| 868 | /* #define ATOM_ENCODER_MODE_CRT 15 */ | ||
| 869 | |||
| 870 | /****************************************************************************/ | ||
| 871 | /* Structures used by SetPixelClockTable */ | ||
| 872 | /* GetPixelClockTable */ | ||
| 873 | /****************************************************************************/ | ||
| 874 | /* Major revision=1., Minor revision=1 */ | ||
| 875 | typedef struct _PIXEL_CLOCK_PARAMETERS { | ||
| 876 | USHORT usPixelClock; /* in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div) */ | ||
| 877 | /* 0 means disable PPLL */ | ||
| 878 | USHORT usRefDiv; /* Reference divider */ | ||
| 879 | USHORT usFbDiv; /* feedback divider */ | ||
| 880 | UCHAR ucPostDiv; /* post divider */ | ||
| 881 | UCHAR ucFracFbDiv; /* fractional feedback divider */ | ||
| 882 | UCHAR ucPpll; /* ATOM_PPLL1 or ATOM_PPL2 */ | ||
| 883 | UCHAR ucRefDivSrc; /* ATOM_PJITTER or ATO_NONPJITTER */ | ||
| 884 | UCHAR ucCRTC; /* Which CRTC uses this Ppll */ | ||
| 885 | UCHAR ucPadding; | ||
| 886 | } PIXEL_CLOCK_PARAMETERS; | ||
| 887 | |||
| 888 | /* Major revision=1., Minor revision=2, add ucMiscIfno */ | ||
| 889 | /* ucMiscInfo: */ | ||
| 890 | #define MISC_FORCE_REPROG_PIXEL_CLOCK 0x1 | ||
| 891 | #define MISC_DEVICE_INDEX_MASK 0xF0 | ||
| 892 | #define MISC_DEVICE_INDEX_SHIFT 4 | ||
| 893 | |||
| 894 | typedef struct _PIXEL_CLOCK_PARAMETERS_V2 { | ||
| 895 | USHORT usPixelClock; /* in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div) */ | ||
| 896 | /* 0 means disable PPLL */ | ||
| 897 | USHORT usRefDiv; /* Reference divider */ | ||
| 898 | USHORT usFbDiv; /* feedback divider */ | ||
| 899 | UCHAR ucPostDiv; /* post divider */ | ||
| 900 | UCHAR ucFracFbDiv; /* fractional feedback divider */ | ||
| 901 | UCHAR ucPpll; /* ATOM_PPLL1 or ATOM_PPL2 */ | ||
| 902 | UCHAR ucRefDivSrc; /* ATOM_PJITTER or ATO_NONPJITTER */ | ||
| 903 | UCHAR ucCRTC; /* Which CRTC uses this Ppll */ | ||
| 904 | UCHAR ucMiscInfo; /* Different bits for different purpose, bit [7:4] as device index, bit[0]=Force prog */ | ||
| 905 | } PIXEL_CLOCK_PARAMETERS_V2; | ||
| 906 | |||
| 907 | /* Major revision=1., Minor revision=3, structure/definition change */ | ||
| 908 | /* ucEncoderMode: */ | ||
| 909 | /* ATOM_ENCODER_MODE_DP */ | ||
| 910 | /* ATOM_ENOCDER_MODE_LVDS */ | ||
| 911 | /* ATOM_ENOCDER_MODE_DVI */ | ||
| 912 | /* ATOM_ENOCDER_MODE_HDMI */ | ||
| 913 | /* ATOM_ENOCDER_MODE_SDVO */ | ||
| 914 | /* ATOM_ENCODER_MODE_TV 13 */ | ||
| 915 | /* ATOM_ENCODER_MODE_CV 14 */ | ||
| 916 | /* ATOM_ENCODER_MODE_CRT 15 */ | ||
| 917 | |||
| 918 | /* ucDVOConfig */ | ||
| 919 | /* #define DVO_ENCODER_CONFIG_RATE_SEL 0x01 */ | ||
| 920 | /* #define DVO_ENCODER_CONFIG_DDR_SPEED 0x00 */ | ||
| 921 | /* #define DVO_ENCODER_CONFIG_SDR_SPEED 0x01 */ | ||
| 922 | /* #define DVO_ENCODER_CONFIG_OUTPUT_SEL 0x0c */ | ||
| 923 | /* #define DVO_ENCODER_CONFIG_LOW12BIT 0x00 */ | ||
| 924 | /* #define DVO_ENCODER_CONFIG_UPPER12BIT 0x04 */ | ||
| 925 | /* #define DVO_ENCODER_CONFIG_24BIT 0x08 */ | ||
| 926 | |||
| 927 | /* ucMiscInfo: also changed, see below */ | ||
| 928 | #define PIXEL_CLOCK_MISC_FORCE_PROG_PPLL 0x01 | ||
| 929 | #define PIXEL_CLOCK_MISC_VGA_MODE 0x02 | ||
| 930 | #define PIXEL_CLOCK_MISC_CRTC_SEL_MASK 0x04 | ||
| 931 | #define PIXEL_CLOCK_MISC_CRTC_SEL_CRTC1 0x00 | ||
| 932 | #define PIXEL_CLOCK_MISC_CRTC_SEL_CRTC2 0x04 | ||
| 933 | #define PIXEL_CLOCK_MISC_USE_ENGINE_FOR_DISPCLK 0x08 | ||
| 934 | |||
| 935 | typedef struct _PIXEL_CLOCK_PARAMETERS_V3 { | ||
| 936 | USHORT usPixelClock; /* in 10kHz unit; for bios convenient = (RefClk*FB_Div)/(Ref_Div*Post_Div) */ | ||
| 937 | /* 0 means disable PPLL. For VGA PPLL,make sure this value is not 0. */ | ||
| 938 | USHORT usRefDiv; /* Reference divider */ | ||
| 939 | USHORT usFbDiv; /* feedback divider */ | ||
| 940 | UCHAR ucPostDiv; /* post divider */ | ||
| 941 | UCHAR ucFracFbDiv; /* fractional feedback divider */ | ||
| 942 | UCHAR ucPpll; /* ATOM_PPLL1 or ATOM_PPL2 */ | ||
| 943 | UCHAR ucTransmitterId; /* graphic encoder id defined in objectId.h */ | ||
| 944 | union { | ||
| 945 | UCHAR ucEncoderMode; /* encoder type defined as ATOM_ENCODER_MODE_DP/DVI/HDMI/ */ | ||
| 946 | UCHAR ucDVOConfig; /* when use DVO, need to know SDR/DDR, 12bit or 24bit */ | ||
| 947 | }; | ||
| 948 | UCHAR ucMiscInfo; /* bit[0]=Force program, bit[1]= set pclk for VGA, b[2]= CRTC sel */ | ||
| 949 | /* bit[3]=0:use PPLL for dispclk source, =1: use engine clock for dispclock source */ | ||
| 950 | } PIXEL_CLOCK_PARAMETERS_V3; | ||
| 951 | |||
| 952 | #define PIXEL_CLOCK_PARAMETERS_LAST PIXEL_CLOCK_PARAMETERS_V2 | ||
| 953 | #define GET_PIXEL_CLOCK_PS_ALLOCATION PIXEL_CLOCK_PARAMETERS_LAST | ||
| 954 | |||
| 955 | /****************************************************************************/ | ||
| 956 | /* Structures used by AdjustDisplayPllTable */ | ||
| 957 | /****************************************************************************/ | ||
| 958 | typedef struct _ADJUST_DISPLAY_PLL_PARAMETERS { | ||
| 959 | USHORT usPixelClock; | ||
| 960 | UCHAR ucTransmitterID; | ||
| 961 | UCHAR ucEncodeMode; | ||
| 962 | union { | ||
| 963 | UCHAR ucDVOConfig; /* if DVO, need passing link rate and output 12bitlow or 24bit */ | ||
| 964 | UCHAR ucConfig; /* if none DVO, not defined yet */ | ||
| 965 | }; | ||
| 966 | UCHAR ucReserved[3]; | ||
| 967 | } ADJUST_DISPLAY_PLL_PARAMETERS; | ||
| 968 | |||
| 969 | #define ADJUST_DISPLAY_CONFIG_SS_ENABLE 0x10 | ||
| 970 | |||
| 971 | #define ADJUST_DISPLAY_PLL_PS_ALLOCATION ADJUST_DISPLAY_PLL_PARAMETERS | ||
| 972 | |||
| 973 | /****************************************************************************/ | ||
| 974 | /* Structures used by EnableYUVTable */ | ||
| 975 | /****************************************************************************/ | ||
| 976 | typedef struct _ENABLE_YUV_PARAMETERS { | ||
| 977 | UCHAR ucEnable; /* ATOM_ENABLE:Enable YUV or ATOM_DISABLE:Disable YUV (RGB) */ | ||
| 978 | UCHAR ucCRTC; /* Which CRTC needs this YUV or RGB format */ | ||
| 979 | UCHAR ucPadding[2]; | ||
| 980 | } ENABLE_YUV_PARAMETERS; | ||
| 981 | #define ENABLE_YUV_PS_ALLOCATION ENABLE_YUV_PARAMETERS | ||
| 982 | |||
| 983 | /****************************************************************************/ | ||
| 984 | /* Structures used by GetMemoryClockTable */ | ||
| 985 | /****************************************************************************/ | ||
| 986 | typedef struct _GET_MEMORY_CLOCK_PARAMETERS { | ||
| 987 | ULONG ulReturnMemoryClock; /* current memory speed in 10KHz unit */ | ||
| 988 | } GET_MEMORY_CLOCK_PARAMETERS; | ||
| 989 | #define GET_MEMORY_CLOCK_PS_ALLOCATION GET_MEMORY_CLOCK_PARAMETERS | ||
| 990 | |||
| 991 | /****************************************************************************/ | ||
| 992 | /* Structures used by GetEngineClockTable */ | ||
| 993 | /****************************************************************************/ | ||
| 994 | typedef struct _GET_ENGINE_CLOCK_PARAMETERS { | ||
| 995 | ULONG ulReturnEngineClock; /* current engine speed in 10KHz unit */ | ||
| 996 | } GET_ENGINE_CLOCK_PARAMETERS; | ||
| 997 | #define GET_ENGINE_CLOCK_PS_ALLOCATION GET_ENGINE_CLOCK_PARAMETERS | ||
| 998 | |||
| 999 | /****************************************************************************/ | ||
| 1000 | /* Following Structures and constant may be obsolete */ | ||
| 1001 | /****************************************************************************/ | ||
| 1002 | /* Maxium 8 bytes,the data read in will be placed in the parameter space. */ | ||
| 1003 | /* Read operaion successeful when the paramter space is non-zero, otherwise read operation failed */ | ||
| 1004 | typedef struct _READ_EDID_FROM_HW_I2C_DATA_PARAMETERS { | ||
| 1005 | USHORT usPrescale; /* Ratio between Engine clock and I2C clock */ | ||
| 1006 | USHORT usVRAMAddress; /* Adress in Frame Buffer where to pace raw EDID */ | ||
| 1007 | USHORT usStatus; /* When use output: lower byte EDID checksum, high byte hardware status */ | ||
| 1008 | /* WHen use input: lower byte as 'byte to read':currently limited to 128byte or 1byte */ | ||
| 1009 | UCHAR ucSlaveAddr; /* Read from which slave */ | ||
| 1010 | UCHAR ucLineNumber; /* Read from which HW assisted line */ | ||
| 1011 | } READ_EDID_FROM_HW_I2C_DATA_PARAMETERS; | ||
| 1012 | #define READ_EDID_FROM_HW_I2C_DATA_PS_ALLOCATION READ_EDID_FROM_HW_I2C_DATA_PARAMETERS | ||
| 1013 | |||
| 1014 | #define ATOM_WRITE_I2C_FORMAT_PSOFFSET_PSDATABYTE 0 | ||
| 1015 | #define ATOM_WRITE_I2C_FORMAT_PSOFFSET_PSTWODATABYTES 1 | ||
| 1016 | #define ATOM_WRITE_I2C_FORMAT_PSCOUNTER_PSOFFSET_IDDATABLOCK 2 | ||
| 1017 | #define ATOM_WRITE_I2C_FORMAT_PSCOUNTER_IDOFFSET_PLUS_IDDATABLOCK 3 | ||
| 1018 | #define ATOM_WRITE_I2C_FORMAT_IDCOUNTER_IDOFFSET_IDDATABLOCK 4 | ||
| 1019 | |||
| 1020 | typedef struct _WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS { | ||
| 1021 | USHORT usPrescale; /* Ratio between Engine clock and I2C clock */ | ||
| 1022 | USHORT usByteOffset; /* Write to which byte */ | ||
| 1023 | /* Upper portion of usByteOffset is Format of data */ | ||
| 1024 | /* 1bytePS+offsetPS */ | ||
| 1025 | /* 2bytesPS+offsetPS */ | ||
| 1026 | /* blockID+offsetPS */ | ||
| 1027 | /* blockID+offsetID */ | ||
| 1028 | /* blockID+counterID+offsetID */ | ||
| 1029 | UCHAR ucData; /* PS data1 */ | ||
| 1030 | UCHAR ucStatus; /* Status byte 1=success, 2=failure, Also is used as PS data2 */ | ||
| 1031 | UCHAR ucSlaveAddr; /* Write to which slave */ | ||
| 1032 | UCHAR ucLineNumber; /* Write from which HW assisted line */ | ||
| 1033 | } WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS; | ||
| 1034 | |||
| 1035 | #define WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS | ||
| 1036 | |||
| 1037 | typedef struct _SET_UP_HW_I2C_DATA_PARAMETERS { | ||
| 1038 | USHORT usPrescale; /* Ratio between Engine clock and I2C clock */ | ||
| 1039 | UCHAR ucSlaveAddr; /* Write to which slave */ | ||
| 1040 | UCHAR ucLineNumber; /* Write from which HW assisted line */ | ||
| 1041 | } SET_UP_HW_I2C_DATA_PARAMETERS; | ||
| 1042 | |||
| 1043 | /**************************************************************************/ | ||
| 1044 | #define SPEED_FAN_CONTROL_PS_ALLOCATION WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS | ||
| 1045 | |||
| 1046 | /****************************************************************************/ | ||
| 1047 | /* Structures used by PowerConnectorDetectionTable */ | ||
| 1048 | /****************************************************************************/ | ||
| 1049 | typedef struct _POWER_CONNECTOR_DETECTION_PARAMETERS { | ||
| 1050 | UCHAR ucPowerConnectorStatus; /* Used for return value 0: detected, 1:not detected */ | ||
| 1051 | UCHAR ucPwrBehaviorId; | ||
| 1052 | USHORT usPwrBudget; /* how much power currently boot to in unit of watt */ | ||
| 1053 | } POWER_CONNECTOR_DETECTION_PARAMETERS; | ||
| 1054 | |||
| 1055 | typedef struct POWER_CONNECTOR_DETECTION_PS_ALLOCATION { | ||
| 1056 | UCHAR ucPowerConnectorStatus; /* Used for return value 0: detected, 1:not detected */ | ||
| 1057 | UCHAR ucReserved; | ||
| 1058 | USHORT usPwrBudget; /* how much power currently boot to in unit of watt */ | ||
| 1059 | WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved; | ||
| 1060 | } POWER_CONNECTOR_DETECTION_PS_ALLOCATION; | ||
| 1061 | |||
| 1062 | /****************************LVDS SS Command Table Definitions**********************/ | ||
| 1063 | |||
| 1064 | /****************************************************************************/ | ||
| 1065 | /* Structures used by EnableSpreadSpectrumOnPPLLTable */ | ||
| 1066 | /****************************************************************************/ | ||
| 1067 | typedef struct _ENABLE_LVDS_SS_PARAMETERS { | ||
| 1068 | USHORT usSpreadSpectrumPercentage; | ||
| 1069 | UCHAR ucSpreadSpectrumType; /* Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD */ | ||
| 1070 | UCHAR ucSpreadSpectrumStepSize_Delay; /* bits3:2 SS_STEP_SIZE; bit 6:4 SS_DELAY */ | ||
| 1071 | UCHAR ucEnable; /* ATOM_ENABLE or ATOM_DISABLE */ | ||
| 1072 | UCHAR ucPadding[3]; | ||
| 1073 | } ENABLE_LVDS_SS_PARAMETERS; | ||
| 1074 | |||
| 1075 | /* ucTableFormatRevision=1,ucTableContentRevision=2 */ | ||
| 1076 | typedef struct _ENABLE_LVDS_SS_PARAMETERS_V2 { | ||
| 1077 | USHORT usSpreadSpectrumPercentage; | ||
| 1078 | UCHAR ucSpreadSpectrumType; /* Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD */ | ||
| 1079 | UCHAR ucSpreadSpectrumStep; /* */ | ||
| 1080 | UCHAR ucEnable; /* ATOM_ENABLE or ATOM_DISABLE */ | ||
| 1081 | UCHAR ucSpreadSpectrumDelay; | ||
| 1082 | UCHAR ucSpreadSpectrumRange; | ||
| 1083 | UCHAR ucPadding; | ||
| 1084 | } ENABLE_LVDS_SS_PARAMETERS_V2; | ||
| 1085 | |||
| 1086 | /* This new structure is based on ENABLE_LVDS_SS_PARAMETERS but expands to SS on PPLL, so other devices can use SS. */ | ||
| 1087 | typedef struct _ENABLE_SPREAD_SPECTRUM_ON_PPLL { | ||
| 1088 | USHORT usSpreadSpectrumPercentage; | ||
| 1089 | UCHAR ucSpreadSpectrumType; /* Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD */ | ||
| 1090 | UCHAR ucSpreadSpectrumStep; /* */ | ||
| 1091 | UCHAR ucEnable; /* ATOM_ENABLE or ATOM_DISABLE */ | ||
| 1092 | UCHAR ucSpreadSpectrumDelay; | ||
| 1093 | UCHAR ucSpreadSpectrumRange; | ||
| 1094 | UCHAR ucPpll; /* ATOM_PPLL1/ATOM_PPLL2 */ | ||
| 1095 | } ENABLE_SPREAD_SPECTRUM_ON_PPLL; | ||
| 1096 | |||
| 1097 | #define ENABLE_SPREAD_SPECTRUM_ON_PPLL_PS_ALLOCATION ENABLE_SPREAD_SPECTRUM_ON_PPLL | ||
| 1098 | |||
| 1099 | /**************************************************************************/ | ||
| 1100 | |||
| 1101 | typedef struct _SET_PIXEL_CLOCK_PS_ALLOCATION { | ||
| 1102 | PIXEL_CLOCK_PARAMETERS sPCLKInput; | ||
| 1103 | ENABLE_SPREAD_SPECTRUM_ON_PPLL sReserved; /* Caller doesn't need to init this portion */ | ||
| 1104 | } SET_PIXEL_CLOCK_PS_ALLOCATION; | ||
| 1105 | |||
| 1106 | #define ENABLE_VGA_RENDER_PS_ALLOCATION SET_PIXEL_CLOCK_PS_ALLOCATION | ||
| 1107 | |||
| 1108 | /****************************************************************************/ | ||
| 1109 | /* Structures used by ### */ | ||
| 1110 | /****************************************************************************/ | ||
| 1111 | typedef struct _MEMORY_TRAINING_PARAMETERS { | ||
| 1112 | ULONG ulTargetMemoryClock; /* In 10Khz unit */ | ||
| 1113 | } MEMORY_TRAINING_PARAMETERS; | ||
| 1114 | #define MEMORY_TRAINING_PS_ALLOCATION MEMORY_TRAINING_PARAMETERS | ||
| 1115 | |||
| 1116 | /****************************LVDS and other encoder command table definitions **********************/ | ||
| 1117 | |||
| 1118 | /****************************************************************************/ | ||
| 1119 | /* Structures used by LVDSEncoderControlTable (Before DCE30) */ | ||
| 1120 | /* LVTMAEncoderControlTable (Before DCE30) */ | ||
| 1121 | /* TMDSAEncoderControlTable (Before DCE30) */ | ||
| 1122 | /****************************************************************************/ | ||
| 1123 | typedef struct _LVDS_ENCODER_CONTROL_PARAMETERS { | ||
| 1124 | USHORT usPixelClock; /* in 10KHz; for bios convenient */ | ||
| 1125 | UCHAR ucMisc; /* bit0=0: Enable single link */ | ||
| 1126 | /* =1: Enable dual link */ | ||
| 1127 | /* Bit1=0: 666RGB */ | ||
| 1128 | /* =1: 888RGB */ | ||
| 1129 | UCHAR ucAction; /* 0: turn off encoder */ | ||
| 1130 | /* 1: setup and turn on encoder */ | ||
| 1131 | } LVDS_ENCODER_CONTROL_PARAMETERS; | ||
| 1132 | |||
| 1133 | #define LVDS_ENCODER_CONTROL_PS_ALLOCATION LVDS_ENCODER_CONTROL_PARAMETERS | ||
| 1134 | |||
| 1135 | #define TMDS1_ENCODER_CONTROL_PARAMETERS LVDS_ENCODER_CONTROL_PARAMETERS | ||
| 1136 | #define TMDS1_ENCODER_CONTROL_PS_ALLOCATION TMDS1_ENCODER_CONTROL_PARAMETERS | ||
| 1137 | |||
| 1138 | #define TMDS2_ENCODER_CONTROL_PARAMETERS TMDS1_ENCODER_CONTROL_PARAMETERS | ||
| 1139 | #define TMDS2_ENCODER_CONTROL_PS_ALLOCATION TMDS2_ENCODER_CONTROL_PARAMETERS | ||
| 1140 | |||
| 1141 | /* ucTableFormatRevision=1,ucTableContentRevision=2 */ | ||
| 1142 | typedef struct _LVDS_ENCODER_CONTROL_PARAMETERS_V2 { | ||
| 1143 | USHORT usPixelClock; /* in 10KHz; for bios convenient */ | ||
| 1144 | UCHAR ucMisc; /* see PANEL_ENCODER_MISC_xx defintions below */ | ||
| 1145 | UCHAR ucAction; /* 0: turn off encoder */ | ||
| 1146 | /* 1: setup and turn on encoder */ | ||
| 1147 | UCHAR ucTruncate; /* bit0=0: Disable truncate */ | ||
| 1148 | /* =1: Enable truncate */ | ||
| 1149 | /* bit4=0: 666RGB */ | ||
| 1150 | /* =1: 888RGB */ | ||
| 1151 | UCHAR ucSpatial; /* bit0=0: Disable spatial dithering */ | ||
| 1152 | /* =1: Enable spatial dithering */ | ||
| 1153 | /* bit4=0: 666RGB */ | ||
| 1154 | /* =1: 888RGB */ | ||
| 1155 | UCHAR ucTemporal; /* bit0=0: Disable temporal dithering */ | ||
| 1156 | /* =1: Enable temporal dithering */ | ||
| 1157 | /* bit4=0: 666RGB */ | ||
| 1158 | /* =1: 888RGB */ | ||
| 1159 | /* bit5=0: Gray level 2 */ | ||
| 1160 | /* =1: Gray level 4 */ | ||
| 1161 | UCHAR ucFRC; /* bit4=0: 25FRC_SEL pattern E */ | ||
| 1162 | /* =1: 25FRC_SEL pattern F */ | ||
| 1163 | /* bit6:5=0: 50FRC_SEL pattern A */ | ||
| 1164 | /* =1: 50FRC_SEL pattern B */ | ||
| 1165 | /* =2: 50FRC_SEL pattern C */ | ||
| 1166 | /* =3: 50FRC_SEL pattern D */ | ||
| 1167 | /* bit7=0: 75FRC_SEL pattern E */ | ||
| 1168 | /* =1: 75FRC_SEL pattern F */ | ||
| 1169 | } LVDS_ENCODER_CONTROL_PARAMETERS_V2; | ||
| 1170 | |||
| 1171 | #define LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 LVDS_ENCODER_CONTROL_PARAMETERS_V2 | ||
| 1172 | |||
| 1173 | #define TMDS1_ENCODER_CONTROL_PARAMETERS_V2 LVDS_ENCODER_CONTROL_PARAMETERS_V2 | ||
| 1174 | #define TMDS1_ENCODER_CONTROL_PS_ALLOCATION_V2 TMDS1_ENCODER_CONTROL_PARAMETERS_V2 | ||
| 1175 | |||
| 1176 | #define TMDS2_ENCODER_CONTROL_PARAMETERS_V2 TMDS1_ENCODER_CONTROL_PARAMETERS_V2 | ||
| 1177 | #define TMDS2_ENCODER_CONTROL_PS_ALLOCATION_V2 TMDS2_ENCODER_CONTROL_PARAMETERS_V2 | ||
| 1178 | |||
| 1179 | #define LVDS_ENCODER_CONTROL_PARAMETERS_V3 LVDS_ENCODER_CONTROL_PARAMETERS_V2 | ||
| 1180 | #define LVDS_ENCODER_CONTROL_PS_ALLOCATION_V3 LVDS_ENCODER_CONTROL_PARAMETERS_V3 | ||
| 1181 | |||
| 1182 | #define TMDS1_ENCODER_CONTROL_PARAMETERS_V3 LVDS_ENCODER_CONTROL_PARAMETERS_V3 | ||
| 1183 | #define TMDS1_ENCODER_CONTROL_PS_ALLOCATION_V3 TMDS1_ENCODER_CONTROL_PARAMETERS_V3 | ||
| 1184 | |||
| 1185 | #define TMDS2_ENCODER_CONTROL_PARAMETERS_V3 LVDS_ENCODER_CONTROL_PARAMETERS_V3 | ||
| 1186 | #define TMDS2_ENCODER_CONTROL_PS_ALLOCATION_V3 TMDS2_ENCODER_CONTROL_PARAMETERS_V3 | ||
| 1187 | |||
| 1188 | /****************************************************************************/ | ||
| 1189 | /* Structures used by ### */ | ||
| 1190 | /****************************************************************************/ | ||
| 1191 | typedef struct _ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS { | ||
| 1192 | UCHAR ucEnable; /* Enable or Disable External TMDS encoder */ | ||
| 1193 | UCHAR ucMisc; /* Bit0=0:Enable Single link;=1:Enable Dual link;Bit1 {=0:666RGB, =1:888RGB} */ | ||
| 1194 | UCHAR ucPadding[2]; | ||
| 1195 | } ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS; | ||
| 1196 | |||
| 1197 | typedef struct _ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION { | ||
| 1198 | ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS sXTmdsEncoder; | ||
| 1199 | WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved; /* Caller doesn't need to init this portion */ | ||
| 1200 | } ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION; | ||
| 1201 | |||
| 1202 | #define ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS_V2 LVDS_ENCODER_CONTROL_PARAMETERS_V2 | ||
| 1203 | |||
| 1204 | typedef struct _ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION_V2 { | ||
| 1205 | ENABLE_EXTERNAL_TMDS_ENCODER_PARAMETERS_V2 sXTmdsEncoder; | ||
| 1206 | WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved; /* Caller doesn't need to init this portion */ | ||
| 1207 | } ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION_V2; | ||
| 1208 | |||
| 1209 | typedef struct _EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION { | ||
| 1210 | DIG_ENCODER_CONTROL_PARAMETERS sDigEncoder; | ||
| 1211 | WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved; | ||
| 1212 | } EXTERNAL_ENCODER_CONTROL_PS_ALLOCATION; | ||
| 1213 | |||
| 1214 | /****************************************************************************/ | ||
| 1215 | /* Structures used by DVOEncoderControlTable */ | ||
| 1216 | /****************************************************************************/ | ||
| 1217 | /* ucTableFormatRevision=1,ucTableContentRevision=3 */ | ||
| 1218 | |||
| 1219 | /* ucDVOConfig: */ | ||
| 1220 | #define DVO_ENCODER_CONFIG_RATE_SEL 0x01 | ||
| 1221 | #define DVO_ENCODER_CONFIG_DDR_SPEED 0x00 | ||
| 1222 | #define DVO_ENCODER_CONFIG_SDR_SPEED 0x01 | ||
| 1223 | #define DVO_ENCODER_CONFIG_OUTPUT_SEL 0x0c | ||
| 1224 | #define DVO_ENCODER_CONFIG_LOW12BIT 0x00 | ||
| 1225 | #define DVO_ENCODER_CONFIG_UPPER12BIT 0x04 | ||
| 1226 | #define DVO_ENCODER_CONFIG_24BIT 0x08 | ||
| 1227 | |||
| 1228 | typedef struct _DVO_ENCODER_CONTROL_PARAMETERS_V3 { | ||
| 1229 | USHORT usPixelClock; | ||
| 1230 | UCHAR ucDVOConfig; | ||
| 1231 | UCHAR ucAction; /* ATOM_ENABLE/ATOM_DISABLE/ATOM_HPD_INIT */ | ||
| 1232 | UCHAR ucReseved[4]; | ||
| 1233 | } DVO_ENCODER_CONTROL_PARAMETERS_V3; | ||
| 1234 | #define DVO_ENCODER_CONTROL_PS_ALLOCATION_V3 DVO_ENCODER_CONTROL_PARAMETERS_V3 | ||
| 1235 | |||
| 1236 | /* ucTableFormatRevision=1 */ | ||
| 1237 | /* ucTableContentRevision=3 structure is not changed but usMisc add bit 1 as another input for */ | ||
| 1238 | /* bit1=0: non-coherent mode */ | ||
| 1239 | /* =1: coherent mode */ | ||
| 1240 | |||
| 1241 | /* ========================================================================================== */ | ||
| 1242 | /* Only change is here next time when changing encoder parameter definitions again! */ | ||
| 1243 | #define LVDS_ENCODER_CONTROL_PARAMETERS_LAST LVDS_ENCODER_CONTROL_PARAMETERS_V3 | ||
| 1244 | #define LVDS_ENCODER_CONTROL_PS_ALLOCATION_LAST LVDS_ENCODER_CONTROL_PARAMETERS_LAST | ||
| 1245 | |||
| 1246 | #define TMDS1_ENCODER_CONTROL_PARAMETERS_LAST LVDS_ENCODER_CONTROL_PARAMETERS_V3 | ||
| 1247 | #define TMDS1_ENCODER_CONTROL_PS_ALLOCATION_LAST TMDS1_ENCODER_CONTROL_PARAMETERS_LAST | ||
| 1248 | |||
| 1249 | #define TMDS2_ENCODER_CONTROL_PARAMETERS_LAST LVDS_ENCODER_CONTROL_PARAMETERS_V3 | ||
| 1250 | #define TMDS2_ENCODER_CONTROL_PS_ALLOCATION_LAST TMDS2_ENCODER_CONTROL_PARAMETERS_LAST | ||
| 1251 | |||
| 1252 | #define DVO_ENCODER_CONTROL_PARAMETERS_LAST DVO_ENCODER_CONTROL_PARAMETERS | ||
| 1253 | #define DVO_ENCODER_CONTROL_PS_ALLOCATION_LAST DVO_ENCODER_CONTROL_PS_ALLOCATION | ||
| 1254 | |||
| 1255 | /* ========================================================================================== */ | ||
| 1256 | #define PANEL_ENCODER_MISC_DUAL 0x01 | ||
| 1257 | #define PANEL_ENCODER_MISC_COHERENT 0x02 | ||
| 1258 | #define PANEL_ENCODER_MISC_TMDS_LINKB 0x04 | ||
| 1259 | #define PANEL_ENCODER_MISC_HDMI_TYPE 0x08 | ||
| 1260 | |||
| 1261 | #define PANEL_ENCODER_ACTION_DISABLE ATOM_DISABLE | ||
| 1262 | #define PANEL_ENCODER_ACTION_ENABLE ATOM_ENABLE | ||
| 1263 | #define PANEL_ENCODER_ACTION_COHERENTSEQ (ATOM_ENABLE+1) | ||
| 1264 | |||
| 1265 | #define PANEL_ENCODER_TRUNCATE_EN 0x01 | ||
| 1266 | #define PANEL_ENCODER_TRUNCATE_DEPTH 0x10 | ||
| 1267 | #define PANEL_ENCODER_SPATIAL_DITHER_EN 0x01 | ||
| 1268 | #define PANEL_ENCODER_SPATIAL_DITHER_DEPTH 0x10 | ||
| 1269 | #define PANEL_ENCODER_TEMPORAL_DITHER_EN 0x01 | ||
| 1270 | #define PANEL_ENCODER_TEMPORAL_DITHER_DEPTH 0x10 | ||
| 1271 | #define PANEL_ENCODER_TEMPORAL_LEVEL_4 0x20 | ||
| 1272 | #define PANEL_ENCODER_25FRC_MASK 0x10 | ||
| 1273 | #define PANEL_ENCODER_25FRC_E 0x00 | ||
| 1274 | #define PANEL_ENCODER_25FRC_F 0x10 | ||
| 1275 | #define PANEL_ENCODER_50FRC_MASK 0x60 | ||
| 1276 | #define PANEL_ENCODER_50FRC_A 0x00 | ||
| 1277 | #define PANEL_ENCODER_50FRC_B 0x20 | ||
| 1278 | #define PANEL_ENCODER_50FRC_C 0x40 | ||
| 1279 | #define PANEL_ENCODER_50FRC_D 0x60 | ||
| 1280 | #define PANEL_ENCODER_75FRC_MASK 0x80 | ||
| 1281 | #define PANEL_ENCODER_75FRC_E 0x00 | ||
| 1282 | #define PANEL_ENCODER_75FRC_F 0x80 | ||
| 1283 | |||
| 1284 | /****************************************************************************/ | ||
| 1285 | /* Structures used by SetVoltageTable */ | ||
| 1286 | /****************************************************************************/ | ||
| 1287 | #define SET_VOLTAGE_TYPE_ASIC_VDDC 1 | ||
| 1288 | #define SET_VOLTAGE_TYPE_ASIC_MVDDC 2 | ||
| 1289 | #define SET_VOLTAGE_TYPE_ASIC_MVDDQ 3 | ||
| 1290 | #define SET_VOLTAGE_TYPE_ASIC_VDDCI 4 | ||
| 1291 | #define SET_VOLTAGE_INIT_MODE 5 | ||
| 1292 | #define SET_VOLTAGE_GET_MAX_VOLTAGE 6 /* Gets the Max. voltage for the soldered Asic */ | ||
| 1293 | |||
| 1294 | #define SET_ASIC_VOLTAGE_MODE_ALL_SOURCE 0x1 | ||
| 1295 | #define SET_ASIC_VOLTAGE_MODE_SOURCE_A 0x2 | ||
| 1296 | #define SET_ASIC_VOLTAGE_MODE_SOURCE_B 0x4 | ||
| 1297 | |||
| 1298 | #define SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE 0x0 | ||
| 1299 | #define SET_ASIC_VOLTAGE_MODE_GET_GPIOVAL 0x1 | ||
| 1300 | #define SET_ASIC_VOLTAGE_MODE_GET_GPIOMASK 0x2 | ||
| 1301 | |||
| 1302 | typedef struct _SET_VOLTAGE_PARAMETERS { | ||
| 1303 | UCHAR ucVoltageType; /* To tell which voltage to set up, VDDC/MVDDC/MVDDQ */ | ||
| 1304 | UCHAR ucVoltageMode; /* To set all, to set source A or source B or ... */ | ||
| 1305 | UCHAR ucVoltageIndex; /* An index to tell which voltage level */ | ||
| 1306 | UCHAR ucReserved; | ||
| 1307 | } SET_VOLTAGE_PARAMETERS; | ||
| 1308 | |||
| 1309 | typedef struct _SET_VOLTAGE_PARAMETERS_V2 { | ||
| 1310 | UCHAR ucVoltageType; /* To tell which voltage to set up, VDDC/MVDDC/MVDDQ */ | ||
| 1311 | UCHAR ucVoltageMode; /* Not used, maybe use for state machine for differen power mode */ | ||
| 1312 | USHORT usVoltageLevel; /* real voltage level */ | ||
| 1313 | } SET_VOLTAGE_PARAMETERS_V2; | ||
| 1314 | |||
| 1315 | typedef struct _SET_VOLTAGE_PS_ALLOCATION { | ||
| 1316 | SET_VOLTAGE_PARAMETERS sASICSetVoltage; | ||
| 1317 | WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved; | ||
| 1318 | } SET_VOLTAGE_PS_ALLOCATION; | ||
| 1319 | |||
| 1320 | /****************************************************************************/ | ||
| 1321 | /* Structures used by TVEncoderControlTable */ | ||
| 1322 | /****************************************************************************/ | ||
| 1323 | typedef struct _TV_ENCODER_CONTROL_PARAMETERS { | ||
| 1324 | USHORT usPixelClock; /* in 10KHz; for bios convenient */ | ||
| 1325 | UCHAR ucTvStandard; /* See definition "ATOM_TV_NTSC ..." */ | ||
| 1326 | UCHAR ucAction; /* 0: turn off encoder */ | ||
| 1327 | /* 1: setup and turn on encoder */ | ||
| 1328 | } TV_ENCODER_CONTROL_PARAMETERS; | ||
| 1329 | |||
| 1330 | typedef struct _TV_ENCODER_CONTROL_PS_ALLOCATION { | ||
| 1331 | TV_ENCODER_CONTROL_PARAMETERS sTVEncoder; | ||
| 1332 | WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved; /* Don't set this one */ | ||
| 1333 | } TV_ENCODER_CONTROL_PS_ALLOCATION; | ||
| 1334 | |||
| 1335 | /* ==============================Data Table Portion==================================== */ | ||
| 1336 | |||
| 1337 | #ifdef UEFI_BUILD | ||
| 1338 | #define UTEMP USHORT | ||
| 1339 | #define USHORT void* | ||
| 1340 | #endif | ||
| 1341 | |||
| 1342 | /****************************************************************************/ | ||
| 1343 | /* Structure used in Data.mtb */ | ||
| 1344 | /****************************************************************************/ | ||
| 1345 | typedef struct _ATOM_MASTER_LIST_OF_DATA_TABLES { | ||
| 1346 | USHORT UtilityPipeLine; /* Offest for the utility to get parser info,Don't change this position! */ | ||
| 1347 | USHORT MultimediaCapabilityInfo; /* Only used by MM Lib,latest version 1.1, not configuable from Bios, need to include the table to build Bios */ | ||
| 1348 | USHORT MultimediaConfigInfo; /* Only used by MM Lib,latest version 2.1, not configuable from Bios, need to include the table to build Bios */ | ||
| 1349 | USHORT StandardVESA_Timing; /* Only used by Bios */ | ||
| 1350 | USHORT FirmwareInfo; /* Shared by various SW components,latest version 1.4 */ | ||
| 1351 | USHORT DAC_Info; /* Will be obsolete from R600 */ | ||
| 1352 | USHORT LVDS_Info; /* Shared by various SW components,latest version 1.1 */ | ||
| 1353 | USHORT TMDS_Info; /* Will be obsolete from R600 */ | ||
| 1354 | USHORT AnalogTV_Info; /* Shared by various SW components,latest version 1.1 */ | ||
| 1355 | USHORT SupportedDevicesInfo; /* Will be obsolete from R600 */ | ||
| 1356 | USHORT GPIO_I2C_Info; /* Shared by various SW components,latest version 1.2 will be used from R600 */ | ||
| 1357 | USHORT VRAM_UsageByFirmware; /* Shared by various SW components,latest version 1.3 will be used from R600 */ | ||
| 1358 | USHORT GPIO_Pin_LUT; /* Shared by various SW components,latest version 1.1 */ | ||
| 1359 | USHORT VESA_ToInternalModeLUT; /* Only used by Bios */ | ||
| 1360 | USHORT ComponentVideoInfo; /* Shared by various SW components,latest version 2.1 will be used from R600 */ | ||
| 1361 | USHORT PowerPlayInfo; /* Shared by various SW components,latest version 2.1,new design from R600 */ | ||
| 1362 | USHORT CompassionateData; /* Will be obsolete from R600 */ | ||
| 1363 | USHORT SaveRestoreInfo; /* Only used by Bios */ | ||
| 1364 | USHORT PPLL_SS_Info; /* Shared by various SW components,latest version 1.2, used to call SS_Info, change to new name because of int ASIC SS info */ | ||
| 1365 | USHORT OemInfo; /* Defined and used by external SW, should be obsolete soon */ | ||
| 1366 | USHORT XTMDS_Info; /* Will be obsolete from R600 */ | ||
| 1367 | USHORT MclkSS_Info; /* Shared by various SW components,latest version 1.1, only enabled when ext SS chip is used */ | ||
| 1368 | USHORT Object_Header; /* Shared by various SW components,latest version 1.1 */ | ||
| 1369 | USHORT IndirectIOAccess; /* Only used by Bios,this table position can't change at all!! */ | ||
| 1370 | USHORT MC_InitParameter; /* Only used by command table */ | ||
| 1371 | USHORT ASIC_VDDC_Info; /* Will be obsolete from R600 */ | ||
| 1372 | USHORT ASIC_InternalSS_Info; /* New tabel name from R600, used to be called "ASIC_MVDDC_Info" */ | ||
| 1373 | USHORT TV_VideoMode; /* Only used by command table */ | ||
| 1374 | USHORT VRAM_Info; /* Only used by command table, latest version 1.3 */ | ||
| 1375 | USHORT MemoryTrainingInfo; /* Used for VBIOS and Diag utility for memory training purpose since R600. the new table rev start from 2.1 */ | ||
| 1376 | USHORT IntegratedSystemInfo; /* Shared by various SW components */ | ||
| 1377 | USHORT ASIC_ProfilingInfo; /* New table name from R600, used to be called "ASIC_VDDCI_Info" for pre-R600 */ | ||
| 1378 | USHORT VoltageObjectInfo; /* Shared by various SW components, latest version 1.1 */ | ||
| 1379 | USHORT PowerSourceInfo; /* Shared by various SW components, latest versoin 1.1 */ | ||
| 1380 | } ATOM_MASTER_LIST_OF_DATA_TABLES; | ||
| 1381 | |||
| 1382 | #ifdef UEFI_BUILD | ||
| 1383 | #define USHORT UTEMP | ||
| 1384 | #endif | ||
| 1385 | |||
| 1386 | typedef struct _ATOM_MASTER_DATA_TABLE { | ||
| 1387 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 1388 | ATOM_MASTER_LIST_OF_DATA_TABLES ListOfDataTables; | ||
| 1389 | } ATOM_MASTER_DATA_TABLE; | ||
| 1390 | |||
| 1391 | /****************************************************************************/ | ||
| 1392 | /* Structure used in MultimediaCapabilityInfoTable */ | ||
| 1393 | /****************************************************************************/ | ||
| 1394 | typedef struct _ATOM_MULTIMEDIA_CAPABILITY_INFO { | ||
| 1395 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 1396 | ULONG ulSignature; /* HW info table signature string "$ATI" */ | ||
| 1397 | UCHAR ucI2C_Type; /* I2C type (normal GP_IO, ImpactTV GP_IO, Dedicated I2C pin, etc) */ | ||
| 1398 | UCHAR ucTV_OutInfo; /* Type of TV out supported (3:0) and video out crystal frequency (6:4) and TV data port (7) */ | ||
| 1399 | UCHAR ucVideoPortInfo; /* Provides the video port capabilities */ | ||
| 1400 | UCHAR ucHostPortInfo; /* Provides host port configuration information */ | ||
| 1401 | } ATOM_MULTIMEDIA_CAPABILITY_INFO; | ||
| 1402 | |||
| 1403 | /****************************************************************************/ | ||
| 1404 | /* Structure used in MultimediaConfigInfoTable */ | ||
| 1405 | /****************************************************************************/ | ||
| 1406 | typedef struct _ATOM_MULTIMEDIA_CONFIG_INFO { | ||
| 1407 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 1408 | ULONG ulSignature; /* MM info table signature sting "$MMT" */ | ||
| 1409 | UCHAR ucTunerInfo; /* Type of tuner installed on the adapter (4:0) and video input for tuner (7:5) */ | ||
| 1410 | UCHAR ucAudioChipInfo; /* List the audio chip type (3:0) product type (4) and OEM revision (7:5) */ | ||
| 1411 | UCHAR ucProductID; /* Defines as OEM ID or ATI board ID dependent on product type setting */ | ||
| 1412 | UCHAR ucMiscInfo1; /* Tuner voltage (1:0) HW teletext support (3:2) FM audio decoder (5:4) reserved (6) audio scrambling (7) */ | ||
| 1413 | UCHAR ucMiscInfo2; /* I2S input config (0) I2S output config (1) I2S Audio Chip (4:2) SPDIF Output Config (5) reserved (7:6) */ | ||
| 1414 | UCHAR ucMiscInfo3; /* Video Decoder Type (3:0) Video In Standard/Crystal (7:4) */ | ||
| 1415 | UCHAR ucMiscInfo4; /* Video Decoder Host Config (2:0) reserved (7:3) */ | ||
| 1416 | UCHAR ucVideoInput0Info; /* Video Input 0 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) */ | ||
| 1417 | UCHAR ucVideoInput1Info; /* Video Input 1 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) */ | ||
| 1418 | UCHAR ucVideoInput2Info; /* Video Input 2 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) */ | ||
| 1419 | UCHAR ucVideoInput3Info; /* Video Input 3 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) */ | ||
| 1420 | UCHAR ucVideoInput4Info; /* Video Input 4 Type (1:0) F/B setting (2) physical connector ID (5:3) reserved (7:6) */ | ||
| 1421 | } ATOM_MULTIMEDIA_CONFIG_INFO; | ||
| 1422 | |||
| 1423 | /****************************************************************************/ | ||
| 1424 | /* Structures used in FirmwareInfoTable */ | ||
| 1425 | /****************************************************************************/ | ||
| 1426 | |||
| 1427 | /* usBIOSCapability Defintion: */ | ||
| 1428 | /* Bit 0 = 0: Bios image is not Posted, =1:Bios image is Posted; */ | ||
| 1429 | /* Bit 1 = 0: Dual CRTC is not supported, =1: Dual CRTC is supported; */ | ||
| 1430 | /* Bit 2 = 0: Extended Desktop is not supported, =1: Extended Desktop is supported; */ | ||
| 1431 | /* Others: Reserved */ | ||
| 1432 | #define ATOM_BIOS_INFO_ATOM_FIRMWARE_POSTED 0x0001 | ||
| 1433 | #define ATOM_BIOS_INFO_DUAL_CRTC_SUPPORT 0x0002 | ||
| 1434 | #define ATOM_BIOS_INFO_EXTENDED_DESKTOP_SUPPORT 0x0004 | ||
| 1435 | #define ATOM_BIOS_INFO_MEMORY_CLOCK_SS_SUPPORT 0x0008 | ||
| 1436 | #define ATOM_BIOS_INFO_ENGINE_CLOCK_SS_SUPPORT 0x0010 | ||
| 1437 | #define ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU 0x0020 | ||
| 1438 | #define ATOM_BIOS_INFO_WMI_SUPPORT 0x0040 | ||
| 1439 | #define ATOM_BIOS_INFO_PPMODE_ASSIGNGED_BY_SYSTEM 0x0080 | ||
| 1440 | #define ATOM_BIOS_INFO_HYPERMEMORY_SUPPORT 0x0100 | ||
| 1441 | #define ATOM_BIOS_INFO_HYPERMEMORY_SIZE_MASK 0x1E00 | ||
| 1442 | #define ATOM_BIOS_INFO_VPOST_WITHOUT_FIRST_MODE_SET 0x2000 | ||
| 1443 | #define ATOM_BIOS_INFO_BIOS_SCRATCH6_SCL2_REDEFINE 0x4000 | ||
| 1444 | |||
| 1445 | #ifndef _H2INC | ||
| 1446 | |||
| 1447 | /* Please don't add or expand this bitfield structure below, this one will retire soon.! */ | ||
| 1448 | typedef struct _ATOM_FIRMWARE_CAPABILITY { | ||
| 1449 | #if ATOM_BIG_ENDIAN | ||
| 1450 | USHORT Reserved:3; | ||
| 1451 | USHORT HyperMemory_Size:4; | ||
| 1452 | USHORT HyperMemory_Support:1; | ||
| 1453 | USHORT PPMode_Assigned:1; | ||
| 1454 | USHORT WMI_SUPPORT:1; | ||
| 1455 | USHORT GPUControlsBL:1; | ||
| 1456 | USHORT EngineClockSS_Support:1; | ||
| 1457 | USHORT MemoryClockSS_Support:1; | ||
| 1458 | USHORT ExtendedDesktopSupport:1; | ||
| 1459 | USHORT DualCRTC_Support:1; | ||
| 1460 | USHORT FirmwarePosted:1; | ||
| 1461 | #else | ||
| 1462 | USHORT FirmwarePosted:1; | ||
| 1463 | USHORT DualCRTC_Support:1; | ||
| 1464 | USHORT ExtendedDesktopSupport:1; | ||
| 1465 | USHORT MemoryClockSS_Support:1; | ||
| 1466 | USHORT EngineClockSS_Support:1; | ||
| 1467 | USHORT GPUControlsBL:1; | ||
| 1468 | USHORT WMI_SUPPORT:1; | ||
| 1469 | USHORT PPMode_Assigned:1; | ||
| 1470 | USHORT HyperMemory_Support:1; | ||
| 1471 | USHORT HyperMemory_Size:4; | ||
| 1472 | USHORT Reserved:3; | ||
| 1473 | #endif | ||
| 1474 | } ATOM_FIRMWARE_CAPABILITY; | ||
| 1475 | |||
| 1476 | typedef union _ATOM_FIRMWARE_CAPABILITY_ACCESS { | ||
| 1477 | ATOM_FIRMWARE_CAPABILITY sbfAccess; | ||
| 1478 | USHORT susAccess; | ||
| 1479 | } ATOM_FIRMWARE_CAPABILITY_ACCESS; | ||
| 1480 | |||
| 1481 | #else | ||
| 1482 | |||
| 1483 | typedef union _ATOM_FIRMWARE_CAPABILITY_ACCESS { | ||
| 1484 | USHORT susAccess; | ||
| 1485 | } ATOM_FIRMWARE_CAPABILITY_ACCESS; | ||
| 1486 | |||
| 1487 | #endif | ||
| 1488 | |||
| 1489 | typedef struct _ATOM_FIRMWARE_INFO { | ||
| 1490 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 1491 | ULONG ulFirmwareRevision; | ||
| 1492 | ULONG ulDefaultEngineClock; /* In 10Khz unit */ | ||
| 1493 | ULONG ulDefaultMemoryClock; /* In 10Khz unit */ | ||
| 1494 | ULONG ulDriverTargetEngineClock; /* In 10Khz unit */ | ||
| 1495 | ULONG ulDriverTargetMemoryClock; /* In 10Khz unit */ | ||
| 1496 | ULONG ulMaxEngineClockPLL_Output; /* In 10Khz unit */ | ||
| 1497 | ULONG ulMaxMemoryClockPLL_Output; /* In 10Khz unit */ | ||
| 1498 | ULONG ulMaxPixelClockPLL_Output; /* In 10Khz unit */ | ||
| 1499 | ULONG ulASICMaxEngineClock; /* In 10Khz unit */ | ||
| 1500 | ULONG ulASICMaxMemoryClock; /* In 10Khz unit */ | ||
| 1501 | UCHAR ucASICMaxTemperature; | ||
| 1502 | UCHAR ucPadding[3]; /* Don't use them */ | ||
| 1503 | ULONG aulReservedForBIOS[3]; /* Don't use them */ | ||
| 1504 | USHORT usMinEngineClockPLL_Input; /* In 10Khz unit */ | ||
| 1505 | USHORT usMaxEngineClockPLL_Input; /* In 10Khz unit */ | ||
| 1506 | USHORT usMinEngineClockPLL_Output; /* In 10Khz unit */ | ||
| 1507 | USHORT usMinMemoryClockPLL_Input; /* In 10Khz unit */ | ||
| 1508 | USHORT usMaxMemoryClockPLL_Input; /* In 10Khz unit */ | ||
| 1509 | USHORT usMinMemoryClockPLL_Output; /* In 10Khz unit */ | ||
| 1510 | USHORT usMaxPixelClock; /* In 10Khz unit, Max. Pclk */ | ||
| 1511 | USHORT usMinPixelClockPLL_Input; /* In 10Khz unit */ | ||
| 1512 | USHORT usMaxPixelClockPLL_Input; /* In 10Khz unit */ | ||
| 1513 | USHORT usMinPixelClockPLL_Output; /* In 10Khz unit, the definitions above can't change!!! */ | ||
| 1514 | ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability; | ||
| 1515 | USHORT usReferenceClock; /* In 10Khz unit */ | ||
| 1516 | USHORT usPM_RTS_Location; /* RTS PM4 starting location in ROM in 1Kb unit */ | ||
| 1517 | UCHAR ucPM_RTS_StreamSize; /* RTS PM4 packets in Kb unit */ | ||
| 1518 | UCHAR ucDesign_ID; /* Indicate what is the board design */ | ||
| 1519 | UCHAR ucMemoryModule_ID; /* Indicate what is the board design */ | ||
| 1520 | } ATOM_FIRMWARE_INFO; | ||
| 1521 | |||
| 1522 | typedef struct _ATOM_FIRMWARE_INFO_V1_2 { | ||
| 1523 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 1524 | ULONG ulFirmwareRevision; | ||
| 1525 | ULONG ulDefaultEngineClock; /* In 10Khz unit */ | ||
| 1526 | ULONG ulDefaultMemoryClock; /* In 10Khz unit */ | ||
| 1527 | ULONG ulDriverTargetEngineClock; /* In 10Khz unit */ | ||
| 1528 | ULONG ulDriverTargetMemoryClock; /* In 10Khz unit */ | ||
| 1529 | ULONG ulMaxEngineClockPLL_Output; /* In 10Khz unit */ | ||
| 1530 | ULONG ulMaxMemoryClockPLL_Output; /* In 10Khz unit */ | ||
| 1531 | ULONG ulMaxPixelClockPLL_Output; /* In 10Khz unit */ | ||
| 1532 | ULONG ulASICMaxEngineClock; /* In 10Khz unit */ | ||
| 1533 | ULONG ulASICMaxMemoryClock; /* In 10Khz unit */ | ||
| 1534 | UCHAR ucASICMaxTemperature; | ||
| 1535 | UCHAR ucMinAllowedBL_Level; | ||
| 1536 | UCHAR ucPadding[2]; /* Don't use them */ | ||
| 1537 | ULONG aulReservedForBIOS[2]; /* Don't use them */ | ||
| 1538 | ULONG ulMinPixelClockPLL_Output; /* In 10Khz unit */ | ||
| 1539 | USHORT usMinEngineClockPLL_Input; /* In 10Khz unit */ | ||
| 1540 | USHORT usMaxEngineClockPLL_Input; /* In 10Khz unit */ | ||
| 1541 | USHORT usMinEngineClockPLL_Output; /* In 10Khz unit */ | ||
| 1542 | USHORT usMinMemoryClockPLL_Input; /* In 10Khz unit */ | ||
| 1543 | USHORT usMaxMemoryClockPLL_Input; /* In 10Khz unit */ | ||
| 1544 | USHORT usMinMemoryClockPLL_Output; /* In 10Khz unit */ | ||
| 1545 | USHORT usMaxPixelClock; /* In 10Khz unit, Max. Pclk */ | ||
| 1546 | USHORT usMinPixelClockPLL_Input; /* In 10Khz unit */ | ||
| 1547 | USHORT usMaxPixelClockPLL_Input; /* In 10Khz unit */ | ||
| 1548 | USHORT usMinPixelClockPLL_Output; /* In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output */ | ||
| 1549 | ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability; | ||
| 1550 | USHORT usReferenceClock; /* In 10Khz unit */ | ||
| 1551 | USHORT usPM_RTS_Location; /* RTS PM4 starting location in ROM in 1Kb unit */ | ||
| 1552 | UCHAR ucPM_RTS_StreamSize; /* RTS PM4 packets in Kb unit */ | ||
| 1553 | UCHAR ucDesign_ID; /* Indicate what is the board design */ | ||
| 1554 | UCHAR ucMemoryModule_ID; /* Indicate what is the board design */ | ||
| 1555 | } ATOM_FIRMWARE_INFO_V1_2; | ||
| 1556 | |||
| 1557 | typedef struct _ATOM_FIRMWARE_INFO_V1_3 { | ||
| 1558 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 1559 | ULONG ulFirmwareRevision; | ||
| 1560 | ULONG ulDefaultEngineClock; /* In 10Khz unit */ | ||
| 1561 | ULONG ulDefaultMemoryClock; /* In 10Khz unit */ | ||
| 1562 | ULONG ulDriverTargetEngineClock; /* In 10Khz unit */ | ||
| 1563 | ULONG ulDriverTargetMemoryClock; /* In 10Khz unit */ | ||
| 1564 | ULONG ulMaxEngineClockPLL_Output; /* In 10Khz unit */ | ||
| 1565 | ULONG ulMaxMemoryClockPLL_Output; /* In 10Khz unit */ | ||
| 1566 | ULONG ulMaxPixelClockPLL_Output; /* In 10Khz unit */ | ||
| 1567 | ULONG ulASICMaxEngineClock; /* In 10Khz unit */ | ||
| 1568 | ULONG ulASICMaxMemoryClock; /* In 10Khz unit */ | ||
| 1569 | UCHAR ucASICMaxTemperature; | ||
| 1570 | UCHAR ucMinAllowedBL_Level; | ||
| 1571 | UCHAR ucPadding[2]; /* Don't use them */ | ||
| 1572 | ULONG aulReservedForBIOS; /* Don't use them */ | ||
| 1573 | ULONG ul3DAccelerationEngineClock; /* In 10Khz unit */ | ||
| 1574 | ULONG ulMinPixelClockPLL_Output; /* In 10Khz unit */ | ||
| 1575 | USHORT usMinEngineClockPLL_Input; /* In 10Khz unit */ | ||
| 1576 | USHORT usMaxEngineClockPLL_Input; /* In 10Khz unit */ | ||
| 1577 | USHORT usMinEngineClockPLL_Output; /* In 10Khz unit */ | ||
| 1578 | USHORT usMinMemoryClockPLL_Input; /* In 10Khz unit */ | ||
| 1579 | USHORT usMaxMemoryClockPLL_Input; /* In 10Khz unit */ | ||
| 1580 | USHORT usMinMemoryClockPLL_Output; /* In 10Khz unit */ | ||
| 1581 | USHORT usMaxPixelClock; /* In 10Khz unit, Max. Pclk */ | ||
| 1582 | USHORT usMinPixelClockPLL_Input; /* In 10Khz unit */ | ||
| 1583 | USHORT usMaxPixelClockPLL_Input; /* In 10Khz unit */ | ||
| 1584 | USHORT usMinPixelClockPLL_Output; /* In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output */ | ||
| 1585 | ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability; | ||
| 1586 | USHORT usReferenceClock; /* In 10Khz unit */ | ||
| 1587 | USHORT usPM_RTS_Location; /* RTS PM4 starting location in ROM in 1Kb unit */ | ||
| 1588 | UCHAR ucPM_RTS_StreamSize; /* RTS PM4 packets in Kb unit */ | ||
| 1589 | UCHAR ucDesign_ID; /* Indicate what is the board design */ | ||
| 1590 | UCHAR ucMemoryModule_ID; /* Indicate what is the board design */ | ||
| 1591 | } ATOM_FIRMWARE_INFO_V1_3; | ||
| 1592 | |||
| 1593 | typedef struct _ATOM_FIRMWARE_INFO_V1_4 { | ||
| 1594 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 1595 | ULONG ulFirmwareRevision; | ||
| 1596 | ULONG ulDefaultEngineClock; /* In 10Khz unit */ | ||
| 1597 | ULONG ulDefaultMemoryClock; /* In 10Khz unit */ | ||
| 1598 | ULONG ulDriverTargetEngineClock; /* In 10Khz unit */ | ||
| 1599 | ULONG ulDriverTargetMemoryClock; /* In 10Khz unit */ | ||
| 1600 | ULONG ulMaxEngineClockPLL_Output; /* In 10Khz unit */ | ||
| 1601 | ULONG ulMaxMemoryClockPLL_Output; /* In 10Khz unit */ | ||
| 1602 | ULONG ulMaxPixelClockPLL_Output; /* In 10Khz unit */ | ||
| 1603 | ULONG ulASICMaxEngineClock; /* In 10Khz unit */ | ||
| 1604 | ULONG ulASICMaxMemoryClock; /* In 10Khz unit */ | ||
| 1605 | UCHAR ucASICMaxTemperature; | ||
| 1606 | UCHAR ucMinAllowedBL_Level; | ||
| 1607 | USHORT usBootUpVDDCVoltage; /* In MV unit */ | ||
| 1608 | USHORT usLcdMinPixelClockPLL_Output; /* In MHz unit */ | ||
| 1609 | USHORT usLcdMaxPixelClockPLL_Output; /* In MHz unit */ | ||
| 1610 | ULONG ul3DAccelerationEngineClock; /* In 10Khz unit */ | ||
| 1611 | ULONG ulMinPixelClockPLL_Output; /* In 10Khz unit */ | ||
| 1612 | USHORT usMinEngineClockPLL_Input; /* In 10Khz unit */ | ||
| 1613 | USHORT usMaxEngineClockPLL_Input; /* In 10Khz unit */ | ||
| 1614 | USHORT usMinEngineClockPLL_Output; /* In 10Khz unit */ | ||
| 1615 | USHORT usMinMemoryClockPLL_Input; /* In 10Khz unit */ | ||
| 1616 | USHORT usMaxMemoryClockPLL_Input; /* In 10Khz unit */ | ||
| 1617 | USHORT usMinMemoryClockPLL_Output; /* In 10Khz unit */ | ||
| 1618 | USHORT usMaxPixelClock; /* In 10Khz unit, Max. Pclk */ | ||
| 1619 | USHORT usMinPixelClockPLL_Input; /* In 10Khz unit */ | ||
| 1620 | USHORT usMaxPixelClockPLL_Input; /* In 10Khz unit */ | ||
| 1621 | USHORT usMinPixelClockPLL_Output; /* In 10Khz unit - lower 16bit of ulMinPixelClockPLL_Output */ | ||
| 1622 | ATOM_FIRMWARE_CAPABILITY_ACCESS usFirmwareCapability; | ||
| 1623 | USHORT usReferenceClock; /* In 10Khz unit */ | ||
| 1624 | USHORT usPM_RTS_Location; /* RTS PM4 starting location in ROM in 1Kb unit */ | ||
| 1625 | UCHAR ucPM_RTS_StreamSize; /* RTS PM4 packets in Kb unit */ | ||
| 1626 | UCHAR ucDesign_ID; /* Indicate what is the board design */ | ||
| 1627 | UCHAR ucMemoryModule_ID; /* Indicate what is the board design */ | ||
| 1628 | } ATOM_FIRMWARE_INFO_V1_4; | ||
| 1629 | |||
| 1630 | #define ATOM_FIRMWARE_INFO_LAST ATOM_FIRMWARE_INFO_V1_4 | ||
| 1631 | |||
| 1632 | /****************************************************************************/ | ||
| 1633 | /* Structures used in IntegratedSystemInfoTable */ | ||
| 1634 | /****************************************************************************/ | ||
| 1635 | #define IGP_CAP_FLAG_DYNAMIC_CLOCK_EN 0x2 | ||
| 1636 | #define IGP_CAP_FLAG_AC_CARD 0x4 | ||
| 1637 | #define IGP_CAP_FLAG_SDVO_CARD 0x8 | ||
| 1638 | #define IGP_CAP_FLAG_POSTDIV_BY_2_MODE 0x10 | ||
| 1639 | |||
| 1640 | typedef struct _ATOM_INTEGRATED_SYSTEM_INFO { | ||
| 1641 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 1642 | ULONG ulBootUpEngineClock; /* in 10kHz unit */ | ||
| 1643 | ULONG ulBootUpMemoryClock; /* in 10kHz unit */ | ||
| 1644 | ULONG ulMaxSystemMemoryClock; /* in 10kHz unit */ | ||
| 1645 | ULONG ulMinSystemMemoryClock; /* in 10kHz unit */ | ||
| 1646 | UCHAR ucNumberOfCyclesInPeriodHi; | ||
| 1647 | UCHAR ucLCDTimingSel; /* =0:not valid.!=0 sel this timing descriptor from LCD EDID. */ | ||
| 1648 | USHORT usReserved1; | ||
| 1649 | USHORT usInterNBVoltageLow; /* An intermidiate PMW value to set the voltage */ | ||
| 1650 | USHORT usInterNBVoltageHigh; /* Another intermidiate PMW value to set the voltage */ | ||
| 1651 | ULONG ulReserved[2]; | ||
| 1652 | |||
| 1653 | USHORT usFSBClock; /* In MHz unit */ | ||
| 1654 | USHORT usCapabilityFlag; /* Bit0=1 indicates the fake HDMI support,Bit1=0/1 for Dynamic clocking dis/enable */ | ||
| 1655 | /* Bit[3:2]== 0:No PCIE card, 1:AC card, 2:SDVO card */ | ||
| 1656 | /* Bit[4]==1: P/2 mode, ==0: P/1 mode */ | ||
| 1657 | USHORT usPCIENBCfgReg7; /* bit[7:0]=MUX_Sel, bit[9:8]=MUX_SEL_LEVEL2, bit[10]=Lane_Reversal */ | ||
| 1658 | USHORT usK8MemoryClock; /* in MHz unit */ | ||
| 1659 | USHORT usK8SyncStartDelay; /* in 0.01 us unit */ | ||
| 1660 | USHORT usK8DataReturnTime; /* in 0.01 us unit */ | ||
| 1661 | UCHAR ucMaxNBVoltage; | ||
| 1662 | UCHAR ucMinNBVoltage; | ||
| 1663 | UCHAR ucMemoryType; /* [7:4]=1:DDR1;=2:DDR2;=3:DDR3.[3:0] is reserved */ | ||
| 1664 | UCHAR ucNumberOfCyclesInPeriod; /* CG.FVTHROT_PWM_CTRL_REG0.NumberOfCyclesInPeriod */ | ||
| 1665 | UCHAR ucStartingPWM_HighTime; /* CG.FVTHROT_PWM_CTRL_REG0.StartingPWM_HighTime */ | ||
| 1666 | UCHAR ucHTLinkWidth; /* 16 bit vs. 8 bit */ | ||
| 1667 | UCHAR ucMaxNBVoltageHigh; | ||
| 1668 | UCHAR ucMinNBVoltageHigh; | ||
| 1669 | } ATOM_INTEGRATED_SYSTEM_INFO; | ||
| 1670 | |||
| 1671 | /* Explanation on entries in ATOM_INTEGRATED_SYSTEM_INFO | ||
| 1672 | ulBootUpMemoryClock: For Intel IGP,it's the UMA system memory clock | ||
| 1673 | For AMD IGP,it's 0 if no SidePort memory installed or it's the boot-up SidePort memory clock | ||
| 1674 | ulMaxSystemMemoryClock: For Intel IGP,it's the Max freq from memory SPD if memory runs in ASYNC mode or otherwise (SYNC mode) it's 0 | ||
| 1675 | For AMD IGP,for now this can be 0 | ||
| 1676 | ulMinSystemMemoryClock: For Intel IGP,it's 133MHz if memory runs in ASYNC mode or otherwise (SYNC mode) it's 0 | ||
| 1677 | For AMD IGP,for now this can be 0 | ||
| 1678 | |||
| 1679 | usFSBClock: For Intel IGP,it's FSB Freq | ||
| 1680 | For AMD IGP,it's HT Link Speed | ||
| 1681 | |||
| 1682 | usK8MemoryClock: For AMD IGP only. For RevF CPU, set it to 200 | ||
| 1683 | usK8SyncStartDelay: For AMD IGP only. Memory access latency in K8, required for watermark calculation | ||
| 1684 | usK8DataReturnTime: For AMD IGP only. Memory access latency in K8, required for watermark calculation | ||
| 1685 | |||
| 1686 | VC:Voltage Control | ||
| 1687 | ucMaxNBVoltage: Voltage regulator dependent PWM value. Low 8 bits of the value for the max voltage.Set this one to 0xFF if VC without PWM. Set this to 0x0 if no VC at all. | ||
| 1688 | ucMinNBVoltage: Voltage regulator dependent PWM value. Low 8 bits of the value for the min voltage.Set this one to 0x00 if VC without PWM or no VC at all. | ||
| 1689 | |||
| 1690 | ucNumberOfCyclesInPeriod: Indicate how many cycles when PWM duty is 100%. low 8 bits of the value. | ||
| 1691 | ucNumberOfCyclesInPeriodHi: Indicate how many cycles when PWM duty is 100%. high 8 bits of the value.If the PWM has an inverter,set bit [7]==1,otherwise set it 0 | ||
| 1692 | |||
| 1693 | ucMaxNBVoltageHigh: Voltage regulator dependent PWM value. High 8 bits of the value for the max voltage.Set this one to 0xFF if VC without PWM. Set this to 0x0 if no VC at all. | ||
| 1694 | ucMinNBVoltageHigh: Voltage regulator dependent PWM value. High 8 bits of the value for the min voltage.Set this one to 0x00 if VC without PWM or no VC at all. | ||
| 1695 | |||
| 1696 | usInterNBVoltageLow: Voltage regulator dependent PWM value. The value makes the the voltage >=Min NB voltage but <=InterNBVoltageHigh. Set this to 0x0000 if VC without PWM or no VC at all. | ||
| 1697 | usInterNBVoltageHigh: Voltage regulator dependent PWM value. The value makes the the voltage >=InterNBVoltageLow but <=Max NB voltage.Set this to 0x0000 if VC without PWM or no VC at all. | ||
| 1698 | */ | ||
| 1699 | |||
| 1700 | /* | ||
| 1701 | The following IGP table is introduced from RS780, which is supposed to be put by SBIOS in FB before IGP VBIOS starts VPOST; | ||
| 1702 | Then VBIOS will copy the whole structure to its image so all GPU SW components can access this data structure to get whatever they need. | ||
| 1703 | The enough reservation should allow us to never change table revisions. Whenever needed, a GPU SW component can use reserved portion for new data entries. | ||
| 1704 | |||
| 1705 | SW components can access the IGP system infor structure in the same way as before | ||
| 1706 | */ | ||
| 1707 | |||
| 1708 | typedef struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 { | ||
| 1709 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 1710 | ULONG ulBootUpEngineClock; /* in 10kHz unit */ | ||
| 1711 | ULONG ulReserved1[2]; /* must be 0x0 for the reserved */ | ||
| 1712 | ULONG ulBootUpUMAClock; /* in 10kHz unit */ | ||
| 1713 | ULONG ulBootUpSidePortClock; /* in 10kHz unit */ | ||
| 1714 | ULONG ulMinSidePortClock; /* in 10kHz unit */ | ||
| 1715 | ULONG ulReserved2[6]; /* must be 0x0 for the reserved */ | ||
| 1716 | ULONG ulSystemConfig; /* see explanation below */ | ||
| 1717 | ULONG ulBootUpReqDisplayVector; | ||
| 1718 | ULONG ulOtherDisplayMisc; | ||
| 1719 | ULONG ulDDISlot1Config; | ||
| 1720 | ULONG ulDDISlot2Config; | ||
| 1721 | UCHAR ucMemoryType; /* [3:0]=1:DDR1;=2:DDR2;=3:DDR3.[7:4] is reserved */ | ||
| 1722 | UCHAR ucUMAChannelNumber; | ||
| 1723 | UCHAR ucDockingPinBit; | ||
| 1724 | UCHAR ucDockingPinPolarity; | ||
| 1725 | ULONG ulDockingPinCFGInfo; | ||
| 1726 | ULONG ulCPUCapInfo; | ||
| 1727 | USHORT usNumberOfCyclesInPeriod; | ||
| 1728 | USHORT usMaxNBVoltage; | ||
| 1729 | USHORT usMinNBVoltage; | ||
| 1730 | USHORT usBootUpNBVoltage; | ||
| 1731 | ULONG ulHTLinkFreq; /* in 10Khz */ | ||
| 1732 | USHORT usMinHTLinkWidth; | ||
| 1733 | USHORT usMaxHTLinkWidth; | ||
| 1734 | USHORT usUMASyncStartDelay; | ||
| 1735 | USHORT usUMADataReturnTime; | ||
| 1736 | USHORT usLinkStatusZeroTime; | ||
| 1737 | USHORT usReserved; | ||
| 1738 | ULONG ulHighVoltageHTLinkFreq; /* in 10Khz */ | ||
| 1739 | ULONG ulLowVoltageHTLinkFreq; /* in 10Khz */ | ||
| 1740 | USHORT usMaxUpStreamHTLinkWidth; | ||
| 1741 | USHORT usMaxDownStreamHTLinkWidth; | ||
| 1742 | USHORT usMinUpStreamHTLinkWidth; | ||
| 1743 | USHORT usMinDownStreamHTLinkWidth; | ||
| 1744 | ULONG ulReserved3[97]; /* must be 0x0 */ | ||
| 1745 | } ATOM_INTEGRATED_SYSTEM_INFO_V2; | ||
| 1746 | |||
| 1747 | /* | ||
| 1748 | ulBootUpEngineClock: Boot-up Engine Clock in 10Khz; | ||
| 1749 | ulBootUpUMAClock: Boot-up UMA Clock in 10Khz; it must be 0x0 when UMA is not present | ||
| 1750 | ulBootUpSidePortClock: Boot-up SidePort Clock in 10Khz; it must be 0x0 when SidePort Memory is not present,this could be equal to or less than maximum supported Sideport memory clock | ||
| 1751 | |||
| 1752 | ulSystemConfig: | ||
| 1753 | Bit[0]=1: PowerExpress mode =0 Non-PowerExpress mode; | ||
| 1754 | Bit[1]=1: system boots up at AMD overdrived state or user customized mode. In this case, driver will just stick to this boot-up mode. No other PowerPlay state | ||
| 1755 | =0: system boots up at driver control state. Power state depends on PowerPlay table. | ||
| 1756 | Bit[2]=1: PWM method is used on NB voltage control. =0: GPIO method is used. | ||
| 1757 | Bit[3]=1: Only one power state(Performance) will be supported. | ||
| 1758 | =0: Multiple power states supported from PowerPlay table. | ||
| 1759 | Bit[4]=1: CLMC is supported and enabled on current system. | ||
| 1760 | =0: CLMC is not supported or enabled on current system. SBIOS need to support HT link/freq change through ATIF interface. | ||
| 1761 | Bit[5]=1: Enable CDLW for all driver control power states. Max HT width is from SBIOS, while Min HT width is determined by display requirement. | ||
| 1762 | =0: CDLW is disabled. If CLMC is enabled case, Min HT width will be set equal to Max HT width. If CLMC disabled case, Max HT width will be applied. | ||
| 1763 | Bit[6]=1: High Voltage requested for all power states. In this case, voltage will be forced at 1.1v and powerplay table voltage drop/throttling request will be ignored. | ||
| 1764 | =0: Voltage settings is determined by powerplay table. | ||
| 1765 | Bit[7]=1: Enable CLMC as hybrid Mode. CDLD and CILR will be disabled in this case and we're using legacy C1E. This is workaround for CPU(Griffin) performance issue. | ||
| 1766 | =0: Enable CLMC as regular mode, CDLD and CILR will be enabled. | ||
| 1767 | |||
| 1768 | ulBootUpReqDisplayVector: This dword is a bit vector indicates what display devices are requested during boot-up. Refer to ATOM_DEVICE_xxx_SUPPORT for the bit vector definitions. | ||
| 1769 | |||
| 1770 | ulOtherDisplayMisc: [15:8]- Bootup LCD Expansion selection; 0-center, 1-full panel size expansion; | ||
| 1771 | [7:0] - BootupTV standard selection; This is a bit vector to indicate what TV standards are supported by the system. Refer to ucTVSuppportedStd definition; | ||
| 1772 | |||
| 1773 | ulDDISlot1Config: Describes the PCIE lane configuration on this DDI PCIE slot (ADD2 card) or connector (Mobile design). | ||
| 1774 | [3:0] - Bit vector to indicate PCIE lane config of the DDI slot/connector on chassis (bit 0=1 lane 3:0; bit 1=1 lane 7:4; bit 2=1 lane 11:8; bit 3=1 lane 15:12) | ||
| 1775 | [7:4] - Bit vector to indicate PCIE lane config of the same DDI slot/connector on docking station (bit 0=1 lane 3:0; bit 1=1 lane 7:4; bit 2=1 lane 11:8; bit 3=1 lane 15:12) | ||
| 1776 | [15:8] - Lane configuration attribute; | ||
| 1777 | [23:16]- Connector type, possible value: | ||
| 1778 | CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D | ||
| 1779 | CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D | ||
| 1780 | CONNECTOR_OBJECT_ID_HDMI_TYPE_A | ||
| 1781 | CONNECTOR_OBJECT_ID_DISPLAYPORT | ||
| 1782 | [31:24]- Reserved | ||
| 1783 | |||
| 1784 | ulDDISlot2Config: Same as Slot1. | ||
| 1785 | ucMemoryType: SidePort memory type, set it to 0x0 when Sideport memory is not installed. Driver needs this info to change sideport memory clock. Not for display in CCC. | ||
| 1786 | For IGP, Hypermemory is the only memory type showed in CCC. | ||
| 1787 | |||
| 1788 | ucUMAChannelNumber: how many channels for the UMA; | ||
| 1789 | |||
| 1790 | ulDockingPinCFGInfo: [15:0]-Bus/Device/Function # to CFG to read this Docking Pin; [31:16]-reg offset in CFG to read this pin | ||
| 1791 | ucDockingPinBit: which bit in this register to read the pin status; | ||
| 1792 | ucDockingPinPolarity:Polarity of the pin when docked; | ||
| 1793 | |||
| 1794 | ulCPUCapInfo: [7:0]=1:Griffin;[7:0]=2:Greyhound;[7:0]=3:K8, other bits reserved for now and must be 0x0 | ||
| 1795 | |||
| 1796 | usNumberOfCyclesInPeriod:Indicate how many cycles when PWM duty is 100%. | ||
| 1797 | usMaxNBVoltage:Max. voltage control value in either PWM or GPIO mode. | ||
| 1798 | usMinNBVoltage:Min. voltage control value in either PWM or GPIO mode. | ||
| 1799 | GPIO mode: both usMaxNBVoltage & usMinNBVoltage have a valid value ulSystemConfig.SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE=0 | ||
| 1800 | PWM mode: both usMaxNBVoltage & usMinNBVoltage have a valid value ulSystemConfig.SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE=1 | ||
| 1801 | GPU SW don't control mode: usMaxNBVoltage & usMinNBVoltage=0 and no care about ulSystemConfig.SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE | ||
| 1802 | usBootUpNBVoltage:Boot-up voltage regulator dependent PWM value. | ||
| 1803 | |||
| 1804 | ulHTLinkFreq: Bootup HT link Frequency in 10Khz. | ||
| 1805 | usMinHTLinkWidth: Bootup minimum HT link width. If CDLW disabled, this is equal to usMaxHTLinkWidth. | ||
| 1806 | If CDLW enabled, both upstream and downstream width should be the same during bootup. | ||
| 1807 | usMaxHTLinkWidth: Bootup maximum HT link width. If CDLW disabled, this is equal to usMinHTLinkWidth. | ||
| 1808 | If CDLW enabled, both upstream and downstream width should be the same during bootup. | ||
| 1809 | |||
| 1810 | usUMASyncStartDelay: Memory access latency, required for watermark calculation | ||
| 1811 | usUMADataReturnTime: Memory access latency, required for watermark calculation | ||
| 1812 | usLinkStatusZeroTime:Memory access latency required for watermark calculation, set this to 0x0 for K8 CPU, set a proper value in 0.01 the unit of us | ||
| 1813 | for Griffin or Greyhound. SBIOS needs to convert to actual time by: | ||
| 1814 | if T0Ttime [5:4]=00b, then usLinkStatusZeroTime=T0Ttime [3:0]*0.1us (0.0 to 1.5us) | ||
| 1815 | if T0Ttime [5:4]=01b, then usLinkStatusZeroTime=T0Ttime [3:0]*0.5us (0.0 to 7.5us) | ||
| 1816 | if T0Ttime [5:4]=10b, then usLinkStatusZeroTime=T0Ttime [3:0]*2.0us (0.0 to 30us) | ||
| 1817 | if T0Ttime [5:4]=11b, and T0Ttime [3:0]=0x0 to 0xa, then usLinkStatusZeroTime=T0Ttime [3:0]*20us (0.0 to 200us) | ||
| 1818 | |||
| 1819 | ulHighVoltageHTLinkFreq: HT link frequency for power state with low voltage. If boot up runs in HT1, this must be 0. | ||
| 1820 | This must be less than or equal to ulHTLinkFreq(bootup frequency). | ||
| 1821 | ulLowVoltageHTLinkFreq: HT link frequency for power state with low voltage or voltage scaling 1.0v~1.1v. If boot up runs in HT1, this must be 0. | ||
| 1822 | This must be less than or equal to ulHighVoltageHTLinkFreq. | ||
| 1823 | |||
| 1824 | usMaxUpStreamHTLinkWidth: Asymmetric link width support in the future, to replace usMaxHTLinkWidth. Not used for now. | ||
| 1825 | usMaxDownStreamHTLinkWidth: same as above. | ||
| 1826 | usMinUpStreamHTLinkWidth: Asymmetric link width support in the future, to replace usMinHTLinkWidth. Not used for now. | ||
| 1827 | usMinDownStreamHTLinkWidth: same as above. | ||
| 1828 | */ | ||
| 1829 | |||
| 1830 | #define SYSTEM_CONFIG_POWEREXPRESS_ENABLE 0x00000001 | ||
| 1831 | #define SYSTEM_CONFIG_RUN_AT_OVERDRIVE_ENGINE 0x00000002 | ||
| 1832 | #define SYSTEM_CONFIG_USE_PWM_ON_VOLTAGE 0x00000004 | ||
| 1833 | #define SYSTEM_CONFIG_PERFORMANCE_POWERSTATE_ONLY 0x00000008 | ||
| 1834 | #define SYSTEM_CONFIG_CLMC_ENABLED 0x00000010 | ||
| 1835 | #define SYSTEM_CONFIG_CDLW_ENABLED 0x00000020 | ||
| 1836 | #define SYSTEM_CONFIG_HIGH_VOLTAGE_REQUESTED 0x00000040 | ||
| 1837 | #define SYSTEM_CONFIG_CLMC_HYBRID_MODE_ENABLED 0x00000080 | ||
| 1838 | |||
| 1839 | #define IGP_DDI_SLOT_LANE_CONFIG_MASK 0x000000FF | ||
| 1840 | |||
| 1841 | #define b0IGP_DDI_SLOT_LANE_MAP_MASK 0x0F | ||
| 1842 | #define b0IGP_DDI_SLOT_DOCKING_LANE_MAP_MASK 0xF0 | ||
| 1843 | #define b0IGP_DDI_SLOT_CONFIG_LANE_0_3 0x01 | ||
| 1844 | #define b0IGP_DDI_SLOT_CONFIG_LANE_4_7 0x02 | ||
| 1845 | #define b0IGP_DDI_SLOT_CONFIG_LANE_8_11 0x04 | ||
| 1846 | #define b0IGP_DDI_SLOT_CONFIG_LANE_12_15 0x08 | ||
| 1847 | |||
| 1848 | #define IGP_DDI_SLOT_ATTRIBUTE_MASK 0x0000FF00 | ||
| 1849 | #define IGP_DDI_SLOT_CONFIG_REVERSED 0x00000100 | ||
| 1850 | #define b1IGP_DDI_SLOT_CONFIG_REVERSED 0x01 | ||
| 1851 | |||
| 1852 | #define IGP_DDI_SLOT_CONNECTOR_TYPE_MASK 0x00FF0000 | ||
| 1853 | |||
| 1854 | #define ATOM_CRT_INT_ENCODER1_INDEX 0x00000000 | ||
| 1855 | #define ATOM_LCD_INT_ENCODER1_INDEX 0x00000001 | ||
| 1856 | #define ATOM_TV_INT_ENCODER1_INDEX 0x00000002 | ||
| 1857 | #define ATOM_DFP_INT_ENCODER1_INDEX 0x00000003 | ||
| 1858 | #define ATOM_CRT_INT_ENCODER2_INDEX 0x00000004 | ||
| 1859 | #define ATOM_LCD_EXT_ENCODER1_INDEX 0x00000005 | ||
| 1860 | #define ATOM_TV_EXT_ENCODER1_INDEX 0x00000006 | ||
| 1861 | #define ATOM_DFP_EXT_ENCODER1_INDEX 0x00000007 | ||
| 1862 | #define ATOM_CV_INT_ENCODER1_INDEX 0x00000008 | ||
| 1863 | #define ATOM_DFP_INT_ENCODER2_INDEX 0x00000009 | ||
| 1864 | #define ATOM_CRT_EXT_ENCODER1_INDEX 0x0000000A | ||
| 1865 | #define ATOM_CV_EXT_ENCODER1_INDEX 0x0000000B | ||
| 1866 | #define ATOM_DFP_INT_ENCODER3_INDEX 0x0000000C | ||
| 1867 | #define ATOM_DFP_INT_ENCODER4_INDEX 0x0000000D | ||
| 1868 | |||
| 1869 | /* define ASIC internal encoder id ( bit vector ) */ | ||
| 1870 | #define ASIC_INT_DAC1_ENCODER_ID 0x00 | ||
| 1871 | #define ASIC_INT_TV_ENCODER_ID 0x02 | ||
| 1872 | #define ASIC_INT_DIG1_ENCODER_ID 0x03 | ||
| 1873 | #define ASIC_INT_DAC2_ENCODER_ID 0x04 | ||
| 1874 | #define ASIC_EXT_TV_ENCODER_ID 0x06 | ||
| 1875 | #define ASIC_INT_DVO_ENCODER_ID 0x07 | ||
| 1876 | #define ASIC_INT_DIG2_ENCODER_ID 0x09 | ||
| 1877 | #define ASIC_EXT_DIG_ENCODER_ID 0x05 | ||
| 1878 | |||
| 1879 | /* define Encoder attribute */ | ||
| 1880 | #define ATOM_ANALOG_ENCODER 0 | ||
| 1881 | #define ATOM_DIGITAL_ENCODER 1 | ||
| 1882 | |||
| 1883 | #define ATOM_DEVICE_CRT1_INDEX 0x00000000 | ||
| 1884 | #define ATOM_DEVICE_LCD1_INDEX 0x00000001 | ||
| 1885 | #define ATOM_DEVICE_TV1_INDEX 0x00000002 | ||
| 1886 | #define ATOM_DEVICE_DFP1_INDEX 0x00000003 | ||
| 1887 | #define ATOM_DEVICE_CRT2_INDEX 0x00000004 | ||
| 1888 | #define ATOM_DEVICE_LCD2_INDEX 0x00000005 | ||
| 1889 | #define ATOM_DEVICE_TV2_INDEX 0x00000006 | ||
| 1890 | #define ATOM_DEVICE_DFP2_INDEX 0x00000007 | ||
| 1891 | #define ATOM_DEVICE_CV_INDEX 0x00000008 | ||
| 1892 | #define ATOM_DEVICE_DFP3_INDEX 0x00000009 | ||
| 1893 | #define ATOM_DEVICE_DFP4_INDEX 0x0000000A | ||
| 1894 | #define ATOM_DEVICE_DFP5_INDEX 0x0000000B | ||
| 1895 | #define ATOM_DEVICE_RESERVEDC_INDEX 0x0000000C | ||
| 1896 | #define ATOM_DEVICE_RESERVEDD_INDEX 0x0000000D | ||
| 1897 | #define ATOM_DEVICE_RESERVEDE_INDEX 0x0000000E | ||
| 1898 | #define ATOM_DEVICE_RESERVEDF_INDEX 0x0000000F | ||
| 1899 | #define ATOM_MAX_SUPPORTED_DEVICE_INFO (ATOM_DEVICE_DFP3_INDEX+1) | ||
| 1900 | #define ATOM_MAX_SUPPORTED_DEVICE_INFO_2 ATOM_MAX_SUPPORTED_DEVICE_INFO | ||
| 1901 | #define ATOM_MAX_SUPPORTED_DEVICE_INFO_3 (ATOM_DEVICE_DFP5_INDEX + 1) | ||
| 1902 | |||
| 1903 | #define ATOM_MAX_SUPPORTED_DEVICE (ATOM_DEVICE_RESERVEDF_INDEX+1) | ||
| 1904 | |||
| 1905 | #define ATOM_DEVICE_CRT1_SUPPORT (0x1L << ATOM_DEVICE_CRT1_INDEX) | ||
| 1906 | #define ATOM_DEVICE_LCD1_SUPPORT (0x1L << ATOM_DEVICE_LCD1_INDEX) | ||
| 1907 | #define ATOM_DEVICE_TV1_SUPPORT (0x1L << ATOM_DEVICE_TV1_INDEX) | ||
| 1908 | #define ATOM_DEVICE_DFP1_SUPPORT (0x1L << ATOM_DEVICE_DFP1_INDEX) | ||
| 1909 | #define ATOM_DEVICE_CRT2_SUPPORT (0x1L << ATOM_DEVICE_CRT2_INDEX) | ||
| 1910 | #define ATOM_DEVICE_LCD2_SUPPORT (0x1L << ATOM_DEVICE_LCD2_INDEX) | ||
| 1911 | #define ATOM_DEVICE_TV2_SUPPORT (0x1L << ATOM_DEVICE_TV2_INDEX) | ||
| 1912 | #define ATOM_DEVICE_DFP2_SUPPORT (0x1L << ATOM_DEVICE_DFP2_INDEX) | ||
| 1913 | #define ATOM_DEVICE_CV_SUPPORT (0x1L << ATOM_DEVICE_CV_INDEX) | ||
| 1914 | #define ATOM_DEVICE_DFP3_SUPPORT (0x1L << ATOM_DEVICE_DFP3_INDEX) | ||
| 1915 | #define ATOM_DEVICE_DFP4_SUPPORT (0x1L << ATOM_DEVICE_DFP4_INDEX ) | ||
| 1916 | #define ATOM_DEVICE_DFP5_SUPPORT (0x1L << ATOM_DEVICE_DFP5_INDEX) | ||
| 1917 | |||
| 1918 | #define ATOM_DEVICE_CRT_SUPPORT \ | ||
| 1919 | (ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_CRT2_SUPPORT) | ||
| 1920 | #define ATOM_DEVICE_DFP_SUPPORT \ | ||
| 1921 | (ATOM_DEVICE_DFP1_SUPPORT | ATOM_DEVICE_DFP2_SUPPORT | \ | ||
| 1922 | ATOM_DEVICE_DFP3_SUPPORT | ATOM_DEVICE_DFP4_SUPPORT | \ | ||
| 1923 | ATOM_DEVICE_DFP5_SUPPORT) | ||
| 1924 | #define ATOM_DEVICE_TV_SUPPORT \ | ||
| 1925 | (ATOM_DEVICE_TV1_SUPPORT | ATOM_DEVICE_TV2_SUPPORT) | ||
| 1926 | #define ATOM_DEVICE_LCD_SUPPORT \ | ||
| 1927 | (ATOM_DEVICE_LCD1_SUPPORT | ATOM_DEVICE_LCD2_SUPPORT) | ||
| 1928 | |||
| 1929 | #define ATOM_DEVICE_CONNECTOR_TYPE_MASK 0x000000F0 | ||
| 1930 | #define ATOM_DEVICE_CONNECTOR_TYPE_SHIFT 0x00000004 | ||
| 1931 | #define ATOM_DEVICE_CONNECTOR_VGA 0x00000001 | ||
| 1932 | #define ATOM_DEVICE_CONNECTOR_DVI_I 0x00000002 | ||
| 1933 | #define ATOM_DEVICE_CONNECTOR_DVI_D 0x00000003 | ||
| 1934 | #define ATOM_DEVICE_CONNECTOR_DVI_A 0x00000004 | ||
| 1935 | #define ATOM_DEVICE_CONNECTOR_SVIDEO 0x00000005 | ||
| 1936 | #define ATOM_DEVICE_CONNECTOR_COMPOSITE 0x00000006 | ||
| 1937 | #define ATOM_DEVICE_CONNECTOR_LVDS 0x00000007 | ||
| 1938 | #define ATOM_DEVICE_CONNECTOR_DIGI_LINK 0x00000008 | ||
| 1939 | #define ATOM_DEVICE_CONNECTOR_SCART 0x00000009 | ||
| 1940 | #define ATOM_DEVICE_CONNECTOR_HDMI_TYPE_A 0x0000000A | ||
| 1941 | #define ATOM_DEVICE_CONNECTOR_HDMI_TYPE_B 0x0000000B | ||
| 1942 | #define ATOM_DEVICE_CONNECTOR_CASE_1 0x0000000E | ||
| 1943 | #define ATOM_DEVICE_CONNECTOR_DISPLAYPORT 0x0000000F | ||
| 1944 | |||
| 1945 | #define ATOM_DEVICE_DAC_INFO_MASK 0x0000000F | ||
| 1946 | #define ATOM_DEVICE_DAC_INFO_SHIFT 0x00000000 | ||
| 1947 | #define ATOM_DEVICE_DAC_INFO_NODAC 0x00000000 | ||
| 1948 | #define ATOM_DEVICE_DAC_INFO_DACA 0x00000001 | ||
| 1949 | #define ATOM_DEVICE_DAC_INFO_DACB 0x00000002 | ||
| 1950 | #define ATOM_DEVICE_DAC_INFO_EXDAC 0x00000003 | ||
| 1951 | |||
| 1952 | #define ATOM_DEVICE_I2C_ID_NOI2C 0x00000000 | ||
| 1953 | |||
| 1954 | #define ATOM_DEVICE_I2C_LINEMUX_MASK 0x0000000F | ||
| 1955 | #define ATOM_DEVICE_I2C_LINEMUX_SHIFT 0x00000000 | ||
| 1956 | |||
| 1957 | #define ATOM_DEVICE_I2C_ID_MASK 0x00000070 | ||
| 1958 | #define ATOM_DEVICE_I2C_ID_SHIFT 0x00000004 | ||
| 1959 | #define ATOM_DEVICE_I2C_ID_IS_FOR_NON_MM_USE 0x00000001 | ||
| 1960 | #define ATOM_DEVICE_I2C_ID_IS_FOR_MM_USE 0x00000002 | ||
| 1961 | #define ATOM_DEVICE_I2C_ID_IS_FOR_SDVO_USE 0x00000003 /* For IGP RS600 */ | ||
| 1962 | #define ATOM_DEVICE_I2C_ID_IS_FOR_DAC_SCL 0x00000004 /* For IGP RS690 */ | ||
| 1963 | |||
| 1964 | #define ATOM_DEVICE_I2C_HARDWARE_CAP_MASK 0x00000080 | ||
| 1965 | #define ATOM_DEVICE_I2C_HARDWARE_CAP_SHIFT 0x00000007 | ||
| 1966 | #define ATOM_DEVICE_USES_SOFTWARE_ASSISTED_I2C 0x00000000 | ||
| 1967 | #define ATOM_DEVICE_USES_HARDWARE_ASSISTED_I2C 0x00000001 | ||
| 1968 | |||
| 1969 | /* usDeviceSupport: */ | ||
| 1970 | /* Bits0 = 0 - no CRT1 support= 1- CRT1 is supported */ | ||
| 1971 | /* Bit 1 = 0 - no LCD1 support= 1- LCD1 is supported */ | ||
| 1972 | /* Bit 2 = 0 - no TV1 support= 1- TV1 is supported */ | ||
| 1973 | /* Bit 3 = 0 - no DFP1 support= 1- DFP1 is supported */ | ||
| 1974 | /* Bit 4 = 0 - no CRT2 support= 1- CRT2 is supported */ | ||
| 1975 | /* Bit 5 = 0 - no LCD2 support= 1- LCD2 is supported */ | ||
| 1976 | /* Bit 6 = 0 - no TV2 support= 1- TV2 is supported */ | ||
| 1977 | /* Bit 7 = 0 - no DFP2 support= 1- DFP2 is supported */ | ||
| 1978 | /* Bit 8 = 0 - no CV support= 1- CV is supported */ | ||
| 1979 | /* Bit 9 = 0 - no DFP3 support= 1- DFP3 is supported */ | ||
| 1980 | /* Byte1 (Supported Device Info) */ | ||
| 1981 | /* Bit 0 = = 0 - no CV support= 1- CV is supported */ | ||
| 1982 | /* */ | ||
| 1983 | /* */ | ||
| 1984 | |||
| 1985 | /* ucI2C_ConfigID */ | ||
| 1986 | /* [7:0] - I2C LINE Associate ID */ | ||
| 1987 | /* = 0 - no I2C */ | ||
| 1988 | /* [7] - HW_Cap = 1, [6:0]=HW assisted I2C ID(HW line selection) */ | ||
| 1989 | /* = 0, [6:0]=SW assisted I2C ID */ | ||
| 1990 | /* [6-4] - HW_ENGINE_ID = 1, HW engine for NON multimedia use */ | ||
| 1991 | /* = 2, HW engine for Multimedia use */ | ||
| 1992 | /* = 3-7 Reserved for future I2C engines */ | ||
| 1993 | /* [3-0] - I2C_LINE_MUX = A Mux number when it's HW assisted I2C or GPIO ID when it's SW I2C */ | ||
| 1994 | |||
| 1995 | typedef struct _ATOM_I2C_ID_CONFIG { | ||
| 1996 | #if ATOM_BIG_ENDIAN | ||
| 1997 | UCHAR bfHW_Capable:1; | ||
| 1998 | UCHAR bfHW_EngineID:3; | ||
| 1999 | UCHAR bfI2C_LineMux:4; | ||
| 2000 | #else | ||
| 2001 | UCHAR bfI2C_LineMux:4; | ||
| 2002 | UCHAR bfHW_EngineID:3; | ||
| 2003 | UCHAR bfHW_Capable:1; | ||
| 2004 | #endif | ||
| 2005 | } ATOM_I2C_ID_CONFIG; | ||
| 2006 | |||
| 2007 | typedef union _ATOM_I2C_ID_CONFIG_ACCESS { | ||
| 2008 | ATOM_I2C_ID_CONFIG sbfAccess; | ||
| 2009 | UCHAR ucAccess; | ||
| 2010 | } ATOM_I2C_ID_CONFIG_ACCESS; | ||
| 2011 | |||
| 2012 | /****************************************************************************/ | ||
| 2013 | /* Structure used in GPIO_I2C_InfoTable */ | ||
| 2014 | /****************************************************************************/ | ||
| 2015 | typedef struct _ATOM_GPIO_I2C_ASSIGMENT { | ||
| 2016 | USHORT usClkMaskRegisterIndex; | ||
| 2017 | USHORT usClkEnRegisterIndex; | ||
| 2018 | USHORT usClkY_RegisterIndex; | ||
| 2019 | USHORT usClkA_RegisterIndex; | ||
| 2020 | USHORT usDataMaskRegisterIndex; | ||
| 2021 | USHORT usDataEnRegisterIndex; | ||
| 2022 | USHORT usDataY_RegisterIndex; | ||
| 2023 | USHORT usDataA_RegisterIndex; | ||
| 2024 | ATOM_I2C_ID_CONFIG_ACCESS sucI2cId; | ||
| 2025 | UCHAR ucClkMaskShift; | ||
| 2026 | UCHAR ucClkEnShift; | ||
| 2027 | UCHAR ucClkY_Shift; | ||
| 2028 | UCHAR ucClkA_Shift; | ||
| 2029 | UCHAR ucDataMaskShift; | ||
| 2030 | UCHAR ucDataEnShift; | ||
| 2031 | UCHAR ucDataY_Shift; | ||
| 2032 | UCHAR ucDataA_Shift; | ||
| 2033 | UCHAR ucReserved1; | ||
| 2034 | UCHAR ucReserved2; | ||
| 2035 | } ATOM_GPIO_I2C_ASSIGMENT; | ||
| 2036 | |||
| 2037 | typedef struct _ATOM_GPIO_I2C_INFO { | ||
| 2038 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 2039 | ATOM_GPIO_I2C_ASSIGMENT asGPIO_Info[ATOM_MAX_SUPPORTED_DEVICE]; | ||
| 2040 | } ATOM_GPIO_I2C_INFO; | ||
| 2041 | |||
| 2042 | /****************************************************************************/ | ||
| 2043 | /* Common Structure used in other structures */ | ||
| 2044 | /****************************************************************************/ | ||
| 2045 | |||
| 2046 | #ifndef _H2INC | ||
| 2047 | |||
| 2048 | /* Please don't add or expand this bitfield structure below, this one will retire soon.! */ | ||
| 2049 | typedef struct _ATOM_MODE_MISC_INFO { | ||
| 2050 | #if ATOM_BIG_ENDIAN | ||
| 2051 | USHORT Reserved:6; | ||
| 2052 | USHORT RGB888:1; | ||
| 2053 | USHORT DoubleClock:1; | ||
| 2054 | USHORT Interlace:1; | ||
| 2055 | USHORT CompositeSync:1; | ||
| 2056 | USHORT V_ReplicationBy2:1; | ||
| 2057 | USHORT H_ReplicationBy2:1; | ||
| 2058 | USHORT VerticalCutOff:1; | ||
| 2059 | USHORT VSyncPolarity:1; /* 0=Active High, 1=Active Low */ | ||
| 2060 | USHORT HSyncPolarity:1; /* 0=Active High, 1=Active Low */ | ||
| 2061 | USHORT HorizontalCutOff:1; | ||
| 2062 | #else | ||
| 2063 | USHORT HorizontalCutOff:1; | ||
| 2064 | USHORT HSyncPolarity:1; /* 0=Active High, 1=Active Low */ | ||
| 2065 | USHORT VSyncPolarity:1; /* 0=Active High, 1=Active Low */ | ||
| 2066 | USHORT VerticalCutOff:1; | ||
| 2067 | USHORT H_ReplicationBy2:1; | ||
| 2068 | USHORT V_ReplicationBy2:1; | ||
| 2069 | USHORT CompositeSync:1; | ||
| 2070 | USHORT Interlace:1; | ||
| 2071 | USHORT DoubleClock:1; | ||
| 2072 | USHORT RGB888:1; | ||
| 2073 | USHORT Reserved:6; | ||
| 2074 | #endif | ||
| 2075 | } ATOM_MODE_MISC_INFO; | ||
| 2076 | |||
| 2077 | typedef union _ATOM_MODE_MISC_INFO_ACCESS { | ||
| 2078 | ATOM_MODE_MISC_INFO sbfAccess; | ||
| 2079 | USHORT usAccess; | ||
| 2080 | } ATOM_MODE_MISC_INFO_ACCESS; | ||
| 2081 | |||
| 2082 | #else | ||
| 2083 | |||
| 2084 | typedef union _ATOM_MODE_MISC_INFO_ACCESS { | ||
| 2085 | USHORT usAccess; | ||
| 2086 | } ATOM_MODE_MISC_INFO_ACCESS; | ||
| 2087 | |||
| 2088 | #endif | ||
| 2089 | |||
| 2090 | /* usModeMiscInfo- */ | ||
| 2091 | #define ATOM_H_CUTOFF 0x01 | ||
| 2092 | #define ATOM_HSYNC_POLARITY 0x02 /* 0=Active High, 1=Active Low */ | ||
| 2093 | #define ATOM_VSYNC_POLARITY 0x04 /* 0=Active High, 1=Active Low */ | ||
| 2094 | #define ATOM_V_CUTOFF 0x08 | ||
| 2095 | #define ATOM_H_REPLICATIONBY2 0x10 | ||
| 2096 | #define ATOM_V_REPLICATIONBY2 0x20 | ||
| 2097 | #define ATOM_COMPOSITESYNC 0x40 | ||
| 2098 | #define ATOM_INTERLACE 0x80 | ||
| 2099 | #define ATOM_DOUBLE_CLOCK_MODE 0x100 | ||
| 2100 | #define ATOM_RGB888_MODE 0x200 | ||
| 2101 | |||
| 2102 | /* usRefreshRate- */ | ||
| 2103 | #define ATOM_REFRESH_43 43 | ||
| 2104 | #define ATOM_REFRESH_47 47 | ||
| 2105 | #define ATOM_REFRESH_56 56 | ||
| 2106 | #define ATOM_REFRESH_60 60 | ||
| 2107 | #define ATOM_REFRESH_65 65 | ||
| 2108 | #define ATOM_REFRESH_70 70 | ||
| 2109 | #define ATOM_REFRESH_72 72 | ||
| 2110 | #define ATOM_REFRESH_75 75 | ||
| 2111 | #define ATOM_REFRESH_85 85 | ||
| 2112 | |||
| 2113 | /* ATOM_MODE_TIMING data are exactly the same as VESA timing data. */ | ||
| 2114 | /* Translation from EDID to ATOM_MODE_TIMING, use the following formula. */ | ||
| 2115 | /* */ | ||
| 2116 | /* VESA_HTOTAL = VESA_ACTIVE + 2* VESA_BORDER + VESA_BLANK */ | ||
| 2117 | /* = EDID_HA + EDID_HBL */ | ||
| 2118 | /* VESA_HDISP = VESA_ACTIVE = EDID_HA */ | ||
| 2119 | /* VESA_HSYNC_START = VESA_ACTIVE + VESA_BORDER + VESA_FRONT_PORCH */ | ||
| 2120 | /* = EDID_HA + EDID_HSO */ | ||
| 2121 | /* VESA_HSYNC_WIDTH = VESA_HSYNC_TIME = EDID_HSPW */ | ||
| 2122 | /* VESA_BORDER = EDID_BORDER */ | ||
| 2123 | |||
| 2124 | /****************************************************************************/ | ||
| 2125 | /* Structure used in SetCRTC_UsingDTDTimingTable */ | ||
| 2126 | /****************************************************************************/ | ||
| 2127 | typedef struct _SET_CRTC_USING_DTD_TIMING_PARAMETERS { | ||
| 2128 | USHORT usH_Size; | ||
| 2129 | USHORT usH_Blanking_Time; | ||
| 2130 | USHORT usV_Size; | ||
| 2131 | USHORT usV_Blanking_Time; | ||
| 2132 | USHORT usH_SyncOffset; | ||
| 2133 | USHORT usH_SyncWidth; | ||
| 2134 | USHORT usV_SyncOffset; | ||
| 2135 | USHORT usV_SyncWidth; | ||
| 2136 | ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo; | ||
| 2137 | UCHAR ucH_Border; /* From DFP EDID */ | ||
| 2138 | UCHAR ucV_Border; | ||
| 2139 | UCHAR ucCRTC; /* ATOM_CRTC1 or ATOM_CRTC2 */ | ||
| 2140 | UCHAR ucPadding[3]; | ||
| 2141 | } SET_CRTC_USING_DTD_TIMING_PARAMETERS; | ||
| 2142 | |||
| 2143 | /****************************************************************************/ | ||
| 2144 | /* Structure used in SetCRTC_TimingTable */ | ||
| 2145 | /****************************************************************************/ | ||
| 2146 | typedef struct _SET_CRTC_TIMING_PARAMETERS { | ||
| 2147 | USHORT usH_Total; /* horizontal total */ | ||
| 2148 | USHORT usH_Disp; /* horizontal display */ | ||
| 2149 | USHORT usH_SyncStart; /* horozontal Sync start */ | ||
| 2150 | USHORT usH_SyncWidth; /* horizontal Sync width */ | ||
| 2151 | USHORT usV_Total; /* vertical total */ | ||
| 2152 | USHORT usV_Disp; /* vertical display */ | ||
| 2153 | USHORT usV_SyncStart; /* vertical Sync start */ | ||
| 2154 | USHORT usV_SyncWidth; /* vertical Sync width */ | ||
| 2155 | ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo; | ||
| 2156 | UCHAR ucCRTC; /* ATOM_CRTC1 or ATOM_CRTC2 */ | ||
| 2157 | UCHAR ucOverscanRight; /* right */ | ||
| 2158 | UCHAR ucOverscanLeft; /* left */ | ||
| 2159 | UCHAR ucOverscanBottom; /* bottom */ | ||
| 2160 | UCHAR ucOverscanTop; /* top */ | ||
| 2161 | UCHAR ucReserved; | ||
| 2162 | } SET_CRTC_TIMING_PARAMETERS; | ||
| 2163 | #define SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION SET_CRTC_TIMING_PARAMETERS | ||
| 2164 | |||
| 2165 | /****************************************************************************/ | ||
| 2166 | /* Structure used in StandardVESA_TimingTable */ | ||
| 2167 | /* AnalogTV_InfoTable */ | ||
| 2168 | /* ComponentVideoInfoTable */ | ||
| 2169 | /****************************************************************************/ | ||
| 2170 | typedef struct _ATOM_MODE_TIMING { | ||
| 2171 | USHORT usCRTC_H_Total; | ||
| 2172 | USHORT usCRTC_H_Disp; | ||
| 2173 | USHORT usCRTC_H_SyncStart; | ||
| 2174 | USHORT usCRTC_H_SyncWidth; | ||
| 2175 | USHORT usCRTC_V_Total; | ||
| 2176 | USHORT usCRTC_V_Disp; | ||
| 2177 | USHORT usCRTC_V_SyncStart; | ||
| 2178 | USHORT usCRTC_V_SyncWidth; | ||
| 2179 | USHORT usPixelClock; /* in 10Khz unit */ | ||
| 2180 | ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo; | ||
| 2181 | USHORT usCRTC_OverscanRight; | ||
| 2182 | USHORT usCRTC_OverscanLeft; | ||
| 2183 | USHORT usCRTC_OverscanBottom; | ||
| 2184 | USHORT usCRTC_OverscanTop; | ||
| 2185 | USHORT usReserve; | ||
| 2186 | UCHAR ucInternalModeNumber; | ||
| 2187 | UCHAR ucRefreshRate; | ||
| 2188 | } ATOM_MODE_TIMING; | ||
| 2189 | |||
| 2190 | typedef struct _ATOM_DTD_FORMAT { | ||
| 2191 | USHORT usPixClk; | ||
| 2192 | USHORT usHActive; | ||
| 2193 | USHORT usHBlanking_Time; | ||
| 2194 | USHORT usVActive; | ||
| 2195 | USHORT usVBlanking_Time; | ||
| 2196 | USHORT usHSyncOffset; | ||
| 2197 | USHORT usHSyncWidth; | ||
| 2198 | USHORT usVSyncOffset; | ||
| 2199 | USHORT usVSyncWidth; | ||
| 2200 | USHORT usImageHSize; | ||
| 2201 | USHORT usImageVSize; | ||
| 2202 | UCHAR ucHBorder; | ||
| 2203 | UCHAR ucVBorder; | ||
| 2204 | ATOM_MODE_MISC_INFO_ACCESS susModeMiscInfo; | ||
| 2205 | UCHAR ucInternalModeNumber; | ||
| 2206 | UCHAR ucRefreshRate; | ||
| 2207 | } ATOM_DTD_FORMAT; | ||
| 2208 | |||
| 2209 | /****************************************************************************/ | ||
| 2210 | /* Structure used in LVDS_InfoTable */ | ||
| 2211 | /* * Need a document to describe this table */ | ||
| 2212 | /****************************************************************************/ | ||
| 2213 | #define SUPPORTED_LCD_REFRESHRATE_30Hz 0x0004 | ||
| 2214 | #define SUPPORTED_LCD_REFRESHRATE_40Hz 0x0008 | ||
| 2215 | #define SUPPORTED_LCD_REFRESHRATE_50Hz 0x0010 | ||
| 2216 | #define SUPPORTED_LCD_REFRESHRATE_60Hz 0x0020 | ||
| 2217 | |||
| 2218 | /* Once DAL sees this CAP is set, it will read EDID from LCD on its own instead of using sLCDTiming in ATOM_LVDS_INFO_V12. */ | ||
| 2219 | /* Other entries in ATOM_LVDS_INFO_V12 are still valid/useful to DAL */ | ||
| 2220 | #define LCDPANEL_CAP_READ_EDID 0x1 | ||
| 2221 | |||
| 2222 | /* ucTableFormatRevision=1 */ | ||
| 2223 | /* ucTableContentRevision=1 */ | ||
| 2224 | typedef struct _ATOM_LVDS_INFO { | ||
| 2225 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 2226 | ATOM_DTD_FORMAT sLCDTiming; | ||
| 2227 | USHORT usModePatchTableOffset; | ||
| 2228 | USHORT usSupportedRefreshRate; /* Refer to panel info table in ATOMBIOS extension Spec. */ | ||
| 2229 | USHORT usOffDelayInMs; | ||
| 2230 | UCHAR ucPowerSequenceDigOntoDEin10Ms; | ||
| 2231 | UCHAR ucPowerSequenceDEtoBLOnin10Ms; | ||
| 2232 | UCHAR ucLVDS_Misc; /* Bit0:{=0:single, =1:dual},Bit1 {=0:666RGB, =1:888RGB},Bit2:3:{Grey level} */ | ||
| 2233 | /* Bit4:{=0:LDI format for RGB888, =1 FPDI format for RGB888} */ | ||
| 2234 | /* Bit5:{=0:Spatial Dithering disabled;1 Spatial Dithering enabled} */ | ||
| 2235 | /* Bit6:{=0:Temporal Dithering disabled;1 Temporal Dithering enabled} */ | ||
| 2236 | UCHAR ucPanelDefaultRefreshRate; | ||
| 2237 | UCHAR ucPanelIdentification; | ||
| 2238 | UCHAR ucSS_Id; | ||
| 2239 | } ATOM_LVDS_INFO; | ||
| 2240 | |||
| 2241 | /* ucTableFormatRevision=1 */ | ||
| 2242 | /* ucTableContentRevision=2 */ | ||
| 2243 | typedef struct _ATOM_LVDS_INFO_V12 { | ||
| 2244 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 2245 | ATOM_DTD_FORMAT sLCDTiming; | ||
| 2246 | USHORT usExtInfoTableOffset; | ||
| 2247 | USHORT usSupportedRefreshRate; /* Refer to panel info table in ATOMBIOS extension Spec. */ | ||
| 2248 | USHORT usOffDelayInMs; | ||
| 2249 | UCHAR ucPowerSequenceDigOntoDEin10Ms; | ||
| 2250 | UCHAR ucPowerSequenceDEtoBLOnin10Ms; | ||
| 2251 | UCHAR ucLVDS_Misc; /* Bit0:{=0:single, =1:dual},Bit1 {=0:666RGB, =1:888RGB},Bit2:3:{Grey level} */ | ||
| 2252 | /* Bit4:{=0:LDI format for RGB888, =1 FPDI format for RGB888} */ | ||
| 2253 | /* Bit5:{=0:Spatial Dithering disabled;1 Spatial Dithering enabled} */ | ||
| 2254 | /* Bit6:{=0:Temporal Dithering disabled;1 Temporal Dithering enabled} */ | ||
| 2255 | UCHAR ucPanelDefaultRefreshRate; | ||
| 2256 | UCHAR ucPanelIdentification; | ||
| 2257 | UCHAR ucSS_Id; | ||
| 2258 | USHORT usLCDVenderID; | ||
| 2259 | USHORT usLCDProductID; | ||
| 2260 | UCHAR ucLCDPanel_SpecialHandlingCap; | ||
| 2261 | UCHAR ucPanelInfoSize; /* start from ATOM_DTD_FORMAT to end of panel info, include ExtInfoTable */ | ||
| 2262 | UCHAR ucReserved[2]; | ||
| 2263 | } ATOM_LVDS_INFO_V12; | ||
| 2264 | |||
| 2265 | #define ATOM_LVDS_INFO_LAST ATOM_LVDS_INFO_V12 | ||
| 2266 | |||
| 2267 | typedef struct _ATOM_PATCH_RECORD_MODE { | ||
| 2268 | UCHAR ucRecordType; | ||
| 2269 | USHORT usHDisp; | ||
| 2270 | USHORT usVDisp; | ||
| 2271 | } ATOM_PATCH_RECORD_MODE; | ||
| 2272 | |||
| 2273 | typedef struct _ATOM_LCD_RTS_RECORD { | ||
| 2274 | UCHAR ucRecordType; | ||
| 2275 | UCHAR ucRTSValue; | ||
| 2276 | } ATOM_LCD_RTS_RECORD; | ||
| 2277 | |||
| 2278 | /* !! If the record below exits, it shoud always be the first record for easy use in command table!!! */ | ||
| 2279 | typedef struct _ATOM_LCD_MODE_CONTROL_CAP { | ||
| 2280 | UCHAR ucRecordType; | ||
| 2281 | USHORT usLCDCap; | ||
| 2282 | } ATOM_LCD_MODE_CONTROL_CAP; | ||
| 2283 | |||
| 2284 | #define LCD_MODE_CAP_BL_OFF 1 | ||
| 2285 | #define LCD_MODE_CAP_CRTC_OFF 2 | ||
| 2286 | #define LCD_MODE_CAP_PANEL_OFF 4 | ||
| 2287 | |||
| 2288 | typedef struct _ATOM_FAKE_EDID_PATCH_RECORD { | ||
| 2289 | UCHAR ucRecordType; | ||
| 2290 | UCHAR ucFakeEDIDLength; | ||
| 2291 | UCHAR ucFakeEDIDString[1]; /* This actually has ucFakeEdidLength elements. */ | ||
| 2292 | } ATOM_FAKE_EDID_PATCH_RECORD; | ||
| 2293 | |||
| 2294 | typedef struct _ATOM_PANEL_RESOLUTION_PATCH_RECORD { | ||
| 2295 | UCHAR ucRecordType; | ||
| 2296 | USHORT usHSize; | ||
| 2297 | USHORT usVSize; | ||
| 2298 | } ATOM_PANEL_RESOLUTION_PATCH_RECORD; | ||
| 2299 | |||
| 2300 | #define LCD_MODE_PATCH_RECORD_MODE_TYPE 1 | ||
| 2301 | #define LCD_RTS_RECORD_TYPE 2 | ||
| 2302 | #define LCD_CAP_RECORD_TYPE 3 | ||
| 2303 | #define LCD_FAKE_EDID_PATCH_RECORD_TYPE 4 | ||
| 2304 | #define LCD_PANEL_RESOLUTION_RECORD_TYPE 5 | ||
| 2305 | #define ATOM_RECORD_END_TYPE 0xFF | ||
| 2306 | |||
| 2307 | /****************************Spread Spectrum Info Table Definitions **********************/ | ||
| 2308 | |||
| 2309 | /* ucTableFormatRevision=1 */ | ||
| 2310 | /* ucTableContentRevision=2 */ | ||
| 2311 | typedef struct _ATOM_SPREAD_SPECTRUM_ASSIGNMENT { | ||
| 2312 | USHORT usSpreadSpectrumPercentage; | ||
| 2313 | UCHAR ucSpreadSpectrumType; /* Bit1=0 Down Spread,=1 Center Spread. Bit1=1 Ext. =0 Int. Others:TBD */ | ||
| 2314 | UCHAR ucSS_Step; | ||
| 2315 | UCHAR ucSS_Delay; | ||
| 2316 | UCHAR ucSS_Id; | ||
| 2317 | UCHAR ucRecommandedRef_Div; | ||
| 2318 | UCHAR ucSS_Range; /* it was reserved for V11 */ | ||
| 2319 | } ATOM_SPREAD_SPECTRUM_ASSIGNMENT; | ||
| 2320 | |||
| 2321 | #define ATOM_MAX_SS_ENTRY 16 | ||
| 2322 | #define ATOM_DP_SS_ID1 0x0f1 /* SS modulation freq=30k */ | ||
| 2323 | #define ATOM_DP_SS_ID2 0x0f2 /* SS modulation freq=33k */ | ||
| 2324 | |||
| 2325 | #define ATOM_SS_DOWN_SPREAD_MODE_MASK 0x00000000 | ||
| 2326 | #define ATOM_SS_DOWN_SPREAD_MODE 0x00000000 | ||
| 2327 | #define ATOM_SS_CENTRE_SPREAD_MODE_MASK 0x00000001 | ||
| 2328 | #define ATOM_SS_CENTRE_SPREAD_MODE 0x00000001 | ||
| 2329 | #define ATOM_INTERNAL_SS_MASK 0x00000000 | ||
| 2330 | #define ATOM_EXTERNAL_SS_MASK 0x00000002 | ||
| 2331 | #define EXEC_SS_STEP_SIZE_SHIFT 2 | ||
| 2332 | #define EXEC_SS_DELAY_SHIFT 4 | ||
| 2333 | #define ACTIVEDATA_TO_BLON_DELAY_SHIFT 4 | ||
| 2334 | |||
| 2335 | typedef struct _ATOM_SPREAD_SPECTRUM_INFO { | ||
| 2336 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 2337 | ATOM_SPREAD_SPECTRUM_ASSIGNMENT asSS_Info[ATOM_MAX_SS_ENTRY]; | ||
| 2338 | } ATOM_SPREAD_SPECTRUM_INFO; | ||
| 2339 | |||
| 2340 | /****************************************************************************/ | ||
| 2341 | /* Structure used in AnalogTV_InfoTable (Top level) */ | ||
| 2342 | /****************************************************************************/ | ||
| 2343 | /* ucTVBootUpDefaultStd definiton: */ | ||
| 2344 | |||
| 2345 | /* ATOM_TV_NTSC 1 */ | ||
| 2346 | /* ATOM_TV_NTSCJ 2 */ | ||
| 2347 | /* ATOM_TV_PAL 3 */ | ||
| 2348 | /* ATOM_TV_PALM 4 */ | ||
| 2349 | /* ATOM_TV_PALCN 5 */ | ||
| 2350 | /* ATOM_TV_PALN 6 */ | ||
| 2351 | /* ATOM_TV_PAL60 7 */ | ||
| 2352 | /* ATOM_TV_SECAM 8 */ | ||
| 2353 | |||
| 2354 | /* ucTVSuppportedStd definition: */ | ||
| 2355 | #define NTSC_SUPPORT 0x1 | ||
| 2356 | #define NTSCJ_SUPPORT 0x2 | ||
| 2357 | |||
| 2358 | #define PAL_SUPPORT 0x4 | ||
| 2359 | #define PALM_SUPPORT 0x8 | ||
| 2360 | #define PALCN_SUPPORT 0x10 | ||
| 2361 | #define PALN_SUPPORT 0x20 | ||
| 2362 | #define PAL60_SUPPORT 0x40 | ||
| 2363 | #define SECAM_SUPPORT 0x80 | ||
| 2364 | |||
| 2365 | #define MAX_SUPPORTED_TV_TIMING 2 | ||
| 2366 | |||
| 2367 | typedef struct _ATOM_ANALOG_TV_INFO { | ||
| 2368 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 2369 | UCHAR ucTV_SupportedStandard; | ||
| 2370 | UCHAR ucTV_BootUpDefaultStandard; | ||
| 2371 | UCHAR ucExt_TV_ASIC_ID; | ||
| 2372 | UCHAR ucExt_TV_ASIC_SlaveAddr; | ||
| 2373 | /*ATOM_DTD_FORMAT aModeTimings[MAX_SUPPORTED_TV_TIMING]; */ | ||
| 2374 | ATOM_MODE_TIMING aModeTimings[MAX_SUPPORTED_TV_TIMING]; | ||
| 2375 | } ATOM_ANALOG_TV_INFO; | ||
| 2376 | |||
| 2377 | /**************************************************************************/ | ||
| 2378 | /* VRAM usage and their defintions */ | ||
| 2379 | |||
| 2380 | /* One chunk of VRAM used by Bios are for HWICON surfaces,EDID data. */ | ||
| 2381 | /* Current Mode timing and Dail Timing and/or STD timing data EACH device. They can be broken down as below. */ | ||
| 2382 | /* All the addresses below are the offsets from the frame buffer start.They all MUST be Dword aligned! */ | ||
| 2383 | /* To driver: The physical address of this memory portion=mmFB_START(4K aligned)+ATOMBIOS_VRAM_USAGE_START_ADDR+ATOM_x_ADDR */ | ||
| 2384 | /* To Bios: ATOMBIOS_VRAM_USAGE_START_ADDR+ATOM_x_ADDR->MM_INDEX */ | ||
| 2385 | |||
| 2386 | #ifndef VESA_MEMORY_IN_64K_BLOCK | ||
| 2387 | #define VESA_MEMORY_IN_64K_BLOCK 0x100 /* 256*64K=16Mb (Max. VESA memory is 16Mb!) */ | ||
| 2388 | #endif | ||
| 2389 | |||
| 2390 | #define ATOM_EDID_RAW_DATASIZE 256 /* In Bytes */ | ||
| 2391 | #define ATOM_HWICON_SURFACE_SIZE 4096 /* In Bytes */ | ||
| 2392 | #define ATOM_HWICON_INFOTABLE_SIZE 32 | ||
| 2393 | #define MAX_DTD_MODE_IN_VRAM 6 | ||
| 2394 | #define ATOM_DTD_MODE_SUPPORT_TBL_SIZE (MAX_DTD_MODE_IN_VRAM*28) /* 28= (SIZEOF ATOM_DTD_FORMAT) */ | ||
| 2395 | #define ATOM_STD_MODE_SUPPORT_TBL_SIZE (32*8) /* 32 is a predefined number,8= (SIZEOF ATOM_STD_FORMAT) */ | ||
| 2396 | #define DFP_ENCODER_TYPE_OFFSET 0x80 | ||
| 2397 | #define DP_ENCODER_LANE_NUM_OFFSET 0x84 | ||
| 2398 | #define DP_ENCODER_LINK_RATE_OFFSET 0x88 | ||
| 2399 | |||
| 2400 | #define ATOM_HWICON1_SURFACE_ADDR 0 | ||
| 2401 | #define ATOM_HWICON2_SURFACE_ADDR (ATOM_HWICON1_SURFACE_ADDR + ATOM_HWICON_SURFACE_SIZE) | ||
| 2402 | #define ATOM_HWICON_INFOTABLE_ADDR (ATOM_HWICON2_SURFACE_ADDR + ATOM_HWICON_SURFACE_SIZE) | ||
| 2403 | #define ATOM_CRT1_EDID_ADDR (ATOM_HWICON_INFOTABLE_ADDR + ATOM_HWICON_INFOTABLE_SIZE) | ||
| 2404 | #define ATOM_CRT1_DTD_MODE_TBL_ADDR (ATOM_CRT1_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) | ||
| 2405 | #define ATOM_CRT1_STD_MODE_TBL_ADDR (ATOM_CRT1_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) | ||
| 2406 | |||
| 2407 | #define ATOM_LCD1_EDID_ADDR (ATOM_CRT1_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) | ||
| 2408 | #define ATOM_LCD1_DTD_MODE_TBL_ADDR (ATOM_LCD1_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) | ||
| 2409 | #define ATOM_LCD1_STD_MODE_TBL_ADDR (ATOM_LCD1_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) | ||
| 2410 | |||
| 2411 | #define ATOM_TV1_DTD_MODE_TBL_ADDR (ATOM_LCD1_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) | ||
| 2412 | |||
| 2413 | #define ATOM_DFP1_EDID_ADDR (ATOM_TV1_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) | ||
| 2414 | #define ATOM_DFP1_DTD_MODE_TBL_ADDR (ATOM_DFP1_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) | ||
| 2415 | #define ATOM_DFP1_STD_MODE_TBL_ADDR (ATOM_DFP1_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) | ||
| 2416 | |||
| 2417 | #define ATOM_CRT2_EDID_ADDR (ATOM_DFP1_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) | ||
| 2418 | #define ATOM_CRT2_DTD_MODE_TBL_ADDR (ATOM_CRT2_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) | ||
| 2419 | #define ATOM_CRT2_STD_MODE_TBL_ADDR (ATOM_CRT2_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) | ||
| 2420 | |||
| 2421 | #define ATOM_LCD2_EDID_ADDR (ATOM_CRT2_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) | ||
| 2422 | #define ATOM_LCD2_DTD_MODE_TBL_ADDR (ATOM_LCD2_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) | ||
| 2423 | #define ATOM_LCD2_STD_MODE_TBL_ADDR (ATOM_LCD2_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) | ||
| 2424 | |||
| 2425 | #define ATOM_TV2_EDID_ADDR (ATOM_LCD2_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) | ||
| 2426 | #define ATOM_TV2_DTD_MODE_TBL_ADDR (ATOM_TV2_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) | ||
| 2427 | #define ATOM_TV2_STD_MODE_TBL_ADDR (ATOM_TV2_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) | ||
| 2428 | |||
| 2429 | #define ATOM_DFP2_EDID_ADDR (ATOM_TV2_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) | ||
| 2430 | #define ATOM_DFP2_DTD_MODE_TBL_ADDR (ATOM_DFP2_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) | ||
| 2431 | #define ATOM_DFP2_STD_MODE_TBL_ADDR (ATOM_DFP2_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) | ||
| 2432 | |||
| 2433 | #define ATOM_CV_EDID_ADDR (ATOM_DFP2_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) | ||
| 2434 | #define ATOM_CV_DTD_MODE_TBL_ADDR (ATOM_CV_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) | ||
| 2435 | #define ATOM_CV_STD_MODE_TBL_ADDR (ATOM_CV_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) | ||
| 2436 | |||
| 2437 | #define ATOM_DFP3_EDID_ADDR (ATOM_CV_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) | ||
| 2438 | #define ATOM_DFP3_DTD_MODE_TBL_ADDR (ATOM_DFP3_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) | ||
| 2439 | #define ATOM_DFP3_STD_MODE_TBL_ADDR (ATOM_DFP3_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) | ||
| 2440 | |||
| 2441 | #define ATOM_DFP4_EDID_ADDR (ATOM_DFP3_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) | ||
| 2442 | #define ATOM_DFP4_DTD_MODE_TBL_ADDR (ATOM_DFP4_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) | ||
| 2443 | #define ATOM_DFP4_STD_MODE_TBL_ADDR (ATOM_DFP4_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) | ||
| 2444 | |||
| 2445 | #define ATOM_DFP5_EDID_ADDR (ATOM_DFP4_STD_MODE_TBL_ADDR + ATOM_STD_MODE_SUPPORT_TBL_SIZE) | ||
| 2446 | #define ATOM_DFP5_DTD_MODE_TBL_ADDR (ATOM_DFP5_EDID_ADDR + ATOM_EDID_RAW_DATASIZE) | ||
| 2447 | #define ATOM_DFP5_STD_MODE_TBL_ADDR (ATOM_DFP5_DTD_MODE_TBL_ADDR + ATOM_DTD_MODE_SUPPORT_TBL_SIZE) | ||
| 2448 | |||
| 2449 | #define ATOM_DP_TRAINING_TBL_ADDR (ATOM_DFP5_STD_MODE_TBL_ADDR+ATOM_STD_MODE_SUPPORT_TBL_SIZE) | ||
| 2450 | |||
| 2451 | #define ATOM_STACK_STORAGE_START (ATOM_DP_TRAINING_TBL_ADDR + 256) | ||
| 2452 | #define ATOM_STACK_STORAGE_END (ATOM_STACK_STORAGE_START + 512) | ||
| 2453 | |||
| 2454 | /* The size below is in Kb! */ | ||
| 2455 | #define ATOM_VRAM_RESERVE_SIZE ((((ATOM_STACK_STORAGE_END - ATOM_HWICON1_SURFACE_ADDR)>>10)+4)&0xFFFC) | ||
| 2456 | |||
| 2457 | #define ATOM_VRAM_OPERATION_FLAGS_MASK 0xC0000000L | ||
| 2458 | #define ATOM_VRAM_OPERATION_FLAGS_SHIFT 30 | ||
| 2459 | #define ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION 0x1 | ||
| 2460 | #define ATOM_VRAM_BLOCK_NEEDS_RESERVATION 0x0 | ||
| 2461 | |||
| 2462 | /***********************************************************************************/ | ||
| 2463 | /* Structure used in VRAM_UsageByFirmwareTable */ | ||
| 2464 | /* Note1: This table is filled by SetBiosReservationStartInFB in CoreCommSubs.asm */ | ||
| 2465 | /* at running time. */ | ||
| 2466 | /* note2: From RV770, the memory is more than 32bit addressable, so we will change */ | ||
| 2467 | /* ucTableFormatRevision=1,ucTableContentRevision=4, the strcuture remains */ | ||
| 2468 | /* exactly same as 1.1 and 1.2 (1.3 is never in use), but ulStartAddrUsedByFirmware */ | ||
| 2469 | /* (in offset to start of memory address) is KB aligned instead of byte aligend. */ | ||
| 2470 | /***********************************************************************************/ | ||
| 2471 | #define ATOM_MAX_FIRMWARE_VRAM_USAGE_INFO 1 | ||
| 2472 | |||
| 2473 | typedef struct _ATOM_FIRMWARE_VRAM_RESERVE_INFO { | ||
| 2474 | ULONG ulStartAddrUsedByFirmware; | ||
| 2475 | USHORT usFirmwareUseInKb; | ||
| 2476 | USHORT usReserved; | ||
| 2477 | } ATOM_FIRMWARE_VRAM_RESERVE_INFO; | ||
| 2478 | |||
| 2479 | typedef struct _ATOM_VRAM_USAGE_BY_FIRMWARE { | ||
| 2480 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 2481 | ATOM_FIRMWARE_VRAM_RESERVE_INFO | ||
| 2482 | asFirmwareVramReserveInfo[ATOM_MAX_FIRMWARE_VRAM_USAGE_INFO]; | ||
| 2483 | } ATOM_VRAM_USAGE_BY_FIRMWARE; | ||
| 2484 | |||
| 2485 | /****************************************************************************/ | ||
| 2486 | /* Structure used in GPIO_Pin_LUTTable */ | ||
| 2487 | /****************************************************************************/ | ||
| 2488 | typedef struct _ATOM_GPIO_PIN_ASSIGNMENT { | ||
| 2489 | USHORT usGpioPin_AIndex; | ||
| 2490 | UCHAR ucGpioPinBitShift; | ||
| 2491 | UCHAR ucGPIO_ID; | ||
| 2492 | } ATOM_GPIO_PIN_ASSIGNMENT; | ||
| 2493 | |||
| 2494 | typedef struct _ATOM_GPIO_PIN_LUT { | ||
| 2495 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 2496 | ATOM_GPIO_PIN_ASSIGNMENT asGPIO_Pin[1]; | ||
| 2497 | } ATOM_GPIO_PIN_LUT; | ||
| 2498 | |||
| 2499 | /****************************************************************************/ | ||
| 2500 | /* Structure used in ComponentVideoInfoTable */ | ||
| 2501 | /****************************************************************************/ | ||
| 2502 | #define GPIO_PIN_ACTIVE_HIGH 0x1 | ||
| 2503 | |||
| 2504 | #define MAX_SUPPORTED_CV_STANDARDS 5 | ||
| 2505 | |||
| 2506 | /* definitions for ATOM_D_INFO.ucSettings */ | ||
| 2507 | #define ATOM_GPIO_SETTINGS_BITSHIFT_MASK 0x1F /* [4:0] */ | ||
| 2508 | #define ATOM_GPIO_SETTINGS_RESERVED_MASK 0x60 /* [6:5] = must be zeroed out */ | ||
| 2509 | #define ATOM_GPIO_SETTINGS_ACTIVE_MASK 0x80 /* [7] */ | ||
| 2510 | |||
| 2511 | typedef struct _ATOM_GPIO_INFO { | ||
| 2512 | USHORT usAOffset; | ||
| 2513 | UCHAR ucSettings; | ||
| 2514 | UCHAR ucReserved; | ||
| 2515 | } ATOM_GPIO_INFO; | ||
| 2516 | |||
| 2517 | /* definitions for ATOM_COMPONENT_VIDEO_INFO.ucMiscInfo (bit vector) */ | ||
| 2518 | #define ATOM_CV_RESTRICT_FORMAT_SELECTION 0x2 | ||
| 2519 | |||
| 2520 | /* definitions for ATOM_COMPONENT_VIDEO_INFO.uc480i/uc480p/uc720p/uc1080i */ | ||
| 2521 | #define ATOM_GPIO_DEFAULT_MODE_EN 0x80 /* [7]; */ | ||
| 2522 | #define ATOM_GPIO_SETTING_PERMODE_MASK 0x7F /* [6:0] */ | ||
| 2523 | |||
| 2524 | /* definitions for ATOM_COMPONENT_VIDEO_INFO.ucLetterBoxMode */ | ||
| 2525 | /* Line 3 out put 5V. */ | ||
| 2526 | #define ATOM_CV_LINE3_ASPECTRATIO_16_9_GPIO_A 0x01 /* represent gpio 3 state for 16:9 */ | ||
| 2527 | #define ATOM_CV_LINE3_ASPECTRATIO_16_9_GPIO_B 0x02 /* represent gpio 4 state for 16:9 */ | ||
| 2528 | #define ATOM_CV_LINE3_ASPECTRATIO_16_9_GPIO_SHIFT 0x0 | ||
| 2529 | |||
| 2530 | /* Line 3 out put 2.2V */ | ||
| 2531 | #define ATOM_CV_LINE3_ASPECTRATIO_4_3_LETBOX_GPIO_A 0x04 /* represent gpio 3 state for 4:3 Letter box */ | ||
| 2532 | #define ATOM_CV_LINE3_ASPECTRATIO_4_3_LETBOX_GPIO_B 0x08 /* represent gpio 4 state for 4:3 Letter box */ | ||
| 2533 | #define ATOM_CV_LINE3_ASPECTRATIO_4_3_LETBOX_GPIO_SHIFT 0x2 | ||
| 2534 | |||
| 2535 | /* Line 3 out put 0V */ | ||
| 2536 | #define ATOM_CV_LINE3_ASPECTRATIO_4_3_GPIO_A 0x10 /* represent gpio 3 state for 4:3 */ | ||
| 2537 | #define ATOM_CV_LINE3_ASPECTRATIO_4_3_GPIO_B 0x20 /* represent gpio 4 state for 4:3 */ | ||
| 2538 | #define ATOM_CV_LINE3_ASPECTRATIO_4_3_GPIO_SHIFT 0x4 | ||
| 2539 | |||
| 2540 | #define ATOM_CV_LINE3_ASPECTRATIO_MASK 0x3F /* bit [5:0] */ | ||
| 2541 | |||
| 2542 | #define ATOM_CV_LINE3_ASPECTRATIO_EXIST 0x80 /* bit 7 */ | ||
| 2543 | |||
| 2544 | /* GPIO bit index in gpio setting per mode value, also represend the block no. in gpio blocks. */ | ||
| 2545 | #define ATOM_GPIO_INDEX_LINE3_ASPECRATIO_GPIO_A 3 /* bit 3 in uc480i/uc480p/uc720p/uc1080i, which represend the default gpio bit setting for the mode. */ | ||
| 2546 | #define ATOM_GPIO_INDEX_LINE3_ASPECRATIO_GPIO_B 4 /* bit 4 in uc480i/uc480p/uc720p/uc1080i, which represend the default gpio bit setting for the mode. */ | ||
| 2547 | |||
| 2548 | typedef struct _ATOM_COMPONENT_VIDEO_INFO { | ||
| 2549 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 2550 | USHORT usMask_PinRegisterIndex; | ||
| 2551 | USHORT usEN_PinRegisterIndex; | ||
| 2552 | USHORT usY_PinRegisterIndex; | ||
| 2553 | USHORT usA_PinRegisterIndex; | ||
| 2554 | UCHAR ucBitShift; | ||
| 2555 | UCHAR ucPinActiveState; /* ucPinActiveState: Bit0=1 active high, =0 active low */ | ||
| 2556 | ATOM_DTD_FORMAT sReserved; /* must be zeroed out */ | ||
| 2557 | UCHAR ucMiscInfo; | ||
| 2558 | UCHAR uc480i; | ||
| 2559 | UCHAR uc480p; | ||
| 2560 | UCHAR uc720p; | ||
| 2561 | UCHAR uc1080i; | ||
| 2562 | UCHAR ucLetterBoxMode; | ||
| 2563 | UCHAR ucReserved[3]; | ||
| 2564 | UCHAR ucNumOfWbGpioBlocks; /* For Component video D-Connector support. If zere, NTSC type connector */ | ||
| 2565 | ATOM_GPIO_INFO aWbGpioStateBlock[MAX_SUPPORTED_CV_STANDARDS]; | ||
| 2566 | ATOM_DTD_FORMAT aModeTimings[MAX_SUPPORTED_CV_STANDARDS]; | ||
| 2567 | } ATOM_COMPONENT_VIDEO_INFO; | ||
| 2568 | |||
| 2569 | /* ucTableFormatRevision=2 */ | ||
| 2570 | /* ucTableContentRevision=1 */ | ||
| 2571 | typedef struct _ATOM_COMPONENT_VIDEO_INFO_V21 { | ||
| 2572 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 2573 | UCHAR ucMiscInfo; | ||
| 2574 | UCHAR uc480i; | ||
| 2575 | UCHAR uc480p; | ||
| 2576 | UCHAR uc720p; | ||
| 2577 | UCHAR uc1080i; | ||
| 2578 | UCHAR ucReserved; | ||
| 2579 | UCHAR ucLetterBoxMode; | ||
| 2580 | UCHAR ucNumOfWbGpioBlocks; /* For Component video D-Connector support. If zere, NTSC type connector */ | ||
| 2581 | ATOM_GPIO_INFO aWbGpioStateBlock[MAX_SUPPORTED_CV_STANDARDS]; | ||
| 2582 | ATOM_DTD_FORMAT aModeTimings[MAX_SUPPORTED_CV_STANDARDS]; | ||
| 2583 | } ATOM_COMPONENT_VIDEO_INFO_V21; | ||
| 2584 | |||
| 2585 | #define ATOM_COMPONENT_VIDEO_INFO_LAST ATOM_COMPONENT_VIDEO_INFO_V21 | ||
| 2586 | |||
| 2587 | /****************************************************************************/ | ||
| 2588 | /* Structure used in object_InfoTable */ | ||
| 2589 | /****************************************************************************/ | ||
| 2590 | typedef struct _ATOM_OBJECT_HEADER { | ||
| 2591 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 2592 | USHORT usDeviceSupport; | ||
| 2593 | USHORT usConnectorObjectTableOffset; | ||
| 2594 | USHORT usRouterObjectTableOffset; | ||
| 2595 | USHORT usEncoderObjectTableOffset; | ||
| 2596 | USHORT usProtectionObjectTableOffset; /* only available when Protection block is independent. */ | ||
| 2597 | USHORT usDisplayPathTableOffset; | ||
| 2598 | } ATOM_OBJECT_HEADER; | ||
| 2599 | |||
| 2600 | typedef struct _ATOM_DISPLAY_OBJECT_PATH { | ||
| 2601 | USHORT usDeviceTag; /* supported device */ | ||
| 2602 | USHORT usSize; /* the size of ATOM_DISPLAY_OBJECT_PATH */ | ||
| 2603 | USHORT usConnObjectId; /* Connector Object ID */ | ||
| 2604 | USHORT usGPUObjectId; /* GPU ID */ | ||
| 2605 | USHORT usGraphicObjIds[1]; /* 1st Encoder Obj source from GPU to last Graphic Obj destinate to connector. */ | ||
| 2606 | } ATOM_DISPLAY_OBJECT_PATH; | ||
| 2607 | |||
| 2608 | typedef struct _ATOM_DISPLAY_OBJECT_PATH_TABLE { | ||
| 2609 | UCHAR ucNumOfDispPath; | ||
| 2610 | UCHAR ucVersion; | ||
| 2611 | UCHAR ucPadding[2]; | ||
| 2612 | ATOM_DISPLAY_OBJECT_PATH asDispPath[1]; | ||
| 2613 | } ATOM_DISPLAY_OBJECT_PATH_TABLE; | ||
| 2614 | |||
| 2615 | typedef struct _ATOM_OBJECT /* each object has this structure */ | ||
| 2616 | { | ||
| 2617 | USHORT usObjectID; | ||
| 2618 | USHORT usSrcDstTableOffset; | ||
| 2619 | USHORT usRecordOffset; /* this pointing to a bunch of records defined below */ | ||
| 2620 | USHORT usReserved; | ||
| 2621 | } ATOM_OBJECT; | ||
| 2622 | |||
| 2623 | typedef struct _ATOM_OBJECT_TABLE /* Above 4 object table offset pointing to a bunch of objects all have this structure */ | ||
| 2624 | { | ||
| 2625 | UCHAR ucNumberOfObjects; | ||
| 2626 | UCHAR ucPadding[3]; | ||
| 2627 | ATOM_OBJECT asObjects[1]; | ||
| 2628 | } ATOM_OBJECT_TABLE; | ||
| 2629 | |||
| 2630 | typedef struct _ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT /* usSrcDstTableOffset pointing to this structure */ | ||
| 2631 | { | ||
| 2632 | UCHAR ucNumberOfSrc; | ||
| 2633 | USHORT usSrcObjectID[1]; | ||
| 2634 | UCHAR ucNumberOfDst; | ||
| 2635 | USHORT usDstObjectID[1]; | ||
| 2636 | } ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT; | ||
| 2637 | |||
| 2638 | /* Related definitions, all records are differnt but they have a commond header */ | ||
| 2639 | typedef struct _ATOM_COMMON_RECORD_HEADER { | ||
| 2640 | UCHAR ucRecordType; /* An emun to indicate the record type */ | ||
| 2641 | UCHAR ucRecordSize; /* The size of the whole record in byte */ | ||
| 2642 | } ATOM_COMMON_RECORD_HEADER; | ||
| 2643 | |||
| 2644 | #define ATOM_I2C_RECORD_TYPE 1 | ||
| 2645 | #define ATOM_HPD_INT_RECORD_TYPE 2 | ||
| 2646 | #define ATOM_OUTPUT_PROTECTION_RECORD_TYPE 3 | ||
| 2647 | #define ATOM_CONNECTOR_DEVICE_TAG_RECORD_TYPE 4 | ||
| 2648 | #define ATOM_CONNECTOR_DVI_EXT_INPUT_RECORD_TYPE 5 /* Obsolete, switch to use GPIO_CNTL_RECORD_TYPE */ | ||
| 2649 | #define ATOM_ENCODER_FPGA_CONTROL_RECORD_TYPE 6 /* Obsolete, switch to use GPIO_CNTL_RECORD_TYPE */ | ||
| 2650 | #define ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD_TYPE 7 | ||
| 2651 | #define ATOM_JTAG_RECORD_TYPE 8 /* Obsolete, switch to use GPIO_CNTL_RECORD_TYPE */ | ||
| 2652 | #define ATOM_OBJECT_GPIO_CNTL_RECORD_TYPE 9 | ||
| 2653 | #define ATOM_ENCODER_DVO_CF_RECORD_TYPE 10 | ||
| 2654 | #define ATOM_CONNECTOR_CF_RECORD_TYPE 11 | ||
| 2655 | #define ATOM_CONNECTOR_HARDCODE_DTD_RECORD_TYPE 12 | ||
| 2656 | #define ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD_TYPE 13 | ||
| 2657 | #define ATOM_ROUTER_DDC_PATH_SELECT_RECORD_TYPE 14 | ||
| 2658 | #define ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD_TYPE 15 | ||
| 2659 | |||
| 2660 | /* Must be updated when new record type is added,equal to that record definition! */ | ||
| 2661 | #define ATOM_MAX_OBJECT_RECORD_NUMBER ATOM_CONNECTOR_CF_RECORD_TYPE | ||
| 2662 | |||
| 2663 | typedef struct _ATOM_I2C_RECORD { | ||
| 2664 | ATOM_COMMON_RECORD_HEADER sheader; | ||
| 2665 | ATOM_I2C_ID_CONFIG sucI2cId; | ||
| 2666 | UCHAR ucI2CAddr; /* The slave address, it's 0 when the record is attached to connector for DDC */ | ||
| 2667 | } ATOM_I2C_RECORD; | ||
| 2668 | |||
| 2669 | typedef struct _ATOM_HPD_INT_RECORD { | ||
| 2670 | ATOM_COMMON_RECORD_HEADER sheader; | ||
| 2671 | UCHAR ucHPDIntGPIOID; /* Corresponding block in GPIO_PIN_INFO table gives the pin info */ | ||
| 2672 | UCHAR ucPluggged_PinState; | ||
| 2673 | } ATOM_HPD_INT_RECORD; | ||
| 2674 | |||
| 2675 | typedef struct _ATOM_OUTPUT_PROTECTION_RECORD { | ||
| 2676 | ATOM_COMMON_RECORD_HEADER sheader; | ||
| 2677 | UCHAR ucProtectionFlag; | ||
| 2678 | UCHAR ucReserved; | ||
| 2679 | } ATOM_OUTPUT_PROTECTION_RECORD; | ||
| 2680 | |||
| 2681 | typedef struct _ATOM_CONNECTOR_DEVICE_TAG { | ||
| 2682 | ULONG ulACPIDeviceEnum; /* Reserved for now */ | ||
| 2683 | USHORT usDeviceID; /* This Id is same as "ATOM_DEVICE_XXX_SUPPORT" */ | ||
| 2684 | USHORT usPadding; | ||
| 2685 | } ATOM_CONNECTOR_DEVICE_TAG; | ||
| 2686 | |||
| 2687 | typedef struct _ATOM_CONNECTOR_DEVICE_TAG_RECORD { | ||
| 2688 | ATOM_COMMON_RECORD_HEADER sheader; | ||
| 2689 | UCHAR ucNumberOfDevice; | ||
| 2690 | UCHAR ucReserved; | ||
| 2691 | ATOM_CONNECTOR_DEVICE_TAG asDeviceTag[1]; /* This Id is same as "ATOM_DEVICE_XXX_SUPPORT", 1 is only for allocation */ | ||
| 2692 | } ATOM_CONNECTOR_DEVICE_TAG_RECORD; | ||
| 2693 | |||
| 2694 | typedef struct _ATOM_CONNECTOR_DVI_EXT_INPUT_RECORD { | ||
| 2695 | ATOM_COMMON_RECORD_HEADER sheader; | ||
| 2696 | UCHAR ucConfigGPIOID; | ||
| 2697 | UCHAR ucConfigGPIOState; /* Set to 1 when it's active high to enable external flow in */ | ||
| 2698 | UCHAR ucFlowinGPIPID; | ||
| 2699 | UCHAR ucExtInGPIPID; | ||
| 2700 | } ATOM_CONNECTOR_DVI_EXT_INPUT_RECORD; | ||
| 2701 | |||
| 2702 | typedef struct _ATOM_ENCODER_FPGA_CONTROL_RECORD { | ||
| 2703 | ATOM_COMMON_RECORD_HEADER sheader; | ||
| 2704 | UCHAR ucCTL1GPIO_ID; | ||
| 2705 | UCHAR ucCTL1GPIOState; /* Set to 1 when it's active high */ | ||
| 2706 | UCHAR ucCTL2GPIO_ID; | ||
| 2707 | UCHAR ucCTL2GPIOState; /* Set to 1 when it's active high */ | ||
| 2708 | UCHAR ucCTL3GPIO_ID; | ||
| 2709 | UCHAR ucCTL3GPIOState; /* Set to 1 when it's active high */ | ||
| 2710 | UCHAR ucCTLFPGA_IN_ID; | ||
| 2711 | UCHAR ucPadding[3]; | ||
| 2712 | } ATOM_ENCODER_FPGA_CONTROL_RECORD; | ||
| 2713 | |||
| 2714 | typedef struct _ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD { | ||
| 2715 | ATOM_COMMON_RECORD_HEADER sheader; | ||
| 2716 | UCHAR ucGPIOID; /* Corresponding block in GPIO_PIN_INFO table gives the pin info */ | ||
| 2717 | UCHAR ucTVActiveState; /* Indicating when the pin==0 or 1 when TV is connected */ | ||
| 2718 | } ATOM_CONNECTOR_CVTV_SHARE_DIN_RECORD; | ||
| 2719 | |||
| 2720 | typedef struct _ATOM_JTAG_RECORD { | ||
| 2721 | ATOM_COMMON_RECORD_HEADER sheader; | ||
| 2722 | UCHAR ucTMSGPIO_ID; | ||
| 2723 | UCHAR ucTMSGPIOState; /* Set to 1 when it's active high */ | ||
| 2724 | UCHAR ucTCKGPIO_ID; | ||
| 2725 | UCHAR ucTCKGPIOState; /* Set to 1 when it's active high */ | ||
| 2726 | UCHAR ucTDOGPIO_ID; | ||
| 2727 | UCHAR ucTDOGPIOState; /* Set to 1 when it's active high */ | ||
| 2728 | UCHAR ucTDIGPIO_ID; | ||
| 2729 | UCHAR ucTDIGPIOState; /* Set to 1 when it's active high */ | ||
| 2730 | UCHAR ucPadding[2]; | ||
| 2731 | } ATOM_JTAG_RECORD; | ||
| 2732 | |||
| 2733 | /* The following generic object gpio pin control record type will replace JTAG_RECORD/FPGA_CONTROL_RECORD/DVI_EXT_INPUT_RECORD above gradually */ | ||
| 2734 | typedef struct _ATOM_GPIO_PIN_CONTROL_PAIR { | ||
| 2735 | UCHAR ucGPIOID; /* GPIO_ID, find the corresponding ID in GPIO_LUT table */ | ||
| 2736 | UCHAR ucGPIO_PinState; /* Pin state showing how to set-up the pin */ | ||
| 2737 | } ATOM_GPIO_PIN_CONTROL_PAIR; | ||
| 2738 | |||
| 2739 | typedef struct _ATOM_OBJECT_GPIO_CNTL_RECORD { | ||
| 2740 | ATOM_COMMON_RECORD_HEADER sheader; | ||
| 2741 | UCHAR ucFlags; /* Future expnadibility */ | ||
| 2742 | UCHAR ucNumberOfPins; /* Number of GPIO pins used to control the object */ | ||
| 2743 | ATOM_GPIO_PIN_CONTROL_PAIR asGpio[1]; /* the real gpio pin pair determined by number of pins ucNumberOfPins */ | ||
| 2744 | } ATOM_OBJECT_GPIO_CNTL_RECORD; | ||
| 2745 | |||
| 2746 | /* Definitions for GPIO pin state */ | ||
| 2747 | #define GPIO_PIN_TYPE_INPUT 0x00 | ||
| 2748 | #define GPIO_PIN_TYPE_OUTPUT 0x10 | ||
| 2749 | #define GPIO_PIN_TYPE_HW_CONTROL 0x20 | ||
| 2750 | |||
| 2751 | /* For GPIO_PIN_TYPE_OUTPUT the following is defined */ | ||
| 2752 | #define GPIO_PIN_OUTPUT_STATE_MASK 0x01 | ||
| 2753 | #define GPIO_PIN_OUTPUT_STATE_SHIFT 0 | ||
| 2754 | #define GPIO_PIN_STATE_ACTIVE_LOW 0x0 | ||
| 2755 | #define GPIO_PIN_STATE_ACTIVE_HIGH 0x1 | ||
| 2756 | |||
| 2757 | typedef struct _ATOM_ENCODER_DVO_CF_RECORD { | ||
| 2758 | ATOM_COMMON_RECORD_HEADER sheader; | ||
| 2759 | ULONG ulStrengthControl; /* DVOA strength control for CF */ | ||
| 2760 | UCHAR ucPadding[2]; | ||
| 2761 | } ATOM_ENCODER_DVO_CF_RECORD; | ||
| 2762 | |||
| 2763 | /* value for ATOM_CONNECTOR_CF_RECORD.ucConnectedDvoBundle */ | ||
| 2764 | #define ATOM_CONNECTOR_CF_RECORD_CONNECTED_UPPER12BITBUNDLEA 1 | ||
| 2765 | #define ATOM_CONNECTOR_CF_RECORD_CONNECTED_LOWER12BITBUNDLEB 2 | ||
| 2766 | |||
| 2767 | typedef struct _ATOM_CONNECTOR_CF_RECORD { | ||
| 2768 | ATOM_COMMON_RECORD_HEADER sheader; | ||
| 2769 | USHORT usMaxPixClk; | ||
| 2770 | UCHAR ucFlowCntlGpioId; | ||
| 2771 | UCHAR ucSwapCntlGpioId; | ||
| 2772 | UCHAR ucConnectedDvoBundle; | ||
| 2773 | UCHAR ucPadding; | ||
| 2774 | } ATOM_CONNECTOR_CF_RECORD; | ||
| 2775 | |||
| 2776 | typedef struct _ATOM_CONNECTOR_HARDCODE_DTD_RECORD { | ||
| 2777 | ATOM_COMMON_RECORD_HEADER sheader; | ||
| 2778 | ATOM_DTD_FORMAT asTiming; | ||
| 2779 | } ATOM_CONNECTOR_HARDCODE_DTD_RECORD; | ||
| 2780 | |||
| 2781 | typedef struct _ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD { | ||
| 2782 | ATOM_COMMON_RECORD_HEADER sheader; /* ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD_TYPE */ | ||
| 2783 | UCHAR ucSubConnectorType; /* CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D|X_ID_DUAL_LINK_DVI_D|HDMI_TYPE_A */ | ||
| 2784 | UCHAR ucReserved; | ||
| 2785 | } ATOM_CONNECTOR_PCIE_SUBCONNECTOR_RECORD; | ||
| 2786 | |||
| 2787 | typedef struct _ATOM_ROUTER_DDC_PATH_SELECT_RECORD { | ||
| 2788 | ATOM_COMMON_RECORD_HEADER sheader; | ||
| 2789 | UCHAR ucMuxType; /* decide the number of ucMuxState, =0, no pin state, =1: single state with complement, >1: multiple state */ | ||
| 2790 | UCHAR ucMuxControlPin; | ||
| 2791 | UCHAR ucMuxState[2]; /* for alligment purpose */ | ||
| 2792 | } ATOM_ROUTER_DDC_PATH_SELECT_RECORD; | ||
| 2793 | |||
| 2794 | typedef struct _ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD { | ||
| 2795 | ATOM_COMMON_RECORD_HEADER sheader; | ||
| 2796 | UCHAR ucMuxType; | ||
| 2797 | UCHAR ucMuxControlPin; | ||
| 2798 | UCHAR ucMuxState[2]; /* for alligment purpose */ | ||
| 2799 | } ATOM_ROUTER_DATA_CLOCK_PATH_SELECT_RECORD; | ||
| 2800 | |||
| 2801 | /* define ucMuxType */ | ||
| 2802 | #define ATOM_ROUTER_MUX_PIN_STATE_MASK 0x0f | ||
| 2803 | #define ATOM_ROUTER_MUX_PIN_SINGLE_STATE_COMPLEMENT 0x01 | ||
| 2804 | |||
| 2805 | /****************************************************************************/ | ||
| 2806 | /* ASIC voltage data table */ | ||
| 2807 | /****************************************************************************/ | ||
| 2808 | typedef struct _ATOM_VOLTAGE_INFO_HEADER { | ||
| 2809 | USHORT usVDDCBaseLevel; /* In number of 50mv unit */ | ||
| 2810 | USHORT usReserved; /* For possible extension table offset */ | ||
| 2811 | UCHAR ucNumOfVoltageEntries; | ||
| 2812 | UCHAR ucBytesPerVoltageEntry; | ||
| 2813 | UCHAR ucVoltageStep; /* Indicating in how many mv increament is one step, 0.5mv unit */ | ||
| 2814 | UCHAR ucDefaultVoltageEntry; | ||
| 2815 | UCHAR ucVoltageControlI2cLine; | ||
| 2816 | UCHAR ucVoltageControlAddress; | ||
| 2817 | UCHAR ucVoltageControlOffset; | ||
| 2818 | } ATOM_VOLTAGE_INFO_HEADER; | ||
| 2819 | |||
| 2820 | typedef struct _ATOM_VOLTAGE_INFO { | ||
| 2821 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 2822 | ATOM_VOLTAGE_INFO_HEADER viHeader; | ||
| 2823 | UCHAR ucVoltageEntries[64]; /* 64 is for allocation, the actual number of entry is present at ucNumOfVoltageEntries*ucBytesPerVoltageEntry */ | ||
| 2824 | } ATOM_VOLTAGE_INFO; | ||
| 2825 | |||
| 2826 | typedef struct _ATOM_VOLTAGE_FORMULA { | ||
| 2827 | USHORT usVoltageBaseLevel; /* In number of 1mv unit */ | ||
| 2828 | USHORT usVoltageStep; /* Indicating in how many mv increament is one step, 1mv unit */ | ||
| 2829 | UCHAR ucNumOfVoltageEntries; /* Number of Voltage Entry, which indicate max Voltage */ | ||
| 2830 | UCHAR ucFlag; /* bit0=0 :step is 1mv =1 0.5mv */ | ||
| 2831 | UCHAR ucBaseVID; /* if there is no lookup table, VID= BaseVID + ( Vol - BaseLevle ) /VoltageStep */ | ||
| 2832 | UCHAR ucReserved; | ||
| 2833 | UCHAR ucVIDAdjustEntries[32]; /* 32 is for allocation, the actual number of entry is present at ucNumOfVoltageEntries */ | ||
| 2834 | } ATOM_VOLTAGE_FORMULA; | ||
| 2835 | |||
| 2836 | typedef struct _ATOM_VOLTAGE_CONTROL { | ||
| 2837 | UCHAR ucVoltageControlId; /* Indicate it is controlled by I2C or GPIO or HW state machine */ | ||
| 2838 | UCHAR ucVoltageControlI2cLine; | ||
| 2839 | UCHAR ucVoltageControlAddress; | ||
| 2840 | UCHAR ucVoltageControlOffset; | ||
| 2841 | USHORT usGpioPin_AIndex; /* GPIO_PAD register index */ | ||
| 2842 | UCHAR ucGpioPinBitShift[9]; /* at most 8 pin support 255 VIDs, termintate with 0xff */ | ||
| 2843 | UCHAR ucReserved; | ||
| 2844 | } ATOM_VOLTAGE_CONTROL; | ||
| 2845 | |||
| 2846 | /* Define ucVoltageControlId */ | ||
| 2847 | #define VOLTAGE_CONTROLLED_BY_HW 0x00 | ||
| 2848 | #define VOLTAGE_CONTROLLED_BY_I2C_MASK 0x7F | ||
| 2849 | #define VOLTAGE_CONTROLLED_BY_GPIO 0x80 | ||
| 2850 | #define VOLTAGE_CONTROL_ID_LM64 0x01 /* I2C control, used for R5xx Core Voltage */ | ||
| 2851 | #define VOLTAGE_CONTROL_ID_DAC 0x02 /* I2C control, used for R5xx/R6xx MVDDC,MVDDQ or VDDCI */ | ||
| 2852 | #define VOLTAGE_CONTROL_ID_VT116xM 0x03 /* I2C control, used for R6xx Core Voltage */ | ||
| 2853 | #define VOLTAGE_CONTROL_ID_DS4402 0x04 | ||
| 2854 | |||
| 2855 | typedef struct _ATOM_VOLTAGE_OBJECT { | ||
| 2856 | UCHAR ucVoltageType; /* Indicate Voltage Source: VDDC, MVDDC, MVDDQ or MVDDCI */ | ||
| 2857 | UCHAR ucSize; /* Size of Object */ | ||
| 2858 | ATOM_VOLTAGE_CONTROL asControl; /* describ how to control */ | ||
| 2859 | ATOM_VOLTAGE_FORMULA asFormula; /* Indicate How to convert real Voltage to VID */ | ||
| 2860 | } ATOM_VOLTAGE_OBJECT; | ||
| 2861 | |||
| 2862 | typedef struct _ATOM_VOLTAGE_OBJECT_INFO { | ||
| 2863 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 2864 | ATOM_VOLTAGE_OBJECT asVoltageObj[3]; /* Info for Voltage control */ | ||
| 2865 | } ATOM_VOLTAGE_OBJECT_INFO; | ||
| 2866 | |||
| 2867 | typedef struct _ATOM_LEAKID_VOLTAGE { | ||
| 2868 | UCHAR ucLeakageId; | ||
| 2869 | UCHAR ucReserved; | ||
| 2870 | USHORT usVoltage; | ||
| 2871 | } ATOM_LEAKID_VOLTAGE; | ||
| 2872 | |||
| 2873 | typedef struct _ATOM_ASIC_PROFILE_VOLTAGE { | ||
| 2874 | UCHAR ucProfileId; | ||
| 2875 | UCHAR ucReserved; | ||
| 2876 | USHORT usSize; | ||
| 2877 | USHORT usEfuseSpareStartAddr; | ||
| 2878 | USHORT usFuseIndex[8]; /* from LSB to MSB, Max 8bit,end of 0xffff if less than 8 efuse id, */ | ||
| 2879 | ATOM_LEAKID_VOLTAGE asLeakVol[2]; /* Leakid and relatd voltage */ | ||
| 2880 | } ATOM_ASIC_PROFILE_VOLTAGE; | ||
| 2881 | |||
| 2882 | /* ucProfileId */ | ||
| 2883 | #define ATOM_ASIC_PROFILE_ID_EFUSE_VOLTAGE 1 | ||
| 2884 | #define ATOM_ASIC_PROFILE_ID_EFUSE_PERFORMANCE_VOLTAGE 1 | ||
| 2885 | #define ATOM_ASIC_PROFILE_ID_EFUSE_THERMAL_VOLTAGE 2 | ||
| 2886 | |||
| 2887 | typedef struct _ATOM_ASIC_PROFILING_INFO { | ||
| 2888 | ATOM_COMMON_TABLE_HEADER asHeader; | ||
| 2889 | ATOM_ASIC_PROFILE_VOLTAGE asVoltage; | ||
| 2890 | } ATOM_ASIC_PROFILING_INFO; | ||
| 2891 | |||
| 2892 | typedef struct _ATOM_POWER_SOURCE_OBJECT { | ||
| 2893 | UCHAR ucPwrSrcId; /* Power source */ | ||
| 2894 | UCHAR ucPwrSensorType; /* GPIO, I2C or none */ | ||
| 2895 | UCHAR ucPwrSensId; /* if GPIO detect, it is GPIO id, if I2C detect, it is I2C id */ | ||
| 2896 | UCHAR ucPwrSensSlaveAddr; /* Slave address if I2C detect */ | ||
| 2897 | UCHAR ucPwrSensRegIndex; /* I2C register Index if I2C detect */ | ||
| 2898 | UCHAR ucPwrSensRegBitMask; /* detect which bit is used if I2C detect */ | ||
| 2899 | UCHAR ucPwrSensActiveState; /* high active or low active */ | ||
| 2900 | UCHAR ucReserve[3]; /* reserve */ | ||
| 2901 | USHORT usSensPwr; /* in unit of watt */ | ||
| 2902 | } ATOM_POWER_SOURCE_OBJECT; | ||
| 2903 | |||
| 2904 | typedef struct _ATOM_POWER_SOURCE_INFO { | ||
| 2905 | ATOM_COMMON_TABLE_HEADER asHeader; | ||
| 2906 | UCHAR asPwrbehave[16]; | ||
| 2907 | ATOM_POWER_SOURCE_OBJECT asPwrObj[1]; | ||
| 2908 | } ATOM_POWER_SOURCE_INFO; | ||
| 2909 | |||
| 2910 | /* Define ucPwrSrcId */ | ||
| 2911 | #define POWERSOURCE_PCIE_ID1 0x00 | ||
| 2912 | #define POWERSOURCE_6PIN_CONNECTOR_ID1 0x01 | ||
| 2913 | #define POWERSOURCE_8PIN_CONNECTOR_ID1 0x02 | ||
| 2914 | #define POWERSOURCE_6PIN_CONNECTOR_ID2 0x04 | ||
| 2915 | #define POWERSOURCE_8PIN_CONNECTOR_ID2 0x08 | ||
| 2916 | |||
| 2917 | /* define ucPwrSensorId */ | ||
| 2918 | #define POWER_SENSOR_ALWAYS 0x00 | ||
| 2919 | #define POWER_SENSOR_GPIO 0x01 | ||
| 2920 | #define POWER_SENSOR_I2C 0x02 | ||
| 2921 | |||
| 2922 | /**************************************************************************/ | ||
| 2923 | /* This portion is only used when ext thermal chip or engine/memory clock SS chip is populated on a design */ | ||
| 2924 | /* Memory SS Info Table */ | ||
| 2925 | /* Define Memory Clock SS chip ID */ | ||
| 2926 | #define ICS91719 1 | ||
| 2927 | #define ICS91720 2 | ||
| 2928 | |||
| 2929 | /* Define one structure to inform SW a "block of data" writing to external SS chip via I2C protocol */ | ||
| 2930 | typedef struct _ATOM_I2C_DATA_RECORD { | ||
| 2931 | UCHAR ucNunberOfBytes; /* Indicates how many bytes SW needs to write to the external ASIC for one block, besides to "Start" and "Stop" */ | ||
| 2932 | UCHAR ucI2CData[1]; /* I2C data in bytes, should be less than 16 bytes usually */ | ||
| 2933 | } ATOM_I2C_DATA_RECORD; | ||
| 2934 | |||
| 2935 | /* Define one structure to inform SW how many blocks of data writing to external SS chip via I2C protocol, in addition to other information */ | ||
| 2936 | typedef struct _ATOM_I2C_DEVICE_SETUP_INFO { | ||
| 2937 | ATOM_I2C_ID_CONFIG_ACCESS sucI2cId; /* I2C line and HW/SW assisted cap. */ | ||
| 2938 | UCHAR ucSSChipID; /* SS chip being used */ | ||
| 2939 | UCHAR ucSSChipSlaveAddr; /* Slave Address to set up this SS chip */ | ||
| 2940 | UCHAR ucNumOfI2CDataRecords; /* number of data block */ | ||
| 2941 | ATOM_I2C_DATA_RECORD asI2CData[1]; | ||
| 2942 | } ATOM_I2C_DEVICE_SETUP_INFO; | ||
| 2943 | |||
| 2944 | /* ========================================================================================== */ | ||
| 2945 | typedef struct _ATOM_ASIC_MVDD_INFO { | ||
| 2946 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 2947 | ATOM_I2C_DEVICE_SETUP_INFO asI2CSetup[1]; | ||
| 2948 | } ATOM_ASIC_MVDD_INFO; | ||
| 2949 | |||
| 2950 | /* ========================================================================================== */ | ||
| 2951 | #define ATOM_MCLK_SS_INFO ATOM_ASIC_MVDD_INFO | ||
| 2952 | |||
| 2953 | /* ========================================================================================== */ | ||
| 2954 | /**************************************************************************/ | ||
| 2955 | |||
| 2956 | typedef struct _ATOM_ASIC_SS_ASSIGNMENT { | ||
| 2957 | ULONG ulTargetClockRange; /* Clock Out frequence (VCO ), in unit of 10Khz */ | ||
| 2958 | USHORT usSpreadSpectrumPercentage; /* in unit of 0.01% */ | ||
| 2959 | USHORT usSpreadRateInKhz; /* in unit of kHz, modulation freq */ | ||
| 2960 | UCHAR ucClockIndication; /* Indicate which clock source needs SS */ | ||
| 2961 | UCHAR ucSpreadSpectrumMode; /* Bit1=0 Down Spread,=1 Center Spread. */ | ||
| 2962 | UCHAR ucReserved[2]; | ||
| 2963 | } ATOM_ASIC_SS_ASSIGNMENT; | ||
| 2964 | |||
| 2965 | /* Define ucSpreadSpectrumType */ | ||
| 2966 | #define ASIC_INTERNAL_MEMORY_SS 1 | ||
| 2967 | #define ASIC_INTERNAL_ENGINE_SS 2 | ||
| 2968 | #define ASIC_INTERNAL_UVD_SS 3 | ||
| 2969 | |||
| 2970 | typedef struct _ATOM_ASIC_INTERNAL_SS_INFO { | ||
| 2971 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 2972 | ATOM_ASIC_SS_ASSIGNMENT asSpreadSpectrum[4]; | ||
| 2973 | } ATOM_ASIC_INTERNAL_SS_INFO; | ||
| 2974 | |||
| 2975 | /* ==============================Scratch Pad Definition Portion=============================== */ | ||
| 2976 | #define ATOM_DEVICE_CONNECT_INFO_DEF 0 | ||
| 2977 | #define ATOM_ROM_LOCATION_DEF 1 | ||
| 2978 | #define ATOM_TV_STANDARD_DEF 2 | ||
| 2979 | #define ATOM_ACTIVE_INFO_DEF 3 | ||
| 2980 | #define ATOM_LCD_INFO_DEF 4 | ||
| 2981 | #define ATOM_DOS_REQ_INFO_DEF 5 | ||
| 2982 | #define ATOM_ACC_CHANGE_INFO_DEF 6 | ||
| 2983 | #define ATOM_DOS_MODE_INFO_DEF 7 | ||
| 2984 | #define ATOM_I2C_CHANNEL_STATUS_DEF 8 | ||
| 2985 | #define ATOM_I2C_CHANNEL_STATUS1_DEF 9 | ||
| 2986 | |||
| 2987 | /* BIOS_0_SCRATCH Definition */ | ||
| 2988 | #define ATOM_S0_CRT1_MONO 0x00000001L | ||
| 2989 | #define ATOM_S0_CRT1_COLOR 0x00000002L | ||
| 2990 | #define ATOM_S0_CRT1_MASK (ATOM_S0_CRT1_MONO+ATOM_S0_CRT1_COLOR) | ||
| 2991 | |||
| 2992 | #define ATOM_S0_TV1_COMPOSITE_A 0x00000004L | ||
| 2993 | #define ATOM_S0_TV1_SVIDEO_A 0x00000008L | ||
| 2994 | #define ATOM_S0_TV1_MASK_A (ATOM_S0_TV1_COMPOSITE_A+ATOM_S0_TV1_SVIDEO_A) | ||
| 2995 | |||
| 2996 | #define ATOM_S0_CV_A 0x00000010L | ||
| 2997 | #define ATOM_S0_CV_DIN_A 0x00000020L | ||
| 2998 | #define ATOM_S0_CV_MASK_A (ATOM_S0_CV_A+ATOM_S0_CV_DIN_A) | ||
| 2999 | |||
| 3000 | #define ATOM_S0_CRT2_MONO 0x00000100L | ||
| 3001 | #define ATOM_S0_CRT2_COLOR 0x00000200L | ||
| 3002 | #define ATOM_S0_CRT2_MASK (ATOM_S0_CRT2_MONO+ATOM_S0_CRT2_COLOR) | ||
| 3003 | |||
| 3004 | #define ATOM_S0_TV1_COMPOSITE 0x00000400L | ||
| 3005 | #define ATOM_S0_TV1_SVIDEO 0x00000800L | ||
| 3006 | #define ATOM_S0_TV1_SCART 0x00004000L | ||
| 3007 | #define ATOM_S0_TV1_MASK (ATOM_S0_TV1_COMPOSITE+ATOM_S0_TV1_SVIDEO+ATOM_S0_TV1_SCART) | ||
| 3008 | |||
| 3009 | #define ATOM_S0_CV 0x00001000L | ||
| 3010 | #define ATOM_S0_CV_DIN 0x00002000L | ||
| 3011 | #define ATOM_S0_CV_MASK (ATOM_S0_CV+ATOM_S0_CV_DIN) | ||
| 3012 | |||
| 3013 | #define ATOM_S0_DFP1 0x00010000L | ||
| 3014 | #define ATOM_S0_DFP2 0x00020000L | ||
| 3015 | #define ATOM_S0_LCD1 0x00040000L | ||
| 3016 | #define ATOM_S0_LCD2 0x00080000L | ||
| 3017 | #define ATOM_S0_TV2 0x00100000L | ||
| 3018 | #define ATOM_S0_DFP3 0x00200000L | ||
| 3019 | #define ATOM_S0_DFP4 0x00400000L | ||
| 3020 | #define ATOM_S0_DFP5 0x00800000L | ||
| 3021 | |||
| 3022 | #define ATOM_S0_DFP_MASK \ | ||
| 3023 | (ATOM_S0_DFP1 | ATOM_S0_DFP2 | ATOM_S0_DFP3 | ATOM_S0_DFP4 | ATOM_S0_DFP5) | ||
| 3024 | |||
| 3025 | #define ATOM_S0_FAD_REGISTER_BUG 0x02000000L /* If set, indicates we are running a PCIE asic with */ | ||
| 3026 | /* the FAD/HDP reg access bug. Bit is read by DAL */ | ||
| 3027 | |||
| 3028 | #define ATOM_S0_THERMAL_STATE_MASK 0x1C000000L | ||
| 3029 | #define ATOM_S0_THERMAL_STATE_SHIFT 26 | ||
| 3030 | |||
| 3031 | #define ATOM_S0_SYSTEM_POWER_STATE_MASK 0xE0000000L | ||
| 3032 | #define ATOM_S0_SYSTEM_POWER_STATE_SHIFT 29 | ||
| 3033 | |||
| 3034 | #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_AC 1 | ||
| 3035 | #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_DC 2 | ||
| 3036 | #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_LITEAC 3 | ||
| 3037 | |||
| 3038 | /* Byte aligned defintion for BIOS usage */ | ||
| 3039 | #define ATOM_S0_CRT1_MONOb0 0x01 | ||
| 3040 | #define ATOM_S0_CRT1_COLORb0 0x02 | ||
| 3041 | #define ATOM_S0_CRT1_MASKb0 (ATOM_S0_CRT1_MONOb0+ATOM_S0_CRT1_COLORb0) | ||
| 3042 | |||
| 3043 | #define ATOM_S0_TV1_COMPOSITEb0 0x04 | ||
| 3044 | #define ATOM_S0_TV1_SVIDEOb0 0x08 | ||
| 3045 | #define ATOM_S0_TV1_MASKb0 (ATOM_S0_TV1_COMPOSITEb0+ATOM_S0_TV1_SVIDEOb0) | ||
| 3046 | |||
| 3047 | #define ATOM_S0_CVb0 0x10 | ||
| 3048 | #define ATOM_S0_CV_DINb0 0x20 | ||
| 3049 | #define ATOM_S0_CV_MASKb0 (ATOM_S0_CVb0+ATOM_S0_CV_DINb0) | ||
| 3050 | |||
| 3051 | #define ATOM_S0_CRT2_MONOb1 0x01 | ||
| 3052 | #define ATOM_S0_CRT2_COLORb1 0x02 | ||
| 3053 | #define ATOM_S0_CRT2_MASKb1 (ATOM_S0_CRT2_MONOb1+ATOM_S0_CRT2_COLORb1) | ||
| 3054 | |||
| 3055 | #define ATOM_S0_TV1_COMPOSITEb1 0x04 | ||
| 3056 | #define ATOM_S0_TV1_SVIDEOb1 0x08 | ||
| 3057 | #define ATOM_S0_TV1_SCARTb1 0x40 | ||
| 3058 | #define ATOM_S0_TV1_MASKb1 (ATOM_S0_TV1_COMPOSITEb1+ATOM_S0_TV1_SVIDEOb1+ATOM_S0_TV1_SCARTb1) | ||
| 3059 | |||
| 3060 | #define ATOM_S0_CVb1 0x10 | ||
| 3061 | #define ATOM_S0_CV_DINb1 0x20 | ||
| 3062 | #define ATOM_S0_CV_MASKb1 (ATOM_S0_CVb1+ATOM_S0_CV_DINb1) | ||
| 3063 | |||
| 3064 | #define ATOM_S0_DFP1b2 0x01 | ||
| 3065 | #define ATOM_S0_DFP2b2 0x02 | ||
| 3066 | #define ATOM_S0_LCD1b2 0x04 | ||
| 3067 | #define ATOM_S0_LCD2b2 0x08 | ||
| 3068 | #define ATOM_S0_TV2b2 0x10 | ||
| 3069 | #define ATOM_S0_DFP3b2 0x20 | ||
| 3070 | |||
| 3071 | #define ATOM_S0_THERMAL_STATE_MASKb3 0x1C | ||
| 3072 | #define ATOM_S0_THERMAL_STATE_SHIFTb3 2 | ||
| 3073 | |||
| 3074 | #define ATOM_S0_SYSTEM_POWER_STATE_MASKb3 0xE0 | ||
| 3075 | #define ATOM_S0_LCD1_SHIFT 18 | ||
| 3076 | |||
| 3077 | /* BIOS_1_SCRATCH Definition */ | ||
| 3078 | #define ATOM_S1_ROM_LOCATION_MASK 0x0000FFFFL | ||
| 3079 | #define ATOM_S1_PCI_BUS_DEV_MASK 0xFFFF0000L | ||
| 3080 | |||
| 3081 | /* BIOS_2_SCRATCH Definition */ | ||
| 3082 | #define ATOM_S2_TV1_STANDARD_MASK 0x0000000FL | ||
| 3083 | #define ATOM_S2_CURRENT_BL_LEVEL_MASK 0x0000FF00L | ||
| 3084 | #define ATOM_S2_CURRENT_BL_LEVEL_SHIFT 8 | ||
| 3085 | |||
| 3086 | #define ATOM_S2_CRT1_DPMS_STATE 0x00010000L | ||
| 3087 | #define ATOM_S2_LCD1_DPMS_STATE 0x00020000L | ||
| 3088 | #define ATOM_S2_TV1_DPMS_STATE 0x00040000L | ||
| 3089 | #define ATOM_S2_DFP1_DPMS_STATE 0x00080000L | ||
| 3090 | #define ATOM_S2_CRT2_DPMS_STATE 0x00100000L | ||
| 3091 | #define ATOM_S2_LCD2_DPMS_STATE 0x00200000L | ||
| 3092 | #define ATOM_S2_TV2_DPMS_STATE 0x00400000L | ||
| 3093 | #define ATOM_S2_DFP2_DPMS_STATE 0x00800000L | ||
| 3094 | #define ATOM_S2_CV_DPMS_STATE 0x01000000L | ||
| 3095 | #define ATOM_S2_DFP3_DPMS_STATE 0x02000000L | ||
| 3096 | #define ATOM_S2_DFP4_DPMS_STATE 0x04000000L | ||
| 3097 | #define ATOM_S2_DFP5_DPMS_STATE 0x08000000L | ||
| 3098 | |||
| 3099 | #define ATOM_S2_DFP_DPM_STATE \ | ||
| 3100 | (ATOM_S2_DFP1_DPMS_STATE | ATOM_S2_DFP2_DPMS_STATE | \ | ||
| 3101 | ATOM_S2_DFP3_DPMS_STATE | ATOM_S2_DFP4_DPMS_STATE | \ | ||
| 3102 | ATOM_S2_DFP5_DPMS_STATE) | ||
| 3103 | |||
| 3104 | #define ATOM_S2_DEVICE_DPMS_STATE \ | ||
| 3105 | (ATOM_S2_CRT1_DPMS_STATE + ATOM_S2_LCD1_DPMS_STATE + \ | ||
| 3106 | ATOM_S2_TV1_DPMS_STATE + ATOM_S2_DFP_DPMS_STATE + \ | ||
| 3107 | ATOM_S2_CRT2_DPMS_STATE + ATOM_S2_LCD2_DPMS_STATE + \ | ||
| 3108 | ATOM_S2_TV2_DPMS_STATE + ATOM_S2_CV_DPMS_STATE) | ||
| 3109 | |||
| 3110 | #define ATOM_S2_FORCEDLOWPWRMODE_STATE_MASK 0x0C000000L | ||
| 3111 | #define ATOM_S2_FORCEDLOWPWRMODE_STATE_MASK_SHIFT 26 | ||
| 3112 | #define ATOM_S2_FORCEDLOWPWRMODE_STATE_CHANGE 0x10000000L | ||
| 3113 | |||
| 3114 | #define ATOM_S2_VRI_BRIGHT_ENABLE 0x20000000L | ||
| 3115 | |||
| 3116 | #define ATOM_S2_DISPLAY_ROTATION_0_DEGREE 0x0 | ||
| 3117 | #define ATOM_S2_DISPLAY_ROTATION_90_DEGREE 0x1 | ||
| 3118 | #define ATOM_S2_DISPLAY_ROTATION_180_DEGREE 0x2 | ||
| 3119 | #define ATOM_S2_DISPLAY_ROTATION_270_DEGREE 0x3 | ||
| 3120 | #define ATOM_S2_DISPLAY_ROTATION_DEGREE_SHIFT 30 | ||
| 3121 | #define ATOM_S2_DISPLAY_ROTATION_ANGLE_MASK 0xC0000000L | ||
| 3122 | |||
| 3123 | /* Byte aligned defintion for BIOS usage */ | ||
| 3124 | #define ATOM_S2_TV1_STANDARD_MASKb0 0x0F | ||
| 3125 | #define ATOM_S2_CURRENT_BL_LEVEL_MASKb1 0xFF | ||
| 3126 | #define ATOM_S2_CRT1_DPMS_STATEb2 0x01 | ||
| 3127 | #define ATOM_S2_LCD1_DPMS_STATEb2 0x02 | ||
| 3128 | #define ATOM_S2_TV1_DPMS_STATEb2 0x04 | ||
| 3129 | #define ATOM_S2_DFP1_DPMS_STATEb2 0x08 | ||
| 3130 | #define ATOM_S2_CRT2_DPMS_STATEb2 0x10 | ||
| 3131 | #define ATOM_S2_LCD2_DPMS_STATEb2 0x20 | ||
| 3132 | #define ATOM_S2_TV2_DPMS_STATEb2 0x40 | ||
| 3133 | #define ATOM_S2_DFP2_DPMS_STATEb2 0x80 | ||
| 3134 | #define ATOM_S2_CV_DPMS_STATEb3 0x01 | ||
| 3135 | #define ATOM_S2_DFP3_DPMS_STATEb3 0x02 | ||
| 3136 | #define ATOM_S2_DFP4_DPMS_STATEb3 0x04 | ||
| 3137 | #define ATOM_S2_DFP5_DPMS_STATEb3 0x08 | ||
| 3138 | |||
| 3139 | #define ATOM_S2_DEVICE_DPMS_MASKw1 0x3FF | ||
| 3140 | #define ATOM_S2_FORCEDLOWPWRMODE_STATE_MASKb3 0x0C | ||
| 3141 | #define ATOM_S2_FORCEDLOWPWRMODE_STATE_CHANGEb3 0x10 | ||
| 3142 | #define ATOM_S2_VRI_BRIGHT_ENABLEb3 0x20 | ||
| 3143 | #define ATOM_S2_ROTATION_STATE_MASKb3 0xC0 | ||
| 3144 | |||
| 3145 | /* BIOS_3_SCRATCH Definition */ | ||
| 3146 | #define ATOM_S3_CRT1_ACTIVE 0x00000001L | ||
| 3147 | #define ATOM_S3_LCD1_ACTIVE 0x00000002L | ||
| 3148 | #define ATOM_S3_TV1_ACTIVE 0x00000004L | ||
| 3149 | #define ATOM_S3_DFP1_ACTIVE 0x00000008L | ||
| 3150 | #define ATOM_S3_CRT2_ACTIVE 0x00000010L | ||
| 3151 | #define ATOM_S3_LCD2_ACTIVE 0x00000020L | ||
| 3152 | #define ATOM_S3_TV2_ACTIVE 0x00000040L | ||
| 3153 | #define ATOM_S3_DFP2_ACTIVE 0x00000080L | ||
| 3154 | #define ATOM_S3_CV_ACTIVE 0x00000100L | ||
| 3155 | #define ATOM_S3_DFP3_ACTIVE 0x00000200L | ||
| 3156 | #define ATOM_S3_DFP4_ACTIVE 0x00000400L | ||
| 3157 | #define ATOM_S3_DFP5_ACTIVE 0x00000800L | ||
| 3158 | |||
| 3159 | #define ATOM_S3_DEVICE_ACTIVE_MASK 0x000003FFL | ||
| 3160 | |||
| 3161 | #define ATOM_S3_LCD_FULLEXPANSION_ACTIVE 0x00001000L | ||
| 3162 | #define ATOM_S3_LCD_EXPANSION_ASPEC_RATIO_ACTIVE 0x00002000L | ||
| 3163 | |||
| 3164 | #define ATOM_S3_CRT1_CRTC_ACTIVE 0x00010000L | ||
| 3165 | #define ATOM_S3_LCD1_CRTC_ACTIVE 0x00020000L | ||
| 3166 | #define ATOM_S3_TV1_CRTC_ACTIVE 0x00040000L | ||
| 3167 | #define ATOM_S3_DFP1_CRTC_ACTIVE 0x00080000L | ||
| 3168 | #define ATOM_S3_CRT2_CRTC_ACTIVE 0x00100000L | ||
| 3169 | #define ATOM_S3_LCD2_CRTC_ACTIVE 0x00200000L | ||
| 3170 | #define ATOM_S3_TV2_CRTC_ACTIVE 0x00400000L | ||
| 3171 | #define ATOM_S3_DFP2_CRTC_ACTIVE 0x00800000L | ||
| 3172 | #define ATOM_S3_CV_CRTC_ACTIVE 0x01000000L | ||
| 3173 | #define ATOM_S3_DFP3_CRTC_ACTIVE 0x02000000L | ||
| 3174 | #define ATOM_S3_DFP4_CRTC_ACTIVE 0x04000000L | ||
| 3175 | #define ATOM_S3_DFP5_CRTC_ACTIVE 0x08000000L | ||
| 3176 | |||
| 3177 | #define ATOM_S3_DEVICE_CRTC_ACTIVE_MASK 0x0FFF0000L | ||
| 3178 | #define ATOM_S3_ASIC_GUI_ENGINE_HUNG 0x20000000L | ||
| 3179 | #define ATOM_S3_ALLOW_FAST_PWR_SWITCH 0x40000000L | ||
| 3180 | #define ATOM_S3_RQST_GPU_USE_MIN_PWR 0x80000000L | ||
| 3181 | |||
| 3182 | /* Byte aligned defintion for BIOS usage */ | ||
| 3183 | #define ATOM_S3_CRT1_ACTIVEb0 0x01 | ||
| 3184 | #define ATOM_S3_LCD1_ACTIVEb0 0x02 | ||
| 3185 | #define ATOM_S3_TV1_ACTIVEb0 0x04 | ||
| 3186 | #define ATOM_S3_DFP1_ACTIVEb0 0x08 | ||
| 3187 | #define ATOM_S3_CRT2_ACTIVEb0 0x10 | ||
| 3188 | #define ATOM_S3_LCD2_ACTIVEb0 0x20 | ||
| 3189 | #define ATOM_S3_TV2_ACTIVEb0 0x40 | ||
| 3190 | #define ATOM_S3_DFP2_ACTIVEb0 0x80 | ||
| 3191 | #define ATOM_S3_CV_ACTIVEb1 0x01 | ||
| 3192 | #define ATOM_S3_DFP3_ACTIVEb1 0x02 | ||
| 3193 | #define ATOM_S3_DFP4_ACTIVEb1 0x04 | ||
| 3194 | #define ATOM_S3_DFP5_ACTIVEb1 0x08 | ||
| 3195 | |||
| 3196 | #define ATOM_S3_ACTIVE_CRTC1w0 0xFFF | ||
| 3197 | |||
| 3198 | #define ATOM_S3_CRT1_CRTC_ACTIVEb2 0x01 | ||
| 3199 | #define ATOM_S3_LCD1_CRTC_ACTIVEb2 0x02 | ||
| 3200 | #define ATOM_S3_TV1_CRTC_ACTIVEb2 0x04 | ||
| 3201 | #define ATOM_S3_DFP1_CRTC_ACTIVEb2 0x08 | ||
| 3202 | #define ATOM_S3_CRT2_CRTC_ACTIVEb2 0x10 | ||
| 3203 | #define ATOM_S3_LCD2_CRTC_ACTIVEb2 0x20 | ||
| 3204 | #define ATOM_S3_TV2_CRTC_ACTIVEb2 0x40 | ||
| 3205 | #define ATOM_S3_DFP2_CRTC_ACTIVEb2 0x80 | ||
| 3206 | #define ATOM_S3_CV_CRTC_ACTIVEb3 0x01 | ||
| 3207 | #define ATOM_S3_DFP3_CRTC_ACTIVEb3 0x02 | ||
| 3208 | #define ATOM_S3_DFP4_CRTC_ACTIVEb3 0x04 | ||
| 3209 | #define ATOM_S3_DFP5_CRTC_ACTIVEb3 0x08 | ||
| 3210 | |||
| 3211 | #define ATOM_S3_ACTIVE_CRTC2w1 0xFFF | ||
| 3212 | |||
| 3213 | #define ATOM_S3_ASIC_GUI_ENGINE_HUNGb3 0x20 | ||
| 3214 | #define ATOM_S3_ALLOW_FAST_PWR_SWITCHb3 0x40 | ||
| 3215 | #define ATOM_S3_RQST_GPU_USE_MIN_PWRb3 0x80 | ||
| 3216 | |||
| 3217 | /* BIOS_4_SCRATCH Definition */ | ||
| 3218 | #define ATOM_S4_LCD1_PANEL_ID_MASK 0x000000FFL | ||
| 3219 | #define ATOM_S4_LCD1_REFRESH_MASK 0x0000FF00L | ||
| 3220 | #define ATOM_S4_LCD1_REFRESH_SHIFT 8 | ||
| 3221 | |||
| 3222 | /* Byte aligned defintion for BIOS usage */ | ||
| 3223 | #define ATOM_S4_LCD1_PANEL_ID_MASKb0 0x0FF | ||
| 3224 | #define ATOM_S4_LCD1_REFRESH_MASKb1 ATOM_S4_LCD1_PANEL_ID_MASKb0 | ||
| 3225 | #define ATOM_S4_VRAM_INFO_MASKb2 ATOM_S4_LCD1_PANEL_ID_MASKb0 | ||
| 3226 | |||
| 3227 | /* BIOS_5_SCRATCH Definition, BIOS_5_SCRATCH is used by Firmware only !!!! */ | ||
| 3228 | #define ATOM_S5_DOS_REQ_CRT1b0 0x01 | ||
| 3229 | #define ATOM_S5_DOS_REQ_LCD1b0 0x02 | ||
| 3230 | #define ATOM_S5_DOS_REQ_TV1b0 0x04 | ||
| 3231 | #define ATOM_S5_DOS_REQ_DFP1b0 0x08 | ||
| 3232 | #define ATOM_S5_DOS_REQ_CRT2b0 0x10 | ||
| 3233 | #define ATOM_S5_DOS_REQ_LCD2b0 0x20 | ||
| 3234 | #define ATOM_S5_DOS_REQ_TV2b0 0x40 | ||
| 3235 | #define ATOM_S5_DOS_REQ_DFP2b0 0x80 | ||
| 3236 | #define ATOM_S5_DOS_REQ_CVb1 0x01 | ||
| 3237 | #define ATOM_S5_DOS_REQ_DFP3b1 0x02 | ||
| 3238 | #define ATOM_S5_DOS_REQ_DFP4b1 0x04 | ||
| 3239 | #define ATOM_S5_DOS_REQ_DFP5b1 0x08 | ||
| 3240 | |||
| 3241 | #define ATOM_S5_DOS_REQ_DEVICEw0 0x03FF | ||
| 3242 | |||
| 3243 | #define ATOM_S5_DOS_REQ_CRT1 0x0001 | ||
| 3244 | #define ATOM_S5_DOS_REQ_LCD1 0x0002 | ||
| 3245 | #define ATOM_S5_DOS_REQ_TV1 0x0004 | ||
| 3246 | #define ATOM_S5_DOS_REQ_DFP1 0x0008 | ||
| 3247 | #define ATOM_S5_DOS_REQ_CRT2 0x0010 | ||
| 3248 | #define ATOM_S5_DOS_REQ_LCD2 0x0020 | ||
| 3249 | #define ATOM_S5_DOS_REQ_TV2 0x0040 | ||
| 3250 | #define ATOM_S5_DOS_REQ_DFP2 0x0080 | ||
| 3251 | #define ATOM_S5_DOS_REQ_CV 0x0100 | ||
| 3252 | #define ATOM_S5_DOS_REQ_DFP3 0x0200 | ||
| 3253 | #define ATOM_S5_DOS_REQ_DFP4 0x0400 | ||
| 3254 | #define ATOM_S5_DOS_REQ_DFP5 0x0800 | ||
| 3255 | |||
| 3256 | #define ATOM_S5_DOS_FORCE_CRT1b2 ATOM_S5_DOS_REQ_CRT1b0 | ||
| 3257 | #define ATOM_S5_DOS_FORCE_TV1b2 ATOM_S5_DOS_REQ_TV1b0 | ||
| 3258 | #define ATOM_S5_DOS_FORCE_CRT2b2 ATOM_S5_DOS_REQ_CRT2b0 | ||
| 3259 | #define ATOM_S5_DOS_FORCE_CVb3 ATOM_S5_DOS_REQ_CVb1 | ||
| 3260 | #define ATOM_S5_DOS_FORCE_DEVICEw1 \ | ||
| 3261 | (ATOM_S5_DOS_FORCE_CRT1b2 + ATOM_S5_DOS_FORCE_TV1b2 + \ | ||
| 3262 | ATOM_S5_DOS_FORCE_CRT2b2 + (ATOM_S5_DOS_FORCE_CVb3 << 8)) | ||
| 3263 | |||
| 3264 | /* BIOS_6_SCRATCH Definition */ | ||
| 3265 | #define ATOM_S6_DEVICE_CHANGE 0x00000001L | ||
| 3266 | #define ATOM_S6_SCALER_CHANGE 0x00000002L | ||
| 3267 | #define ATOM_S6_LID_CHANGE 0x00000004L | ||
| 3268 | #define ATOM_S6_DOCKING_CHANGE 0x00000008L | ||
| 3269 | #define ATOM_S6_ACC_MODE 0x00000010L | ||
| 3270 | #define ATOM_S6_EXT_DESKTOP_MODE 0x00000020L | ||
| 3271 | #define ATOM_S6_LID_STATE 0x00000040L | ||
| 3272 | #define ATOM_S6_DOCK_STATE 0x00000080L | ||
| 3273 | #define ATOM_S6_CRITICAL_STATE 0x00000100L | ||
| 3274 | #define ATOM_S6_HW_I2C_BUSY_STATE 0x00000200L | ||
| 3275 | #define ATOM_S6_THERMAL_STATE_CHANGE 0x00000400L | ||
| 3276 | #define ATOM_S6_INTERRUPT_SET_BY_BIOS 0x00000800L | ||
| 3277 | #define ATOM_S6_REQ_LCD_EXPANSION_FULL 0x00001000L /* Normal expansion Request bit for LCD */ | ||
| 3278 | #define ATOM_S6_REQ_LCD_EXPANSION_ASPEC_RATIO 0x00002000L /* Aspect ratio expansion Request bit for LCD */ | ||
| 3279 | |||
| 3280 | #define ATOM_S6_DISPLAY_STATE_CHANGE 0x00004000L /* This bit is recycled when ATOM_BIOS_INFO_BIOS_SCRATCH6_SCL2_REDEFINE is set,previously it's SCL2_H_expansion */ | ||
| 3281 | #define ATOM_S6_I2C_STATE_CHANGE 0x00008000L /* This bit is recycled,when ATOM_BIOS_INFO_BIOS_SCRATCH6_SCL2_REDEFINE is set,previously it's SCL2_V_expansion */ | ||
| 3282 | |||
| 3283 | #define ATOM_S6_ACC_REQ_CRT1 0x00010000L | ||
| 3284 | #define ATOM_S6_ACC_REQ_LCD1 0x00020000L | ||
| 3285 | #define ATOM_S6_ACC_REQ_TV1 0x00040000L | ||
| 3286 | #define ATOM_S6_ACC_REQ_DFP1 0x00080000L | ||
| 3287 | #define ATOM_S6_ACC_REQ_CRT2 0x00100000L | ||
| 3288 | #define ATOM_S6_ACC_REQ_LCD2 0x00200000L | ||
| 3289 | #define ATOM_S6_ACC_REQ_TV2 0x00400000L | ||
| 3290 | #define ATOM_S6_ACC_REQ_DFP2 0x00800000L | ||
| 3291 | #define ATOM_S6_ACC_REQ_CV 0x01000000L | ||
| 3292 | #define ATOM_S6_ACC_REQ_DFP3 0x02000000L | ||
| 3293 | #define ATOM_S6_ACC_REQ_DFP4 0x04000000L | ||
| 3294 | #define ATOM_S6_ACC_REQ_DFP5 0x08000000L | ||
| 3295 | |||
| 3296 | #define ATOM_S6_ACC_REQ_MASK 0x0FFF0000L | ||
| 3297 | #define ATOM_S6_SYSTEM_POWER_MODE_CHANGE 0x10000000L | ||
| 3298 | #define ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH 0x20000000L | ||
| 3299 | #define ATOM_S6_VRI_BRIGHTNESS_CHANGE 0x40000000L | ||
| 3300 | #define ATOM_S6_CONFIG_DISPLAY_CHANGE_MASK 0x80000000L | ||
| 3301 | |||
| 3302 | /* Byte aligned defintion for BIOS usage */ | ||
| 3303 | #define ATOM_S6_DEVICE_CHANGEb0 0x01 | ||
| 3304 | #define ATOM_S6_SCALER_CHANGEb0 0x02 | ||
| 3305 | #define ATOM_S6_LID_CHANGEb0 0x04 | ||
| 3306 | #define ATOM_S6_DOCKING_CHANGEb0 0x08 | ||
| 3307 | #define ATOM_S6_ACC_MODEb0 0x10 | ||
| 3308 | #define ATOM_S6_EXT_DESKTOP_MODEb0 0x20 | ||
| 3309 | #define ATOM_S6_LID_STATEb0 0x40 | ||
| 3310 | #define ATOM_S6_DOCK_STATEb0 0x80 | ||
| 3311 | #define ATOM_S6_CRITICAL_STATEb1 0x01 | ||
| 3312 | #define ATOM_S6_HW_I2C_BUSY_STATEb1 0x02 | ||
| 3313 | #define ATOM_S6_THERMAL_STATE_CHANGEb1 0x04 | ||
| 3314 | #define ATOM_S6_INTERRUPT_SET_BY_BIOSb1 0x08 | ||
| 3315 | #define ATOM_S6_REQ_LCD_EXPANSION_FULLb1 0x10 | ||
| 3316 | #define ATOM_S6_REQ_LCD_EXPANSION_ASPEC_RATIOb1 0x20 | ||
| 3317 | |||
| 3318 | #define ATOM_S6_ACC_REQ_CRT1b2 0x01 | ||
| 3319 | #define ATOM_S6_ACC_REQ_LCD1b2 0x02 | ||
| 3320 | #define ATOM_S6_ACC_REQ_TV1b2 0x04 | ||
| 3321 | #define ATOM_S6_ACC_REQ_DFP1b2 0x08 | ||
| 3322 | #define ATOM_S6_ACC_REQ_CRT2b2 0x10 | ||
| 3323 | #define ATOM_S6_ACC_REQ_LCD2b2 0x20 | ||
| 3324 | #define ATOM_S6_ACC_REQ_TV2b2 0x40 | ||
| 3325 | #define ATOM_S6_ACC_REQ_DFP2b2 0x80 | ||
| 3326 | #define ATOM_S6_ACC_REQ_CVb3 0x01 | ||
| 3327 | #define ATOM_S6_ACC_REQ_DFP3b3 0x02 | ||
| 3328 | #define ATOM_S6_ACC_REQ_DFP4b3 0x04 | ||
| 3329 | #define ATOM_S6_ACC_REQ_DFP5b3 0x08 | ||
| 3330 | |||
| 3331 | #define ATOM_S6_ACC_REQ_DEVICEw1 ATOM_S5_DOS_REQ_DEVICEw0 | ||
| 3332 | #define ATOM_S6_SYSTEM_POWER_MODE_CHANGEb3 0x10 | ||
| 3333 | #define ATOM_S6_ACC_BLOCK_DISPLAY_SWITCHb3 0x20 | ||
| 3334 | #define ATOM_S6_VRI_BRIGHTNESS_CHANGEb3 0x40 | ||
| 3335 | #define ATOM_S6_CONFIG_DISPLAY_CHANGEb3 0x80 | ||
| 3336 | |||
| 3337 | #define ATOM_S6_DEVICE_CHANGE_SHIFT 0 | ||
| 3338 | #define ATOM_S6_SCALER_CHANGE_SHIFT 1 | ||
| 3339 | #define ATOM_S6_LID_CHANGE_SHIFT 2 | ||
| 3340 | #define ATOM_S6_DOCKING_CHANGE_SHIFT 3 | ||
| 3341 | #define ATOM_S6_ACC_MODE_SHIFT 4 | ||
| 3342 | #define ATOM_S6_EXT_DESKTOP_MODE_SHIFT 5 | ||
| 3343 | #define ATOM_S6_LID_STATE_SHIFT 6 | ||
| 3344 | #define ATOM_S6_DOCK_STATE_SHIFT 7 | ||
| 3345 | #define ATOM_S6_CRITICAL_STATE_SHIFT 8 | ||
| 3346 | #define ATOM_S6_HW_I2C_BUSY_STATE_SHIFT 9 | ||
| 3347 | #define ATOM_S6_THERMAL_STATE_CHANGE_SHIFT 10 | ||
| 3348 | #define ATOM_S6_INTERRUPT_SET_BY_BIOS_SHIFT 11 | ||
| 3349 | #define ATOM_S6_REQ_SCALER_SHIFT 12 | ||
| 3350 | #define ATOM_S6_REQ_SCALER_ARATIO_SHIFT 13 | ||
| 3351 | #define ATOM_S6_DISPLAY_STATE_CHANGE_SHIFT 14 | ||
| 3352 | #define ATOM_S6_I2C_STATE_CHANGE_SHIFT 15 | ||
| 3353 | #define ATOM_S6_SYSTEM_POWER_MODE_CHANGE_SHIFT 28 | ||
| 3354 | #define ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH_SHIFT 29 | ||
| 3355 | #define ATOM_S6_VRI_BRIGHTNESS_CHANGE_SHIFT 30 | ||
| 3356 | #define ATOM_S6_CONFIG_DISPLAY_CHANGE_SHIFT 31 | ||
| 3357 | |||
| 3358 | /* BIOS_7_SCRATCH Definition, BIOS_7_SCRATCH is used by Firmware only !!!! */ | ||
| 3359 | #define ATOM_S7_DOS_MODE_TYPEb0 0x03 | ||
| 3360 | #define ATOM_S7_DOS_MODE_VGAb0 0x00 | ||
| 3361 | #define ATOM_S7_DOS_MODE_VESAb0 0x01 | ||
| 3362 | #define ATOM_S7_DOS_MODE_EXTb0 0x02 | ||
| 3363 | #define ATOM_S7_DOS_MODE_PIXEL_DEPTHb0 0x0C | ||
| 3364 | #define ATOM_S7_DOS_MODE_PIXEL_FORMATb0 0xF0 | ||
| 3365 | #define ATOM_S7_DOS_8BIT_DAC_ENb1 0x01 | ||
| 3366 | #define ATOM_S7_DOS_MODE_NUMBERw1 0x0FFFF | ||
| 3367 | |||
| 3368 | #define ATOM_S7_DOS_8BIT_DAC_EN_SHIFT 8 | ||
| 3369 | |||
| 3370 | /* BIOS_8_SCRATCH Definition */ | ||
| 3371 | #define ATOM_S8_I2C_CHANNEL_BUSY_MASK 0x00000FFFF | ||
| 3372 | #define ATOM_S8_I2C_HW_ENGINE_BUSY_MASK 0x0FFFF0000 | ||
| 3373 | |||
| 3374 | #define ATOM_S8_I2C_CHANNEL_BUSY_SHIFT 0 | ||
| 3375 | #define ATOM_S8_I2C_ENGINE_BUSY_SHIFT 16 | ||
| 3376 | |||
| 3377 | /* BIOS_9_SCRATCH Definition */ | ||
| 3378 | #ifndef ATOM_S9_I2C_CHANNEL_COMPLETED_MASK | ||
| 3379 | #define ATOM_S9_I2C_CHANNEL_COMPLETED_MASK 0x0000FFFF | ||
| 3380 | #endif | ||
| 3381 | #ifndef ATOM_S9_I2C_CHANNEL_ABORTED_MASK | ||
| 3382 | #define ATOM_S9_I2C_CHANNEL_ABORTED_MASK 0xFFFF0000 | ||
| 3383 | #endif | ||
| 3384 | #ifndef ATOM_S9_I2C_CHANNEL_COMPLETED_SHIFT | ||
| 3385 | #define ATOM_S9_I2C_CHANNEL_COMPLETED_SHIFT 0 | ||
| 3386 | #endif | ||
| 3387 | #ifndef ATOM_S9_I2C_CHANNEL_ABORTED_SHIFT | ||
| 3388 | #define ATOM_S9_I2C_CHANNEL_ABORTED_SHIFT 16 | ||
| 3389 | #endif | ||
| 3390 | |||
| 3391 | #define ATOM_FLAG_SET 0x20 | ||
| 3392 | #define ATOM_FLAG_CLEAR 0 | ||
| 3393 | #define CLEAR_ATOM_S6_ACC_MODE \ | ||
| 3394 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3395 | ATOM_S6_ACC_MODE_SHIFT | ATOM_FLAG_CLEAR) | ||
| 3396 | #define SET_ATOM_S6_DEVICE_CHANGE \ | ||
| 3397 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3398 | ATOM_S6_DEVICE_CHANGE_SHIFT | ATOM_FLAG_SET) | ||
| 3399 | #define SET_ATOM_S6_VRI_BRIGHTNESS_CHANGE \ | ||
| 3400 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3401 | ATOM_S6_VRI_BRIGHTNESS_CHANGE_SHIFT | ATOM_FLAG_SET) | ||
| 3402 | #define SET_ATOM_S6_SCALER_CHANGE \ | ||
| 3403 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3404 | ATOM_S6_SCALER_CHANGE_SHIFT | ATOM_FLAG_SET) | ||
| 3405 | #define SET_ATOM_S6_LID_CHANGE \ | ||
| 3406 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3407 | ATOM_S6_LID_CHANGE_SHIFT | ATOM_FLAG_SET) | ||
| 3408 | |||
| 3409 | #define SET_ATOM_S6_LID_STATE \ | ||
| 3410 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) |\ | ||
| 3411 | ATOM_S6_LID_STATE_SHIFT | ATOM_FLAG_SET) | ||
| 3412 | #define CLEAR_ATOM_S6_LID_STATE \ | ||
| 3413 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3414 | ATOM_S6_LID_STATE_SHIFT | ATOM_FLAG_CLEAR) | ||
| 3415 | |||
| 3416 | #define SET_ATOM_S6_DOCK_CHANGE \ | ||
| 3417 | ((ATOM_ACC_CHANGE_INFO_DEF << 8)| \ | ||
| 3418 | ATOM_S6_DOCKING_CHANGE_SHIFT | ATOM_FLAG_SET) | ||
| 3419 | #define SET_ATOM_S6_DOCK_STATE \ | ||
| 3420 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3421 | ATOM_S6_DOCK_STATE_SHIFT | ATOM_FLAG_SET) | ||
| 3422 | #define CLEAR_ATOM_S6_DOCK_STATE \ | ||
| 3423 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3424 | ATOM_S6_DOCK_STATE_SHIFT | ATOM_FLAG_CLEAR) | ||
| 3425 | |||
| 3426 | #define SET_ATOM_S6_THERMAL_STATE_CHANGE \ | ||
| 3427 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3428 | ATOM_S6_THERMAL_STATE_CHANGE_SHIFT | ATOM_FLAG_SET) | ||
| 3429 | #define SET_ATOM_S6_SYSTEM_POWER_MODE_CHANGE \ | ||
| 3430 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3431 | ATOM_S6_SYSTEM_POWER_MODE_CHANGE_SHIFT | ATOM_FLAG_SET) | ||
| 3432 | #define SET_ATOM_S6_INTERRUPT_SET_BY_BIOS \ | ||
| 3433 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3434 | ATOM_S6_INTERRUPT_SET_BY_BIOS_SHIFT | ATOM_FLAG_SET) | ||
| 3435 | |||
| 3436 | #define SET_ATOM_S6_CRITICAL_STATE \ | ||
| 3437 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3438 | ATOM_S6_CRITICAL_STATE_SHIFT | ATOM_FLAG_SET) | ||
| 3439 | #define CLEAR_ATOM_S6_CRITICAL_STATE \ | ||
| 3440 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3441 | ATOM_S6_CRITICAL_STATE_SHIFT | ATOM_FLAG_CLEAR) | ||
| 3442 | |||
| 3443 | #define SET_ATOM_S6_REQ_SCALER \ | ||
| 3444 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3445 | ATOM_S6_REQ_SCALER_SHIFT | ATOM_FLAG_SET) | ||
| 3446 | #define CLEAR_ATOM_S6_REQ_SCALER \ | ||
| 3447 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3448 | ATOM_S6_REQ_SCALER_SHIFT | ATOM_FLAG_CLEAR ) | ||
| 3449 | |||
| 3450 | #define SET_ATOM_S6_REQ_SCALER_ARATIO \ | ||
| 3451 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3452 | ATOM_S6_REQ_SCALER_ARATIO_SHIFT | ATOM_FLAG_SET ) | ||
| 3453 | #define CLEAR_ATOM_S6_REQ_SCALER_ARATIO \ | ||
| 3454 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3455 | ATOM_S6_REQ_SCALER_ARATIO_SHIFT | ATOM_FLAG_CLEAR ) | ||
| 3456 | |||
| 3457 | #define SET_ATOM_S6_I2C_STATE_CHANGE \ | ||
| 3458 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3459 | ATOM_S6_I2C_STATE_CHANGE_SHIFT | ATOM_FLAG_SET ) | ||
| 3460 | |||
| 3461 | #define SET_ATOM_S6_DISPLAY_STATE_CHANGE \ | ||
| 3462 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3463 | ATOM_S6_DISPLAY_STATE_CHANGE_SHIFT | ATOM_FLAG_SET ) | ||
| 3464 | |||
| 3465 | #define SET_ATOM_S6_DEVICE_RECONFIG \ | ||
| 3466 | ((ATOM_ACC_CHANGE_INFO_DEF << 8) | \ | ||
| 3467 | ATOM_S6_CONFIG_DISPLAY_CHANGE_SHIFT | ATOM_FLAG_SET) | ||
| 3468 | #define CLEAR_ATOM_S0_LCD1 \ | ||
| 3469 | ((ATOM_DEVICE_CONNECT_INFO_DEF << 8 ) | \ | ||
| 3470 | ATOM_S0_LCD1_SHIFT | ATOM_FLAG_CLEAR ) | ||
| 3471 | #define SET_ATOM_S7_DOS_8BIT_DAC_EN \ | ||
| 3472 | ((ATOM_DOS_MODE_INFO_DEF << 8) | \ | ||
| 3473 | ATOM_S7_DOS_8BIT_DAC_EN_SHIFT | ATOM_FLAG_SET ) | ||
| 3474 | #define CLEAR_ATOM_S7_DOS_8BIT_DAC_EN \ | ||
| 3475 | ((ATOM_DOS_MODE_INFO_DEF << 8) | \ | ||
| 3476 | ATOM_S7_DOS_8BIT_DAC_EN_SHIFT | ATOM_FLAG_CLEAR ) | ||
| 3477 | |||
| 3478 | /****************************************************************************/ | ||
| 3479 | /* Portion II: Definitinos only used in Driver */ | ||
| 3480 | /****************************************************************************/ | ||
| 3481 | |||
| 3482 | /* Macros used by driver */ | ||
| 3483 | |||
| 3484 | #define GetIndexIntoMasterTable(MasterOrData, FieldName) (((char *)(&((ATOM_MASTER_LIST_OF_##MasterOrData##_TABLES *)0)->FieldName)-(char *)0)/sizeof(USHORT)) | ||
| 3485 | |||
| 3486 | #define GET_COMMAND_TABLE_COMMANDSET_REVISION(TABLE_HEADER_OFFSET) ((((ATOM_COMMON_TABLE_HEADER*)TABLE_HEADER_OFFSET)->ucTableFormatRevision)&0x3F) | ||
| 3487 | #define GET_COMMAND_TABLE_PARAMETER_REVISION(TABLE_HEADER_OFFSET) ((((ATOM_COMMON_TABLE_HEADER*)TABLE_HEADER_OFFSET)->ucTableContentRevision)&0x3F) | ||
| 3488 | |||
| 3489 | #define GET_DATA_TABLE_MAJOR_REVISION GET_COMMAND_TABLE_COMMANDSET_REVISION | ||
| 3490 | #define GET_DATA_TABLE_MINOR_REVISION GET_COMMAND_TABLE_PARAMETER_REVISION | ||
| 3491 | |||
| 3492 | /****************************************************************************/ | ||
| 3493 | /* Portion III: Definitinos only used in VBIOS */ | ||
| 3494 | /****************************************************************************/ | ||
| 3495 | #define ATOM_DAC_SRC 0x80 | ||
| 3496 | #define ATOM_SRC_DAC1 0 | ||
| 3497 | #define ATOM_SRC_DAC2 0x80 | ||
| 3498 | |||
| 3499 | #ifdef UEFI_BUILD | ||
| 3500 | #define USHORT UTEMP | ||
| 3501 | #endif | ||
| 3502 | |||
| 3503 | typedef struct _MEMORY_PLLINIT_PARAMETERS { | ||
| 3504 | ULONG ulTargetMemoryClock; /* In 10Khz unit */ | ||
| 3505 | UCHAR ucAction; /* not define yet */ | ||
| 3506 | UCHAR ucFbDiv_Hi; /* Fbdiv Hi byte */ | ||
| 3507 | UCHAR ucFbDiv; /* FB value */ | ||
| 3508 | UCHAR ucPostDiv; /* Post div */ | ||
| 3509 | } MEMORY_PLLINIT_PARAMETERS; | ||
| 3510 | |||
| 3511 | #define MEMORY_PLLINIT_PS_ALLOCATION MEMORY_PLLINIT_PARAMETERS | ||
| 3512 | |||
| 3513 | #define GPIO_PIN_WRITE 0x01 | ||
| 3514 | #define GPIO_PIN_READ 0x00 | ||
| 3515 | |||
| 3516 | typedef struct _GPIO_PIN_CONTROL_PARAMETERS { | ||
| 3517 | UCHAR ucGPIO_ID; /* return value, read from GPIO pins */ | ||
| 3518 | UCHAR ucGPIOBitShift; /* define which bit in uGPIOBitVal need to be update */ | ||
| 3519 | UCHAR ucGPIOBitVal; /* Set/Reset corresponding bit defined in ucGPIOBitMask */ | ||
| 3520 | UCHAR ucAction; /* =GPIO_PIN_WRITE: Read; =GPIO_PIN_READ: Write */ | ||
| 3521 | } GPIO_PIN_CONTROL_PARAMETERS; | ||
| 3522 | |||
| 3523 | typedef struct _ENABLE_SCALER_PARAMETERS { | ||
| 3524 | UCHAR ucScaler; /* ATOM_SCALER1, ATOM_SCALER2 */ | ||
| 3525 | UCHAR ucEnable; /* ATOM_SCALER_DISABLE or ATOM_SCALER_CENTER or ATOM_SCALER_EXPANSION */ | ||
| 3526 | UCHAR ucTVStandard; /* */ | ||
| 3527 | UCHAR ucPadding[1]; | ||
| 3528 | } ENABLE_SCALER_PARAMETERS; | ||
| 3529 | #define ENABLE_SCALER_PS_ALLOCATION ENABLE_SCALER_PARAMETERS | ||
| 3530 | |||
| 3531 | /* ucEnable: */ | ||
| 3532 | #define SCALER_BYPASS_AUTO_CENTER_NO_REPLICATION 0 | ||
| 3533 | #define SCALER_BYPASS_AUTO_CENTER_AUTO_REPLICATION 1 | ||
| 3534 | #define SCALER_ENABLE_2TAP_ALPHA_MODE 2 | ||
| 3535 | #define SCALER_ENABLE_MULTITAP_MODE 3 | ||
| 3536 | |||
| 3537 | typedef struct _ENABLE_HARDWARE_ICON_CURSOR_PARAMETERS { | ||
| 3538 | ULONG usHWIconHorzVertPosn; /* Hardware Icon Vertical position */ | ||
| 3539 | UCHAR ucHWIconVertOffset; /* Hardware Icon Vertical offset */ | ||
| 3540 | UCHAR ucHWIconHorzOffset; /* Hardware Icon Horizontal offset */ | ||
| 3541 | UCHAR ucSelection; /* ATOM_CURSOR1 or ATOM_ICON1 or ATOM_CURSOR2 or ATOM_ICON2 */ | ||
| 3542 | UCHAR ucEnable; /* ATOM_ENABLE or ATOM_DISABLE */ | ||
| 3543 | } ENABLE_HARDWARE_ICON_CURSOR_PARAMETERS; | ||
| 3544 | |||
| 3545 | typedef struct _ENABLE_HARDWARE_ICON_CURSOR_PS_ALLOCATION { | ||
| 3546 | ENABLE_HARDWARE_ICON_CURSOR_PARAMETERS sEnableIcon; | ||
| 3547 | ENABLE_CRTC_PARAMETERS sReserved; | ||
| 3548 | } ENABLE_HARDWARE_ICON_CURSOR_PS_ALLOCATION; | ||
| 3549 | |||
| 3550 | typedef struct _ENABLE_GRAPH_SURFACE_PARAMETERS { | ||
| 3551 | USHORT usHight; /* Image Hight */ | ||
| 3552 | USHORT usWidth; /* Image Width */ | ||
| 3553 | UCHAR ucSurface; /* Surface 1 or 2 */ | ||
| 3554 | UCHAR ucPadding[3]; | ||
| 3555 | } ENABLE_GRAPH_SURFACE_PARAMETERS; | ||
| 3556 | |||
| 3557 | typedef struct _ENABLE_GRAPH_SURFACE_PARAMETERS_V1_2 { | ||
| 3558 | USHORT usHight; /* Image Hight */ | ||
| 3559 | USHORT usWidth; /* Image Width */ | ||
| 3560 | UCHAR ucSurface; /* Surface 1 or 2 */ | ||
| 3561 | UCHAR ucEnable; /* ATOM_ENABLE or ATOM_DISABLE */ | ||
| 3562 | UCHAR ucPadding[2]; | ||
| 3563 | } ENABLE_GRAPH_SURFACE_PARAMETERS_V1_2; | ||
| 3564 | |||
| 3565 | typedef struct _ENABLE_GRAPH_SURFACE_PS_ALLOCATION { | ||
| 3566 | ENABLE_GRAPH_SURFACE_PARAMETERS sSetSurface; | ||
| 3567 | ENABLE_YUV_PS_ALLOCATION sReserved; /* Don't set this one */ | ||
| 3568 | } ENABLE_GRAPH_SURFACE_PS_ALLOCATION; | ||
| 3569 | |||
| 3570 | typedef struct _MEMORY_CLEAN_UP_PARAMETERS { | ||
| 3571 | USHORT usMemoryStart; /* in 8Kb boundry, offset from memory base address */ | ||
| 3572 | USHORT usMemorySize; /* 8Kb blocks aligned */ | ||
| 3573 | } MEMORY_CLEAN_UP_PARAMETERS; | ||
| 3574 | #define MEMORY_CLEAN_UP_PS_ALLOCATION MEMORY_CLEAN_UP_PARAMETERS | ||
| 3575 | |||
| 3576 | typedef struct _GET_DISPLAY_SURFACE_SIZE_PARAMETERS { | ||
| 3577 | USHORT usX_Size; /* When use as input parameter, usX_Size indicates which CRTC */ | ||
| 3578 | USHORT usY_Size; | ||
| 3579 | } GET_DISPLAY_SURFACE_SIZE_PARAMETERS; | ||
| 3580 | |||
| 3581 | typedef struct _INDIRECT_IO_ACCESS { | ||
| 3582 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 3583 | UCHAR IOAccessSequence[256]; | ||
| 3584 | } INDIRECT_IO_ACCESS; | ||
| 3585 | |||
| 3586 | #define INDIRECT_READ 0x00 | ||
| 3587 | #define INDIRECT_WRITE 0x80 | ||
| 3588 | |||
| 3589 | #define INDIRECT_IO_MM 0 | ||
| 3590 | #define INDIRECT_IO_PLL 1 | ||
| 3591 | #define INDIRECT_IO_MC 2 | ||
| 3592 | #define INDIRECT_IO_PCIE 3 | ||
| 3593 | #define INDIRECT_IO_PCIEP 4 | ||
| 3594 | #define INDIRECT_IO_NBMISC 5 | ||
| 3595 | |||
| 3596 | #define INDIRECT_IO_PLL_READ INDIRECT_IO_PLL | INDIRECT_READ | ||
| 3597 | #define INDIRECT_IO_PLL_WRITE INDIRECT_IO_PLL | INDIRECT_WRITE | ||
| 3598 | #define INDIRECT_IO_MC_READ INDIRECT_IO_MC | INDIRECT_READ | ||
| 3599 | #define INDIRECT_IO_MC_WRITE INDIRECT_IO_MC | INDIRECT_WRITE | ||
| 3600 | #define INDIRECT_IO_PCIE_READ INDIRECT_IO_PCIE | INDIRECT_READ | ||
| 3601 | #define INDIRECT_IO_PCIE_WRITE INDIRECT_IO_PCIE | INDIRECT_WRITE | ||
| 3602 | #define INDIRECT_IO_PCIEP_READ INDIRECT_IO_PCIEP | INDIRECT_READ | ||
| 3603 | #define INDIRECT_IO_PCIEP_WRITE INDIRECT_IO_PCIEP | INDIRECT_WRITE | ||
| 3604 | #define INDIRECT_IO_NBMISC_READ INDIRECT_IO_NBMISC | INDIRECT_READ | ||
| 3605 | #define INDIRECT_IO_NBMISC_WRITE INDIRECT_IO_NBMISC | INDIRECT_WRITE | ||
| 3606 | |||
| 3607 | typedef struct _ATOM_OEM_INFO { | ||
| 3608 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 3609 | ATOM_I2C_ID_CONFIG_ACCESS sucI2cId; | ||
| 3610 | } ATOM_OEM_INFO; | ||
| 3611 | |||
| 3612 | typedef struct _ATOM_TV_MODE { | ||
| 3613 | UCHAR ucVMode_Num; /* Video mode number */ | ||
| 3614 | UCHAR ucTV_Mode_Num; /* Internal TV mode number */ | ||
| 3615 | } ATOM_TV_MODE; | ||
| 3616 | |||
| 3617 | typedef struct _ATOM_BIOS_INT_TVSTD_MODE { | ||
| 3618 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 3619 | USHORT usTV_Mode_LUT_Offset; /* Pointer to standard to internal number conversion table */ | ||
| 3620 | USHORT usTV_FIFO_Offset; /* Pointer to FIFO entry table */ | ||
| 3621 | USHORT usNTSC_Tbl_Offset; /* Pointer to SDTV_Mode_NTSC table */ | ||
| 3622 | USHORT usPAL_Tbl_Offset; /* Pointer to SDTV_Mode_PAL table */ | ||
| 3623 | USHORT usCV_Tbl_Offset; /* Pointer to SDTV_Mode_PAL table */ | ||
| 3624 | } ATOM_BIOS_INT_TVSTD_MODE; | ||
| 3625 | |||
| 3626 | typedef struct _ATOM_TV_MODE_SCALER_PTR { | ||
| 3627 | USHORT ucFilter0_Offset; /* Pointer to filter format 0 coefficients */ | ||
| 3628 | USHORT usFilter1_Offset; /* Pointer to filter format 0 coefficients */ | ||
| 3629 | UCHAR ucTV_Mode_Num; | ||
| 3630 | } ATOM_TV_MODE_SCALER_PTR; | ||
| 3631 | |||
| 3632 | typedef struct _ATOM_STANDARD_VESA_TIMING { | ||
| 3633 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 3634 | ATOM_DTD_FORMAT aModeTimings[16]; /* 16 is not the real array number, just for initial allocation */ | ||
| 3635 | } ATOM_STANDARD_VESA_TIMING; | ||
| 3636 | |||
| 3637 | typedef struct _ATOM_STD_FORMAT { | ||
| 3638 | USHORT usSTD_HDisp; | ||
| 3639 | USHORT usSTD_VDisp; | ||
| 3640 | USHORT usSTD_RefreshRate; | ||
| 3641 | USHORT usReserved; | ||
| 3642 | } ATOM_STD_FORMAT; | ||
| 3643 | |||
| 3644 | typedef struct _ATOM_VESA_TO_EXTENDED_MODE { | ||
| 3645 | USHORT usVESA_ModeNumber; | ||
| 3646 | USHORT usExtendedModeNumber; | ||
| 3647 | } ATOM_VESA_TO_EXTENDED_MODE; | ||
| 3648 | |||
| 3649 | typedef struct _ATOM_VESA_TO_INTENAL_MODE_LUT { | ||
| 3650 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 3651 | ATOM_VESA_TO_EXTENDED_MODE asVESA_ToExtendedModeInfo[76]; | ||
| 3652 | } ATOM_VESA_TO_INTENAL_MODE_LUT; | ||
| 3653 | |||
| 3654 | /*************** ATOM Memory Related Data Structure ***********************/ | ||
| 3655 | typedef struct _ATOM_MEMORY_VENDOR_BLOCK { | ||
| 3656 | UCHAR ucMemoryType; | ||
| 3657 | UCHAR ucMemoryVendor; | ||
| 3658 | UCHAR ucAdjMCId; | ||
| 3659 | UCHAR ucDynClkId; | ||
| 3660 | ULONG ulDllResetClkRange; | ||
| 3661 | } ATOM_MEMORY_VENDOR_BLOCK; | ||
| 3662 | |||
| 3663 | typedef struct _ATOM_MEMORY_SETTING_ID_CONFIG { | ||
| 3664 | #if ATOM_BIG_ENDIAN | ||
| 3665 | ULONG ucMemBlkId:8; | ||
| 3666 | ULONG ulMemClockRange:24; | ||
| 3667 | #else | ||
| 3668 | ULONG ulMemClockRange:24; | ||
| 3669 | ULONG ucMemBlkId:8; | ||
| 3670 | #endif | ||
| 3671 | } ATOM_MEMORY_SETTING_ID_CONFIG; | ||
| 3672 | |||
| 3673 | typedef union _ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS { | ||
| 3674 | ATOM_MEMORY_SETTING_ID_CONFIG slAccess; | ||
| 3675 | ULONG ulAccess; | ||
| 3676 | } ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS; | ||
| 3677 | |||
| 3678 | typedef struct _ATOM_MEMORY_SETTING_DATA_BLOCK { | ||
| 3679 | ATOM_MEMORY_SETTING_ID_CONFIG_ACCESS ulMemoryID; | ||
| 3680 | ULONG aulMemData[1]; | ||
| 3681 | } ATOM_MEMORY_SETTING_DATA_BLOCK; | ||
| 3682 | |||
| 3683 | typedef struct _ATOM_INIT_REG_INDEX_FORMAT { | ||
| 3684 | USHORT usRegIndex; /* MC register index */ | ||
| 3685 | UCHAR ucPreRegDataLength; /* offset in ATOM_INIT_REG_DATA_BLOCK.saRegDataBuf */ | ||
| 3686 | } ATOM_INIT_REG_INDEX_FORMAT; | ||
| 3687 | |||
| 3688 | typedef struct _ATOM_INIT_REG_BLOCK { | ||
| 3689 | USHORT usRegIndexTblSize; /* size of asRegIndexBuf */ | ||
| 3690 | USHORT usRegDataBlkSize; /* size of ATOM_MEMORY_SETTING_DATA_BLOCK */ | ||
| 3691 | ATOM_INIT_REG_INDEX_FORMAT asRegIndexBuf[1]; | ||
| 3692 | ATOM_MEMORY_SETTING_DATA_BLOCK asRegDataBuf[1]; | ||
| 3693 | } ATOM_INIT_REG_BLOCK; | ||
| 3694 | |||
| 3695 | #define END_OF_REG_INDEX_BLOCK 0x0ffff | ||
| 3696 | #define END_OF_REG_DATA_BLOCK 0x00000000 | ||
| 3697 | #define ATOM_INIT_REG_MASK_FLAG 0x80 | ||
| 3698 | #define CLOCK_RANGE_HIGHEST 0x00ffffff | ||
| 3699 | |||
| 3700 | #define VALUE_DWORD SIZEOF ULONG | ||
| 3701 | #define VALUE_SAME_AS_ABOVE 0 | ||
| 3702 | #define VALUE_MASK_DWORD 0x84 | ||
| 3703 | |||
| 3704 | #define INDEX_ACCESS_RANGE_BEGIN (VALUE_DWORD + 1) | ||
| 3705 | #define INDEX_ACCESS_RANGE_END (INDEX_ACCESS_RANGE_BEGIN + 1) | ||
| 3706 | #define VALUE_INDEX_ACCESS_SINGLE (INDEX_ACCESS_RANGE_END + 1) | ||
| 3707 | |||
| 3708 | typedef struct _ATOM_MC_INIT_PARAM_TABLE { | ||
| 3709 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 3710 | USHORT usAdjustARB_SEQDataOffset; | ||
| 3711 | USHORT usMCInitMemTypeTblOffset; | ||
| 3712 | USHORT usMCInitCommonTblOffset; | ||
| 3713 | USHORT usMCInitPowerDownTblOffset; | ||
| 3714 | ULONG ulARB_SEQDataBuf[32]; | ||
| 3715 | ATOM_INIT_REG_BLOCK asMCInitMemType; | ||
| 3716 | ATOM_INIT_REG_BLOCK asMCInitCommon; | ||
| 3717 | } ATOM_MC_INIT_PARAM_TABLE; | ||
| 3718 | |||
| 3719 | #define _4Mx16 0x2 | ||
| 3720 | #define _4Mx32 0x3 | ||
| 3721 | #define _8Mx16 0x12 | ||
| 3722 | #define _8Mx32 0x13 | ||
| 3723 | #define _16Mx16 0x22 | ||
| 3724 | #define _16Mx32 0x23 | ||
| 3725 | #define _32Mx16 0x32 | ||
| 3726 | #define _32Mx32 0x33 | ||
| 3727 | #define _64Mx8 0x41 | ||
| 3728 | #define _64Mx16 0x42 | ||
| 3729 | |||
| 3730 | #define SAMSUNG 0x1 | ||
| 3731 | #define INFINEON 0x2 | ||
| 3732 | #define ELPIDA 0x3 | ||
| 3733 | #define ETRON 0x4 | ||
| 3734 | #define NANYA 0x5 | ||
| 3735 | #define HYNIX 0x6 | ||
| 3736 | #define MOSEL 0x7 | ||
| 3737 | #define WINBOND 0x8 | ||
| 3738 | #define ESMT 0x9 | ||
| 3739 | #define MICRON 0xF | ||
| 3740 | |||
| 3741 | #define QIMONDA INFINEON | ||
| 3742 | #define PROMOS MOSEL | ||
| 3743 | |||
| 3744 | /* ///////////Support for GDDR5 MC uCode to reside in upper 64K of ROM///////////// */ | ||
| 3745 | |||
| 3746 | #define UCODE_ROM_START_ADDRESS 0x1c000 | ||
| 3747 | #define UCODE_SIGNATURE 0x4375434d /* 'MCuC' - MC uCode */ | ||
| 3748 | |||
| 3749 | /* uCode block header for reference */ | ||
| 3750 | |||
| 3751 | typedef struct _MCuCodeHeader { | ||
| 3752 | ULONG ulSignature; | ||
| 3753 | UCHAR ucRevision; | ||
| 3754 | UCHAR ucChecksum; | ||
| 3755 | UCHAR ucReserved1; | ||
| 3756 | UCHAR ucReserved2; | ||
| 3757 | USHORT usParametersLength; | ||
| 3758 | USHORT usUCodeLength; | ||
| 3759 | USHORT usReserved1; | ||
| 3760 | USHORT usReserved2; | ||
| 3761 | } MCuCodeHeader; | ||
| 3762 | |||
| 3763 | /* //////////////////////////////////////////////////////////////////////////////// */ | ||
| 3764 | |||
| 3765 | #define ATOM_MAX_NUMBER_OF_VRAM_MODULE 16 | ||
| 3766 | |||
| 3767 | #define ATOM_VRAM_MODULE_MEMORY_VENDOR_ID_MASK 0xF | ||
| 3768 | typedef struct _ATOM_VRAM_MODULE_V1 { | ||
| 3769 | ULONG ulReserved; | ||
| 3770 | USHORT usEMRSValue; | ||
| 3771 | USHORT usMRSValue; | ||
| 3772 | USHORT usReserved; | ||
| 3773 | UCHAR ucExtMemoryID; /* An external indicator (by hardcode, callback or pin) to tell what is the current memory module */ | ||
| 3774 | UCHAR ucMemoryType; /* [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4;[3:0] reserved; */ | ||
| 3775 | UCHAR ucMemoryVenderID; /* Predefined,never change across designs or memory type/vender */ | ||
| 3776 | UCHAR ucMemoryDeviceCfg; /* [7:4]=0x0:4M;=0x1:8M;=0x2:16M;0x3:32M....[3:0]=0x0:x4;=0x1:x8;=0x2:x16;=0x3:x32... */ | ||
| 3777 | UCHAR ucRow; /* Number of Row,in power of 2; */ | ||
| 3778 | UCHAR ucColumn; /* Number of Column,in power of 2; */ | ||
| 3779 | UCHAR ucBank; /* Nunber of Bank; */ | ||
| 3780 | UCHAR ucRank; /* Number of Rank, in power of 2 */ | ||
| 3781 | UCHAR ucChannelNum; /* Number of channel; */ | ||
| 3782 | UCHAR ucChannelConfig; /* [3:0]=Indication of what channel combination;[4:7]=Channel bit width, in number of 2 */ | ||
| 3783 | UCHAR ucDefaultMVDDQ_ID; /* Default MVDDQ setting for this memory block, ID linking to MVDDQ info table to find real set-up data; */ | ||
| 3784 | UCHAR ucDefaultMVDDC_ID; /* Default MVDDC setting for this memory block, ID linking to MVDDC info table to find real set-up data; */ | ||
| 3785 | UCHAR ucReserved[2]; | ||
| 3786 | } ATOM_VRAM_MODULE_V1; | ||
| 3787 | |||
| 3788 | typedef struct _ATOM_VRAM_MODULE_V2 { | ||
| 3789 | ULONG ulReserved; | ||
| 3790 | ULONG ulFlags; /* To enable/disable functionalities based on memory type */ | ||
| 3791 | ULONG ulEngineClock; /* Override of default engine clock for particular memory type */ | ||
| 3792 | ULONG ulMemoryClock; /* Override of default memory clock for particular memory type */ | ||
| 3793 | USHORT usEMRS2Value; /* EMRS2 Value is used for GDDR2 and GDDR4 memory type */ | ||
| 3794 | USHORT usEMRS3Value; /* EMRS3 Value is used for GDDR2 and GDDR4 memory type */ | ||
| 3795 | USHORT usEMRSValue; | ||
| 3796 | USHORT usMRSValue; | ||
| 3797 | USHORT usReserved; | ||
| 3798 | UCHAR ucExtMemoryID; /* An external indicator (by hardcode, callback or pin) to tell what is the current memory module */ | ||
| 3799 | UCHAR ucMemoryType; /* [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4;[3:0] - must not be used for now; */ | ||
| 3800 | UCHAR ucMemoryVenderID; /* Predefined,never change across designs or memory type/vender. If not predefined, vendor detection table gets executed */ | ||
| 3801 | UCHAR ucMemoryDeviceCfg; /* [7:4]=0x0:4M;=0x1:8M;=0x2:16M;0x3:32M....[3:0]=0x0:x4;=0x1:x8;=0x2:x16;=0x3:x32... */ | ||
| 3802 | UCHAR ucRow; /* Number of Row,in power of 2; */ | ||
| 3803 | UCHAR ucColumn; /* Number of Column,in power of 2; */ | ||
| 3804 | UCHAR ucBank; /* Nunber of Bank; */ | ||
| 3805 | UCHAR ucRank; /* Number of Rank, in power of 2 */ | ||
| 3806 | UCHAR ucChannelNum; /* Number of channel; */ | ||
| 3807 | UCHAR ucChannelConfig; /* [3:0]=Indication of what channel combination;[4:7]=Channel bit width, in number of 2 */ | ||
| 3808 | UCHAR ucDefaultMVDDQ_ID; /* Default MVDDQ setting for this memory block, ID linking to MVDDQ info table to find real set-up data; */ | ||
| 3809 | UCHAR ucDefaultMVDDC_ID; /* Default MVDDC setting for this memory block, ID linking to MVDDC info table to find real set-up data; */ | ||
| 3810 | UCHAR ucRefreshRateFactor; | ||
| 3811 | UCHAR ucReserved[3]; | ||
| 3812 | } ATOM_VRAM_MODULE_V2; | ||
| 3813 | |||
| 3814 | typedef struct _ATOM_MEMORY_TIMING_FORMAT { | ||
| 3815 | ULONG ulClkRange; /* memory clock in 10kHz unit, when target memory clock is below this clock, use this memory timing */ | ||
| 3816 | union { | ||
| 3817 | USHORT usMRS; /* mode register */ | ||
| 3818 | USHORT usDDR3_MR0; | ||
| 3819 | }; | ||
| 3820 | union { | ||
| 3821 | USHORT usEMRS; /* extended mode register */ | ||
| 3822 | USHORT usDDR3_MR1; | ||
| 3823 | }; | ||
| 3824 | UCHAR ucCL; /* CAS latency */ | ||
| 3825 | UCHAR ucWL; /* WRITE Latency */ | ||
| 3826 | UCHAR uctRAS; /* tRAS */ | ||
| 3827 | UCHAR uctRC; /* tRC */ | ||
| 3828 | UCHAR uctRFC; /* tRFC */ | ||
| 3829 | UCHAR uctRCDR; /* tRCDR */ | ||
| 3830 | UCHAR uctRCDW; /* tRCDW */ | ||
| 3831 | UCHAR uctRP; /* tRP */ | ||
| 3832 | UCHAR uctRRD; /* tRRD */ | ||
| 3833 | UCHAR uctWR; /* tWR */ | ||
| 3834 | UCHAR uctWTR; /* tWTR */ | ||
| 3835 | UCHAR uctPDIX; /* tPDIX */ | ||
| 3836 | UCHAR uctFAW; /* tFAW */ | ||
| 3837 | UCHAR uctAOND; /* tAOND */ | ||
| 3838 | union { | ||
| 3839 | struct { | ||
| 3840 | UCHAR ucflag; /* flag to control memory timing calculation. bit0= control EMRS2 Infineon */ | ||
| 3841 | UCHAR ucReserved; | ||
| 3842 | }; | ||
| 3843 | USHORT usDDR3_MR2; | ||
| 3844 | }; | ||
| 3845 | } ATOM_MEMORY_TIMING_FORMAT; | ||
| 3846 | |||
| 3847 | typedef struct _ATOM_MEMORY_TIMING_FORMAT_V1 { | ||
| 3848 | ULONG ulClkRange; /* memory clock in 10kHz unit, when target memory clock is below this clock, use this memory timing */ | ||
| 3849 | USHORT usMRS; /* mode register */ | ||
| 3850 | USHORT usEMRS; /* extended mode register */ | ||
| 3851 | UCHAR ucCL; /* CAS latency */ | ||
| 3852 | UCHAR ucWL; /* WRITE Latency */ | ||
| 3853 | UCHAR uctRAS; /* tRAS */ | ||
| 3854 | UCHAR uctRC; /* tRC */ | ||
| 3855 | UCHAR uctRFC; /* tRFC */ | ||
| 3856 | UCHAR uctRCDR; /* tRCDR */ | ||
| 3857 | UCHAR uctRCDW; /* tRCDW */ | ||
| 3858 | UCHAR uctRP; /* tRP */ | ||
| 3859 | UCHAR uctRRD; /* tRRD */ | ||
| 3860 | UCHAR uctWR; /* tWR */ | ||
| 3861 | UCHAR uctWTR; /* tWTR */ | ||
| 3862 | UCHAR uctPDIX; /* tPDIX */ | ||
| 3863 | UCHAR uctFAW; /* tFAW */ | ||
| 3864 | UCHAR uctAOND; /* tAOND */ | ||
| 3865 | UCHAR ucflag; /* flag to control memory timing calculation. bit0= control EMRS2 Infineon */ | ||
| 3866 | /* ///////////////////////GDDR parameters/////////////////////////////////// */ | ||
| 3867 | UCHAR uctCCDL; /* */ | ||
| 3868 | UCHAR uctCRCRL; /* */ | ||
| 3869 | UCHAR uctCRCWL; /* */ | ||
| 3870 | UCHAR uctCKE; /* */ | ||
| 3871 | UCHAR uctCKRSE; /* */ | ||
| 3872 | UCHAR uctCKRSX; /* */ | ||
| 3873 | UCHAR uctFAW32; /* */ | ||
| 3874 | UCHAR ucReserved1; /* */ | ||
| 3875 | UCHAR ucReserved2; /* */ | ||
| 3876 | UCHAR ucTerminator; | ||
| 3877 | } ATOM_MEMORY_TIMING_FORMAT_V1; | ||
| 3878 | |||
| 3879 | typedef struct _ATOM_MEMORY_FORMAT { | ||
| 3880 | ULONG ulDllDisClock; /* memory DLL will be disable when target memory clock is below this clock */ | ||
| 3881 | union { | ||
| 3882 | USHORT usEMRS2Value; /* EMRS2 Value is used for GDDR2 and GDDR4 memory type */ | ||
| 3883 | USHORT usDDR3_Reserved; /* Not used for DDR3 memory */ | ||
| 3884 | }; | ||
| 3885 | union { | ||
| 3886 | USHORT usEMRS3Value; /* EMRS3 Value is used for GDDR2 and GDDR4 memory type */ | ||
| 3887 | USHORT usDDR3_MR3; /* Used for DDR3 memory */ | ||
| 3888 | }; | ||
| 3889 | UCHAR ucMemoryType; /* [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4;[3:0] - must not be used for now; */ | ||
| 3890 | UCHAR ucMemoryVenderID; /* Predefined,never change across designs or memory type/vender. If not predefined, vendor detection table gets executed */ | ||
| 3891 | UCHAR ucRow; /* Number of Row,in power of 2; */ | ||
| 3892 | UCHAR ucColumn; /* Number of Column,in power of 2; */ | ||
| 3893 | UCHAR ucBank; /* Nunber of Bank; */ | ||
| 3894 | UCHAR ucRank; /* Number of Rank, in power of 2 */ | ||
| 3895 | UCHAR ucBurstSize; /* burst size, 0= burst size=4 1= burst size=8 */ | ||
| 3896 | UCHAR ucDllDisBit; /* position of DLL Enable/Disable bit in EMRS ( Extended Mode Register ) */ | ||
| 3897 | UCHAR ucRefreshRateFactor; /* memory refresh rate in unit of ms */ | ||
| 3898 | UCHAR ucDensity; /* _8Mx32, _16Mx32, _16Mx16, _32Mx16 */ | ||
| 3899 | UCHAR ucPreamble; /* [7:4] Write Preamble, [3:0] Read Preamble */ | ||
| 3900 | UCHAR ucMemAttrib; /* Memory Device Addribute, like RDBI/WDBI etc */ | ||
| 3901 | ATOM_MEMORY_TIMING_FORMAT asMemTiming[5]; /* Memory Timing block sort from lower clock to higher clock */ | ||
| 3902 | } ATOM_MEMORY_FORMAT; | ||
| 3903 | |||
| 3904 | typedef struct _ATOM_VRAM_MODULE_V3 { | ||
| 3905 | ULONG ulChannelMapCfg; /* board dependent paramenter:Channel combination */ | ||
| 3906 | USHORT usSize; /* size of ATOM_VRAM_MODULE_V3 */ | ||
| 3907 | USHORT usDefaultMVDDQ; /* board dependent parameter:Default Memory Core Voltage */ | ||
| 3908 | USHORT usDefaultMVDDC; /* board dependent parameter:Default Memory IO Voltage */ | ||
| 3909 | UCHAR ucExtMemoryID; /* An external indicator (by hardcode, callback or pin) to tell what is the current memory module */ | ||
| 3910 | UCHAR ucChannelNum; /* board dependent parameter:Number of channel; */ | ||
| 3911 | UCHAR ucChannelSize; /* board dependent parameter:32bit or 64bit */ | ||
| 3912 | UCHAR ucVREFI; /* board dependnt parameter: EXT or INT +160mv to -140mv */ | ||
| 3913 | UCHAR ucNPL_RT; /* board dependent parameter:NPL round trip delay, used for calculate memory timing parameters */ | ||
| 3914 | UCHAR ucFlag; /* To enable/disable functionalities based on memory type */ | ||
| 3915 | ATOM_MEMORY_FORMAT asMemory; /* describ all of video memory parameters from memory spec */ | ||
| 3916 | } ATOM_VRAM_MODULE_V3; | ||
| 3917 | |||
| 3918 | /* ATOM_VRAM_MODULE_V3.ucNPL_RT */ | ||
| 3919 | #define NPL_RT_MASK 0x0f | ||
| 3920 | #define BATTERY_ODT_MASK 0xc0 | ||
| 3921 | |||
| 3922 | #define ATOM_VRAM_MODULE ATOM_VRAM_MODULE_V3 | ||
| 3923 | |||
| 3924 | typedef struct _ATOM_VRAM_MODULE_V4 { | ||
| 3925 | ULONG ulChannelMapCfg; /* board dependent parameter: Channel combination */ | ||
| 3926 | USHORT usModuleSize; /* size of ATOM_VRAM_MODULE_V4, make it easy for VBIOS to look for next entry of VRAM_MODULE */ | ||
| 3927 | USHORT usPrivateReserved; /* BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! */ | ||
| 3928 | /* MC_ARB_RAMCFG (includes NOOFBANK,NOOFRANKS,NOOFROWS,NOOFCOLS) */ | ||
| 3929 | USHORT usReserved; | ||
| 3930 | UCHAR ucExtMemoryID; /* An external indicator (by hardcode, callback or pin) to tell what is the current memory module */ | ||
| 3931 | UCHAR ucMemoryType; /* [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4; 0x5:DDR5 [3:0] - Must be 0x0 for now; */ | ||
| 3932 | UCHAR ucChannelNum; /* Number of channels present in this module config */ | ||
| 3933 | UCHAR ucChannelWidth; /* 0 - 32 bits; 1 - 64 bits */ | ||
| 3934 | UCHAR ucDensity; /* _8Mx32, _16Mx32, _16Mx16, _32Mx16 */ | ||
| 3935 | UCHAR ucFlag; /* To enable/disable functionalities based on memory type */ | ||
| 3936 | UCHAR ucMisc; /* bit0: 0 - single rank; 1 - dual rank; bit2: 0 - burstlength 4, 1 - burstlength 8 */ | ||
| 3937 | UCHAR ucVREFI; /* board dependent parameter */ | ||
| 3938 | UCHAR ucNPL_RT; /* board dependent parameter:NPL round trip delay, used for calculate memory timing parameters */ | ||
| 3939 | UCHAR ucPreamble; /* [7:4] Write Preamble, [3:0] Read Preamble */ | ||
| 3940 | UCHAR ucMemorySize; /* BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! */ | ||
| 3941 | /* Total memory size in unit of 16MB for CONFIG_MEMSIZE - bit[23:0] zeros */ | ||
| 3942 | UCHAR ucReserved[3]; | ||
| 3943 | |||
| 3944 | /* compare with V3, we flat the struct by merging ATOM_MEMORY_FORMAT (as is) into V4 as the same level */ | ||
| 3945 | union { | ||
| 3946 | USHORT usEMRS2Value; /* EMRS2 Value is used for GDDR2 and GDDR4 memory type */ | ||
| 3947 | USHORT usDDR3_Reserved; | ||
| 3948 | }; | ||
| 3949 | union { | ||
| 3950 | USHORT usEMRS3Value; /* EMRS3 Value is used for GDDR2 and GDDR4 memory type */ | ||
| 3951 | USHORT usDDR3_MR3; /* Used for DDR3 memory */ | ||
| 3952 | }; | ||
| 3953 | UCHAR ucMemoryVenderID; /* Predefined, If not predefined, vendor detection table gets executed */ | ||
| 3954 | UCHAR ucRefreshRateFactor; /* [1:0]=RefreshFactor (00=8ms, 01=16ms, 10=32ms,11=64ms) */ | ||
| 3955 | UCHAR ucReserved2[2]; | ||
| 3956 | ATOM_MEMORY_TIMING_FORMAT asMemTiming[5]; /* Memory Timing block sort from lower clock to higher clock */ | ||
| 3957 | } ATOM_VRAM_MODULE_V4; | ||
| 3958 | |||
| 3959 | #define VRAM_MODULE_V4_MISC_RANK_MASK 0x3 | ||
| 3960 | #define VRAM_MODULE_V4_MISC_DUAL_RANK 0x1 | ||
| 3961 | #define VRAM_MODULE_V4_MISC_BL_MASK 0x4 | ||
| 3962 | #define VRAM_MODULE_V4_MISC_BL8 0x4 | ||
| 3963 | #define VRAM_MODULE_V4_MISC_DUAL_CS 0x10 | ||
| 3964 | |||
| 3965 | typedef struct _ATOM_VRAM_MODULE_V5 { | ||
| 3966 | ULONG ulChannelMapCfg; /* board dependent parameter: Channel combination */ | ||
| 3967 | USHORT usModuleSize; /* size of ATOM_VRAM_MODULE_V4, make it easy for VBIOS to look for next entry of VRAM_MODULE */ | ||
| 3968 | USHORT usPrivateReserved; /* BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! */ | ||
| 3969 | /* MC_ARB_RAMCFG (includes NOOFBANK,NOOFRANKS,NOOFROWS,NOOFCOLS) */ | ||
| 3970 | USHORT usReserved; | ||
| 3971 | UCHAR ucExtMemoryID; /* An external indicator (by hardcode, callback or pin) to tell what is the current memory module */ | ||
| 3972 | UCHAR ucMemoryType; /* [7:4]=0x1:DDR1;=0x2:DDR2;=0x3:DDR3;=0x4:DDR4; 0x5:DDR5 [3:0] - Must be 0x0 for now; */ | ||
| 3973 | UCHAR ucChannelNum; /* Number of channels present in this module config */ | ||
| 3974 | UCHAR ucChannelWidth; /* 0 - 32 bits; 1 - 64 bits */ | ||
| 3975 | UCHAR ucDensity; /* _8Mx32, _16Mx32, _16Mx16, _32Mx16 */ | ||
| 3976 | UCHAR ucFlag; /* To enable/disable functionalities based on memory type */ | ||
| 3977 | UCHAR ucMisc; /* bit0: 0 - single rank; 1 - dual rank; bit2: 0 - burstlength 4, 1 - burstlength 8 */ | ||
| 3978 | UCHAR ucVREFI; /* board dependent parameter */ | ||
| 3979 | UCHAR ucNPL_RT; /* board dependent parameter:NPL round trip delay, used for calculate memory timing parameters */ | ||
| 3980 | UCHAR ucPreamble; /* [7:4] Write Preamble, [3:0] Read Preamble */ | ||
| 3981 | UCHAR ucMemorySize; /* BIOS internal reserved space to optimize code size, updated by the compiler, shouldn't be modified manually!! */ | ||
| 3982 | /* Total memory size in unit of 16MB for CONFIG_MEMSIZE - bit[23:0] zeros */ | ||
| 3983 | UCHAR ucReserved[3]; | ||
| 3984 | |||
| 3985 | /* compare with V3, we flat the struct by merging ATOM_MEMORY_FORMAT (as is) into V4 as the same level */ | ||
| 3986 | USHORT usEMRS2Value; /* EMRS2 Value is used for GDDR2 and GDDR4 memory type */ | ||
| 3987 | USHORT usEMRS3Value; /* EMRS3 Value is used for GDDR2 and GDDR4 memory type */ | ||
| 3988 | UCHAR ucMemoryVenderID; /* Predefined, If not predefined, vendor detection table gets executed */ | ||
| 3989 | UCHAR ucRefreshRateFactor; /* [1:0]=RefreshFactor (00=8ms, 01=16ms, 10=32ms,11=64ms) */ | ||
| 3990 | UCHAR ucFIFODepth; /* FIFO depth supposes to be detected during vendor detection, but if we dont do vendor detection we have to hardcode FIFO Depth */ | ||
| 3991 | UCHAR ucCDR_Bandwidth; /* [0:3]=Read CDR bandwidth, [4:7] - Write CDR Bandwidth */ | ||
| 3992 | ATOM_MEMORY_TIMING_FORMAT_V1 asMemTiming[5]; /* Memory Timing block sort from lower clock to higher clock */ | ||
| 3993 | } ATOM_VRAM_MODULE_V5; | ||
| 3994 | |||
| 3995 | typedef struct _ATOM_VRAM_INFO_V2 { | ||
| 3996 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 3997 | UCHAR ucNumOfVRAMModule; | ||
| 3998 | ATOM_VRAM_MODULE aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE]; /* just for allocation, real number of blocks is in ucNumOfVRAMModule; */ | ||
| 3999 | } ATOM_VRAM_INFO_V2; | ||
| 4000 | |||
| 4001 | typedef struct _ATOM_VRAM_INFO_V3 { | ||
| 4002 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 4003 | USHORT usMemAdjustTblOffset; /* offset of ATOM_INIT_REG_BLOCK structure for memory vendor specific MC adjust setting */ | ||
| 4004 | USHORT usMemClkPatchTblOffset; /* offset of ATOM_INIT_REG_BLOCK structure for memory clock specific MC setting */ | ||
| 4005 | USHORT usRerseved; | ||
| 4006 | UCHAR aVID_PinsShift[9]; /* 8 bit strap maximum+terminator */ | ||
| 4007 | UCHAR ucNumOfVRAMModule; | ||
| 4008 | ATOM_VRAM_MODULE aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE]; /* just for allocation, real number of blocks is in ucNumOfVRAMModule; */ | ||
| 4009 | ATOM_INIT_REG_BLOCK asMemPatch; /* for allocation */ | ||
| 4010 | /* ATOM_INIT_REG_BLOCK aMemAdjust; */ | ||
| 4011 | } ATOM_VRAM_INFO_V3; | ||
| 4012 | |||
| 4013 | #define ATOM_VRAM_INFO_LAST ATOM_VRAM_INFO_V3 | ||
| 4014 | |||
| 4015 | typedef struct _ATOM_VRAM_INFO_V4 { | ||
| 4016 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 4017 | USHORT usMemAdjustTblOffset; /* offset of ATOM_INIT_REG_BLOCK structure for memory vendor specific MC adjust setting */ | ||
| 4018 | USHORT usMemClkPatchTblOffset; /* offset of ATOM_INIT_REG_BLOCK structure for memory clock specific MC setting */ | ||
| 4019 | USHORT usRerseved; | ||
| 4020 | UCHAR ucMemDQ7_0ByteRemap; /* DQ line byte remap, =0: Memory Data line BYTE0, =1: BYTE1, =2: BYTE2, =3: BYTE3 */ | ||
| 4021 | ULONG ulMemDQ7_0BitRemap; /* each DQ line ( 7~0) use 3bits, like: DQ0=Bit[2:0], DQ1:[5:3], ... DQ7:[23:21] */ | ||
| 4022 | UCHAR ucReservde[4]; | ||
| 4023 | UCHAR ucNumOfVRAMModule; | ||
| 4024 | ATOM_VRAM_MODULE_V4 aVramInfo[ATOM_MAX_NUMBER_OF_VRAM_MODULE]; /* just for allocation, real number of blocks is in ucNumOfVRAMModule; */ | ||
| 4025 | ATOM_INIT_REG_BLOCK asMemPatch; /* for allocation */ | ||
| 4026 | /* ATOM_INIT_REG_BLOCK aMemAdjust; */ | ||
| 4027 | } ATOM_VRAM_INFO_V4; | ||
| 4028 | |||
| 4029 | typedef struct _ATOM_VRAM_GPIO_DETECTION_INFO { | ||
| 4030 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 4031 | UCHAR aVID_PinsShift[9]; /* 8 bit strap maximum+terminator */ | ||
| 4032 | } ATOM_VRAM_GPIO_DETECTION_INFO; | ||
| 4033 | |||
| 4034 | typedef struct _ATOM_MEMORY_TRAINING_INFO { | ||
| 4035 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 4036 | UCHAR ucTrainingLoop; | ||
| 4037 | UCHAR ucReserved[3]; | ||
| 4038 | ATOM_INIT_REG_BLOCK asMemTrainingSetting; | ||
| 4039 | } ATOM_MEMORY_TRAINING_INFO; | ||
| 4040 | |||
| 4041 | typedef struct SW_I2C_CNTL_DATA_PARAMETERS { | ||
| 4042 | UCHAR ucControl; | ||
| 4043 | UCHAR ucData; | ||
| 4044 | UCHAR ucSatus; | ||
| 4045 | UCHAR ucTemp; | ||
| 4046 | } SW_I2C_CNTL_DATA_PARAMETERS; | ||
| 4047 | |||
| 4048 | #define SW_I2C_CNTL_DATA_PS_ALLOCATION SW_I2C_CNTL_DATA_PARAMETERS | ||
| 4049 | |||
| 4050 | typedef struct _SW_I2C_IO_DATA_PARAMETERS { | ||
| 4051 | USHORT GPIO_Info; | ||
| 4052 | UCHAR ucAct; | ||
| 4053 | UCHAR ucData; | ||
| 4054 | } SW_I2C_IO_DATA_PARAMETERS; | ||
| 4055 | |||
| 4056 | #define SW_I2C_IO_DATA_PS_ALLOCATION SW_I2C_IO_DATA_PARAMETERS | ||
| 4057 | |||
| 4058 | /****************************SW I2C CNTL DEFINITIONS**********************/ | ||
| 4059 | #define SW_I2C_IO_RESET 0 | ||
| 4060 | #define SW_I2C_IO_GET 1 | ||
| 4061 | #define SW_I2C_IO_DRIVE 2 | ||
| 4062 | #define SW_I2C_IO_SET 3 | ||
| 4063 | #define SW_I2C_IO_START 4 | ||
| 4064 | |||
| 4065 | #define SW_I2C_IO_CLOCK 0 | ||
| 4066 | #define SW_I2C_IO_DATA 0x80 | ||
| 4067 | |||
| 4068 | #define SW_I2C_IO_ZERO 0 | ||
| 4069 | #define SW_I2C_IO_ONE 0x100 | ||
| 4070 | |||
| 4071 | #define SW_I2C_CNTL_READ 0 | ||
| 4072 | #define SW_I2C_CNTL_WRITE 1 | ||
| 4073 | #define SW_I2C_CNTL_START 2 | ||
| 4074 | #define SW_I2C_CNTL_STOP 3 | ||
| 4075 | #define SW_I2C_CNTL_OPEN 4 | ||
| 4076 | #define SW_I2C_CNTL_CLOSE 5 | ||
| 4077 | #define SW_I2C_CNTL_WRITE1BIT 6 | ||
| 4078 | |||
| 4079 | /* ==============================VESA definition Portion=============================== */ | ||
| 4080 | #define VESA_OEM_PRODUCT_REV '01.00' | ||
| 4081 | #define VESA_MODE_ATTRIBUTE_MODE_SUPPORT 0xBB /* refer to VBE spec p.32, no TTY support */ | ||
| 4082 | #define VESA_MODE_WIN_ATTRIBUTE 7 | ||
| 4083 | #define VESA_WIN_SIZE 64 | ||
| 4084 | |||
| 4085 | typedef struct _PTR_32_BIT_STRUCTURE { | ||
| 4086 | USHORT Offset16; | ||
| 4087 | USHORT Segment16; | ||
| 4088 | } PTR_32_BIT_STRUCTURE; | ||
| 4089 | |||
| 4090 | typedef union _PTR_32_BIT_UNION { | ||
| 4091 | PTR_32_BIT_STRUCTURE SegmentOffset; | ||
| 4092 | ULONG Ptr32_Bit; | ||
| 4093 | } PTR_32_BIT_UNION; | ||
| 4094 | |||
| 4095 | typedef struct _VBE_1_2_INFO_BLOCK_UPDATABLE { | ||
| 4096 | UCHAR VbeSignature[4]; | ||
| 4097 | USHORT VbeVersion; | ||
| 4098 | PTR_32_BIT_UNION OemStringPtr; | ||
| 4099 | UCHAR Capabilities[4]; | ||
| 4100 | PTR_32_BIT_UNION VideoModePtr; | ||
| 4101 | USHORT TotalMemory; | ||
| 4102 | } VBE_1_2_INFO_BLOCK_UPDATABLE; | ||
| 4103 | |||
| 4104 | typedef struct _VBE_2_0_INFO_BLOCK_UPDATABLE { | ||
| 4105 | VBE_1_2_INFO_BLOCK_UPDATABLE CommonBlock; | ||
| 4106 | USHORT OemSoftRev; | ||
| 4107 | PTR_32_BIT_UNION OemVendorNamePtr; | ||
| 4108 | PTR_32_BIT_UNION OemProductNamePtr; | ||
| 4109 | PTR_32_BIT_UNION OemProductRevPtr; | ||
| 4110 | } VBE_2_0_INFO_BLOCK_UPDATABLE; | ||
| 4111 | |||
| 4112 | typedef union _VBE_VERSION_UNION { | ||
| 4113 | VBE_2_0_INFO_BLOCK_UPDATABLE VBE_2_0_InfoBlock; | ||
| 4114 | VBE_1_2_INFO_BLOCK_UPDATABLE VBE_1_2_InfoBlock; | ||
| 4115 | } VBE_VERSION_UNION; | ||
| 4116 | |||
| 4117 | typedef struct _VBE_INFO_BLOCK { | ||
| 4118 | VBE_VERSION_UNION UpdatableVBE_Info; | ||
| 4119 | UCHAR Reserved[222]; | ||
| 4120 | UCHAR OemData[256]; | ||
| 4121 | } VBE_INFO_BLOCK; | ||
| 4122 | |||
| 4123 | typedef struct _VBE_FP_INFO { | ||
| 4124 | USHORT HSize; | ||
| 4125 | USHORT VSize; | ||
| 4126 | USHORT FPType; | ||
| 4127 | UCHAR RedBPP; | ||
| 4128 | UCHAR GreenBPP; | ||
| 4129 | UCHAR BlueBPP; | ||
| 4130 | UCHAR ReservedBPP; | ||
| 4131 | ULONG RsvdOffScrnMemSize; | ||
| 4132 | ULONG RsvdOffScrnMEmPtr; | ||
| 4133 | UCHAR Reserved[14]; | ||
| 4134 | } VBE_FP_INFO; | ||
| 4135 | |||
| 4136 | typedef struct _VESA_MODE_INFO_BLOCK { | ||
| 4137 | /* Mandatory information for all VBE revisions */ | ||
| 4138 | USHORT ModeAttributes; /* dw ? ; mode attributes */ | ||
| 4139 | UCHAR WinAAttributes; /* db ? ; window A attributes */ | ||
| 4140 | UCHAR WinBAttributes; /* db ? ; window B attributes */ | ||
| 4141 | USHORT WinGranularity; /* dw ? ; window granularity */ | ||
| 4142 | USHORT WinSize; /* dw ? ; window size */ | ||
| 4143 | USHORT WinASegment; /* dw ? ; window A start segment */ | ||
| 4144 | USHORT WinBSegment; /* dw ? ; window B start segment */ | ||
| 4145 | ULONG WinFuncPtr; /* dd ? ; real mode pointer to window function */ | ||
| 4146 | USHORT BytesPerScanLine; /* dw ? ; bytes per scan line */ | ||
| 4147 | |||
| 4148 | /* ; Mandatory information for VBE 1.2 and above */ | ||
| 4149 | USHORT XResolution; /* dw ? ; horizontal resolution in pixels or characters */ | ||
| 4150 | USHORT YResolution; /* dw ? ; vertical resolution in pixels or characters */ | ||
| 4151 | UCHAR XCharSize; /* db ? ; character cell width in pixels */ | ||
| 4152 | UCHAR YCharSize; /* db ? ; character cell height in pixels */ | ||
| 4153 | UCHAR NumberOfPlanes; /* db ? ; number of memory planes */ | ||
| 4154 | UCHAR BitsPerPixel; /* db ? ; bits per pixel */ | ||
| 4155 | UCHAR NumberOfBanks; /* db ? ; number of banks */ | ||
| 4156 | UCHAR MemoryModel; /* db ? ; memory model type */ | ||
| 4157 | UCHAR BankSize; /* db ? ; bank size in KB */ | ||
| 4158 | UCHAR NumberOfImagePages; /* db ? ; number of images */ | ||
| 4159 | UCHAR ReservedForPageFunction; /* db 1 ; reserved for page function */ | ||
| 4160 | |||
| 4161 | /* ; Direct Color fields(required for direct/6 and YUV/7 memory models) */ | ||
| 4162 | UCHAR RedMaskSize; /* db ? ; size of direct color red mask in bits */ | ||
| 4163 | UCHAR RedFieldPosition; /* db ? ; bit position of lsb of red mask */ | ||
| 4164 | UCHAR GreenMaskSize; /* db ? ; size of direct color green mask in bits */ | ||
| 4165 | UCHAR GreenFieldPosition; /* db ? ; bit position of lsb of green mask */ | ||
| 4166 | UCHAR BlueMaskSize; /* db ? ; size of direct color blue mask in bits */ | ||
| 4167 | UCHAR BlueFieldPosition; /* db ? ; bit position of lsb of blue mask */ | ||
| 4168 | UCHAR RsvdMaskSize; /* db ? ; size of direct color reserved mask in bits */ | ||
| 4169 | UCHAR RsvdFieldPosition; /* db ? ; bit position of lsb of reserved mask */ | ||
| 4170 | UCHAR DirectColorModeInfo; /* db ? ; direct color mode attributes */ | ||
| 4171 | |||
| 4172 | /* ; Mandatory information for VBE 2.0 and above */ | ||
| 4173 | ULONG PhysBasePtr; /* dd ? ; physical address for flat memory frame buffer */ | ||
| 4174 | ULONG Reserved_1; /* dd 0 ; reserved - always set to 0 */ | ||
| 4175 | USHORT Reserved_2; /* dw 0 ; reserved - always set to 0 */ | ||
| 4176 | |||
| 4177 | /* ; Mandatory information for VBE 3.0 and above */ | ||
| 4178 | USHORT LinBytesPerScanLine; /* dw ? ; bytes per scan line for linear modes */ | ||
| 4179 | UCHAR BnkNumberOfImagePages; /* db ? ; number of images for banked modes */ | ||
| 4180 | UCHAR LinNumberOfImagPages; /* db ? ; number of images for linear modes */ | ||
| 4181 | UCHAR LinRedMaskSize; /* db ? ; size of direct color red mask(linear modes) */ | ||
| 4182 | UCHAR LinRedFieldPosition; /* db ? ; bit position of lsb of red mask(linear modes) */ | ||
| 4183 | UCHAR LinGreenMaskSize; /* db ? ; size of direct color green mask(linear modes) */ | ||
| 4184 | UCHAR LinGreenFieldPosition; /* db ? ; bit position of lsb of green mask(linear modes) */ | ||
| 4185 | UCHAR LinBlueMaskSize; /* db ? ; size of direct color blue mask(linear modes) */ | ||
| 4186 | UCHAR LinBlueFieldPosition; /* db ? ; bit position of lsb of blue mask(linear modes) */ | ||
| 4187 | UCHAR LinRsvdMaskSize; /* db ? ; size of direct color reserved mask(linear modes) */ | ||
| 4188 | UCHAR LinRsvdFieldPosition; /* db ? ; bit position of lsb of reserved mask(linear modes) */ | ||
| 4189 | ULONG MaxPixelClock; /* dd ? ; maximum pixel clock(in Hz) for graphics mode */ | ||
| 4190 | UCHAR Reserved; /* db 190 dup (0) */ | ||
| 4191 | } VESA_MODE_INFO_BLOCK; | ||
| 4192 | |||
| 4193 | /* BIOS function CALLS */ | ||
| 4194 | #define ATOM_BIOS_EXTENDED_FUNCTION_CODE 0xA0 /* ATI Extended Function code */ | ||
| 4195 | #define ATOM_BIOS_FUNCTION_COP_MODE 0x00 | ||
| 4196 | #define ATOM_BIOS_FUNCTION_SHORT_QUERY1 0x04 | ||
| 4197 | #define ATOM_BIOS_FUNCTION_SHORT_QUERY2 0x05 | ||
| 4198 | #define ATOM_BIOS_FUNCTION_SHORT_QUERY3 0x06 | ||
| 4199 | #define ATOM_BIOS_FUNCTION_GET_DDC 0x0B | ||
| 4200 | #define ATOM_BIOS_FUNCTION_ASIC_DSTATE 0x0E | ||
| 4201 | #define ATOM_BIOS_FUNCTION_DEBUG_PLAY 0x0F | ||
| 4202 | #define ATOM_BIOS_FUNCTION_STV_STD 0x16 | ||
| 4203 | #define ATOM_BIOS_FUNCTION_DEVICE_DET 0x17 | ||
| 4204 | #define ATOM_BIOS_FUNCTION_DEVICE_SWITCH 0x18 | ||
| 4205 | |||
| 4206 | #define ATOM_BIOS_FUNCTION_PANEL_CONTROL 0x82 | ||
| 4207 | #define ATOM_BIOS_FUNCTION_OLD_DEVICE_DET 0x83 | ||
| 4208 | #define ATOM_BIOS_FUNCTION_OLD_DEVICE_SWITCH 0x84 | ||
| 4209 | #define ATOM_BIOS_FUNCTION_HW_ICON 0x8A | ||
| 4210 | #define ATOM_BIOS_FUNCTION_SET_CMOS 0x8B | ||
| 4211 | #define SUB_FUNCTION_UPDATE_DISPLAY_INFO 0x8000 /* Sub function 80 */ | ||
| 4212 | #define SUB_FUNCTION_UPDATE_EXPANSION_INFO 0x8100 /* Sub function 80 */ | ||
| 4213 | |||
| 4214 | #define ATOM_BIOS_FUNCTION_DISPLAY_INFO 0x8D | ||
| 4215 | #define ATOM_BIOS_FUNCTION_DEVICE_ON_OFF 0x8E | ||
| 4216 | #define ATOM_BIOS_FUNCTION_VIDEO_STATE 0x8F | ||
| 4217 | #define ATOM_SUB_FUNCTION_GET_CRITICAL_STATE 0x0300 /* Sub function 03 */ | ||
| 4218 | #define ATOM_SUB_FUNCTION_GET_LIDSTATE 0x0700 /* Sub function 7 */ | ||
| 4219 | #define ATOM_SUB_FUNCTION_THERMAL_STATE_NOTICE 0x1400 /* Notify caller the current thermal state */ | ||
| 4220 | #define ATOM_SUB_FUNCTION_CRITICAL_STATE_NOTICE 0x8300 /* Notify caller the current critical state */ | ||
| 4221 | #define ATOM_SUB_FUNCTION_SET_LIDSTATE 0x8500 /* Sub function 85 */ | ||
| 4222 | #define ATOM_SUB_FUNCTION_GET_REQ_DISPLAY_FROM_SBIOS_MODE 0x8900 /* Sub function 89 */ | ||
| 4223 | #define ATOM_SUB_FUNCTION_INFORM_ADC_SUPPORT 0x9400 /* Notify caller that ADC is supported */ | ||
| 4224 | |||
| 4225 | #define ATOM_BIOS_FUNCTION_VESA_DPMS 0x4F10 /* Set DPMS */ | ||
| 4226 | #define ATOM_SUB_FUNCTION_SET_DPMS 0x0001 /* BL: Sub function 01 */ | ||
| 4227 | #define ATOM_SUB_FUNCTION_GET_DPMS 0x0002 /* BL: Sub function 02 */ | ||
| 4228 | #define ATOM_PARAMETER_VESA_DPMS_ON 0x0000 /* BH Parameter for DPMS ON. */ | ||
| 4229 | #define ATOM_PARAMETER_VESA_DPMS_STANDBY 0x0100 /* BH Parameter for DPMS STANDBY */ | ||
| 4230 | #define ATOM_PARAMETER_VESA_DPMS_SUSPEND 0x0200 /* BH Parameter for DPMS SUSPEND */ | ||
| 4231 | #define ATOM_PARAMETER_VESA_DPMS_OFF 0x0400 /* BH Parameter for DPMS OFF */ | ||
| 4232 | #define ATOM_PARAMETER_VESA_DPMS_REDUCE_ON 0x0800 /* BH Parameter for DPMS REDUCE ON (NOT SUPPORTED) */ | ||
| 4233 | |||
| 4234 | #define ATOM_BIOS_RETURN_CODE_MASK 0x0000FF00L | ||
| 4235 | #define ATOM_BIOS_REG_HIGH_MASK 0x0000FF00L | ||
| 4236 | #define ATOM_BIOS_REG_LOW_MASK 0x000000FFL | ||
| 4237 | |||
| 4238 | /* structure used for VBIOS only */ | ||
| 4239 | |||
| 4240 | /* DispOutInfoTable */ | ||
| 4241 | typedef struct _ASIC_TRANSMITTER_INFO { | ||
| 4242 | USHORT usTransmitterObjId; | ||
| 4243 | USHORT usSupportDevice; | ||
| 4244 | UCHAR ucTransmitterCmdTblId; | ||
| 4245 | UCHAR ucConfig; | ||
| 4246 | UCHAR ucEncoderID; /* available 1st encoder ( default ) */ | ||
| 4247 | UCHAR ucOptionEncoderID; /* available 2nd encoder ( optional ) */ | ||
| 4248 | UCHAR uc2ndEncoderID; | ||
| 4249 | UCHAR ucReserved; | ||
| 4250 | } ASIC_TRANSMITTER_INFO; | ||
| 4251 | |||
| 4252 | typedef struct _ASIC_ENCODER_INFO { | ||
| 4253 | UCHAR ucEncoderID; | ||
| 4254 | UCHAR ucEncoderConfig; | ||
| 4255 | USHORT usEncoderCmdTblId; | ||
| 4256 | } ASIC_ENCODER_INFO; | ||
| 4257 | |||
| 4258 | typedef struct _ATOM_DISP_OUT_INFO { | ||
| 4259 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 4260 | USHORT ptrTransmitterInfo; | ||
| 4261 | USHORT ptrEncoderInfo; | ||
| 4262 | ASIC_TRANSMITTER_INFO asTransmitterInfo[1]; | ||
| 4263 | ASIC_ENCODER_INFO asEncoderInfo[1]; | ||
| 4264 | } ATOM_DISP_OUT_INFO; | ||
| 4265 | |||
| 4266 | /* DispDevicePriorityInfo */ | ||
| 4267 | typedef struct _ATOM_DISPLAY_DEVICE_PRIORITY_INFO { | ||
| 4268 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 4269 | USHORT asDevicePriority[16]; | ||
| 4270 | } ATOM_DISPLAY_DEVICE_PRIORITY_INFO; | ||
| 4271 | |||
| 4272 | /* ProcessAuxChannelTransactionTable */ | ||
| 4273 | typedef struct _PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS { | ||
| 4274 | USHORT lpAuxRequest; | ||
| 4275 | USHORT lpDataOut; | ||
| 4276 | UCHAR ucChannelID; | ||
| 4277 | union { | ||
| 4278 | UCHAR ucReplyStatus; | ||
| 4279 | UCHAR ucDelay; | ||
| 4280 | }; | ||
| 4281 | UCHAR ucDataOutLen; | ||
| 4282 | UCHAR ucReserved; | ||
| 4283 | } PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS; | ||
| 4284 | |||
| 4285 | #define PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS | ||
| 4286 | |||
| 4287 | /* GetSinkType */ | ||
| 4288 | |||
| 4289 | typedef struct _DP_ENCODER_SERVICE_PARAMETERS { | ||
| 4290 | USHORT ucLinkClock; | ||
| 4291 | union { | ||
| 4292 | UCHAR ucConfig; /* for DP training command */ | ||
| 4293 | UCHAR ucI2cId; /* use for GET_SINK_TYPE command */ | ||
| 4294 | }; | ||
| 4295 | UCHAR ucAction; | ||
| 4296 | UCHAR ucStatus; | ||
| 4297 | UCHAR ucLaneNum; | ||
| 4298 | UCHAR ucReserved[2]; | ||
| 4299 | } DP_ENCODER_SERVICE_PARAMETERS; | ||
| 4300 | |||
| 4301 | /* ucAction */ | ||
| 4302 | #define ATOM_DP_ACTION_GET_SINK_TYPE 0x01 | ||
| 4303 | #define ATOM_DP_ACTION_TRAINING_START 0x02 | ||
| 4304 | #define ATOM_DP_ACTION_TRAINING_COMPLETE 0x03 | ||
| 4305 | #define ATOM_DP_ACTION_TRAINING_PATTERN_SEL 0x04 | ||
| 4306 | #define ATOM_DP_ACTION_SET_VSWING_PREEMP 0x05 | ||
| 4307 | #define ATOM_DP_ACTION_GET_VSWING_PREEMP 0x06 | ||
| 4308 | #define ATOM_DP_ACTION_BLANKING 0x07 | ||
| 4309 | |||
| 4310 | /* ucConfig */ | ||
| 4311 | #define ATOM_DP_CONFIG_ENCODER_SEL_MASK 0x03 | ||
| 4312 | #define ATOM_DP_CONFIG_DIG1_ENCODER 0x00 | ||
| 4313 | #define ATOM_DP_CONFIG_DIG2_ENCODER 0x01 | ||
| 4314 | #define ATOM_DP_CONFIG_EXTERNAL_ENCODER 0x02 | ||
| 4315 | #define ATOM_DP_CONFIG_LINK_SEL_MASK 0x04 | ||
| 4316 | #define ATOM_DP_CONFIG_LINK_A 0x00 | ||
| 4317 | #define ATOM_DP_CONFIG_LINK_B 0x04 | ||
| 4318 | |||
| 4319 | #define DP_ENCODER_SERVICE_PS_ALLOCATION WRITE_ONE_BYTE_HW_I2C_DATA_PARAMETERS | ||
| 4320 | |||
| 4321 | /* DP_TRAINING_TABLE */ | ||
| 4322 | #define DPCD_SET_LINKRATE_LANENUM_PATTERN1_TBL_ADDR ATOM_DP_TRAINING_TBL_ADDR | ||
| 4323 | #define DPCD_SET_SS_CNTL_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 8 ) | ||
| 4324 | #define DPCD_SET_LANE_VSWING_PREEMP_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 16) | ||
| 4325 | #define DPCD_SET_TRAINING_PATTERN0_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 24) | ||
| 4326 | #define DPCD_SET_TRAINING_PATTERN2_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 32) | ||
| 4327 | #define DPCD_GET_LINKRATE_LANENUM_SS_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 40) | ||
| 4328 | #define DPCD_GET_LANE_STATUS_ADJUST_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 48) | ||
| 4329 | #define DP_I2C_AUX_DDC_WRITE_START_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 60) | ||
| 4330 | #define DP_I2C_AUX_DDC_WRITE_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 64) | ||
| 4331 | #define DP_I2C_AUX_DDC_READ_START_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 72) | ||
| 4332 | #define DP_I2C_AUX_DDC_READ_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 76) | ||
| 4333 | #define DP_I2C_AUX_DDC_READ_END_TBL_ADDR (ATOM_DP_TRAINING_TBL_ADDR + 80) | ||
| 4334 | |||
| 4335 | typedef struct _PROCESS_I2C_CHANNEL_TRANSACTION_PARAMETERS { | ||
| 4336 | UCHAR ucI2CSpeed; | ||
| 4337 | union { | ||
| 4338 | UCHAR ucRegIndex; | ||
| 4339 | UCHAR ucStatus; | ||
| 4340 | }; | ||
| 4341 | USHORT lpI2CDataOut; | ||
| 4342 | UCHAR ucFlag; | ||
| 4343 | UCHAR ucTransBytes; | ||
| 4344 | UCHAR ucSlaveAddr; | ||
| 4345 | UCHAR ucLineNumber; | ||
| 4346 | } PROCESS_I2C_CHANNEL_TRANSACTION_PARAMETERS; | ||
| 4347 | |||
| 4348 | #define PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION PROCESS_I2C_CHANNEL_TRANSACTION_PARAMETERS | ||
| 4349 | |||
| 4350 | /* ucFlag */ | ||
| 4351 | #define HW_I2C_WRITE 1 | ||
| 4352 | #define HW_I2C_READ 0 | ||
| 4353 | |||
| 4354 | /****************************************************************************/ | ||
| 4355 | /* Portion VI: Definitinos being oboselete */ | ||
| 4356 | /****************************************************************************/ | ||
| 4357 | |||
| 4358 | /* ========================================================================================== */ | ||
| 4359 | /* Remove the definitions below when driver is ready! */ | ||
| 4360 | typedef struct _ATOM_DAC_INFO { | ||
| 4361 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 4362 | USHORT usMaxFrequency; /* in 10kHz unit */ | ||
| 4363 | USHORT usReserved; | ||
| 4364 | } ATOM_DAC_INFO; | ||
| 4365 | |||
| 4366 | typedef struct _COMPASSIONATE_DATA { | ||
| 4367 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 4368 | |||
| 4369 | /* ============================== DAC1 portion */ | ||
| 4370 | UCHAR ucDAC1_BG_Adjustment; | ||
| 4371 | UCHAR ucDAC1_DAC_Adjustment; | ||
| 4372 | USHORT usDAC1_FORCE_Data; | ||
| 4373 | /* ============================== DAC2 portion */ | ||
| 4374 | UCHAR ucDAC2_CRT2_BG_Adjustment; | ||
| 4375 | UCHAR ucDAC2_CRT2_DAC_Adjustment; | ||
| 4376 | USHORT usDAC2_CRT2_FORCE_Data; | ||
| 4377 | USHORT usDAC2_CRT2_MUX_RegisterIndex; | ||
| 4378 | UCHAR ucDAC2_CRT2_MUX_RegisterInfo; /* Bit[4:0]=Bit position,Bit[7]=1:Active High;=0 Active Low */ | ||
| 4379 | UCHAR ucDAC2_NTSC_BG_Adjustment; | ||
| 4380 | UCHAR ucDAC2_NTSC_DAC_Adjustment; | ||
| 4381 | USHORT usDAC2_TV1_FORCE_Data; | ||
| 4382 | USHORT usDAC2_TV1_MUX_RegisterIndex; | ||
| 4383 | UCHAR ucDAC2_TV1_MUX_RegisterInfo; /* Bit[4:0]=Bit position,Bit[7]=1:Active High;=0 Active Low */ | ||
| 4384 | UCHAR ucDAC2_CV_BG_Adjustment; | ||
| 4385 | UCHAR ucDAC2_CV_DAC_Adjustment; | ||
| 4386 | USHORT usDAC2_CV_FORCE_Data; | ||
| 4387 | USHORT usDAC2_CV_MUX_RegisterIndex; | ||
| 4388 | UCHAR ucDAC2_CV_MUX_RegisterInfo; /* Bit[4:0]=Bit position,Bit[7]=1:Active High;=0 Active Low */ | ||
| 4389 | UCHAR ucDAC2_PAL_BG_Adjustment; | ||
| 4390 | UCHAR ucDAC2_PAL_DAC_Adjustment; | ||
| 4391 | USHORT usDAC2_TV2_FORCE_Data; | ||
| 4392 | } COMPASSIONATE_DATA; | ||
| 4393 | |||
| 4394 | /****************************Supported Device Info Table Definitions**********************/ | ||
| 4395 | /* ucConnectInfo: */ | ||
| 4396 | /* [7:4] - connector type */ | ||
| 4397 | /* = 1 - VGA connector */ | ||
| 4398 | /* = 2 - DVI-I */ | ||
| 4399 | /* = 3 - DVI-D */ | ||
| 4400 | /* = 4 - DVI-A */ | ||
| 4401 | /* = 5 - SVIDEO */ | ||
| 4402 | /* = 6 - COMPOSITE */ | ||
| 4403 | /* = 7 - LVDS */ | ||
| 4404 | /* = 8 - DIGITAL LINK */ | ||
| 4405 | /* = 9 - SCART */ | ||
| 4406 | /* = 0xA - HDMI_type A */ | ||
| 4407 | /* = 0xB - HDMI_type B */ | ||
| 4408 | /* = 0xE - Special case1 (DVI+DIN) */ | ||
| 4409 | /* Others=TBD */ | ||
| 4410 | /* [3:0] - DAC Associated */ | ||
| 4411 | /* = 0 - no DAC */ | ||
| 4412 | /* = 1 - DACA */ | ||
| 4413 | /* = 2 - DACB */ | ||
| 4414 | /* = 3 - External DAC */ | ||
| 4415 | /* Others=TBD */ | ||
| 4416 | /* */ | ||
| 4417 | |||
| 4418 | typedef struct _ATOM_CONNECTOR_INFO { | ||
| 4419 | #if ATOM_BIG_ENDIAN | ||
| 4420 | UCHAR bfConnectorType:4; | ||
| 4421 | UCHAR bfAssociatedDAC:4; | ||
| 4422 | #else | ||
| 4423 | UCHAR bfAssociatedDAC:4; | ||
| 4424 | UCHAR bfConnectorType:4; | ||
| 4425 | #endif | ||
| 4426 | } ATOM_CONNECTOR_INFO; | ||
| 4427 | |||
| 4428 | typedef union _ATOM_CONNECTOR_INFO_ACCESS { | ||
| 4429 | ATOM_CONNECTOR_INFO sbfAccess; | ||
| 4430 | UCHAR ucAccess; | ||
| 4431 | } ATOM_CONNECTOR_INFO_ACCESS; | ||
| 4432 | |||
| 4433 | typedef struct _ATOM_CONNECTOR_INFO_I2C { | ||
| 4434 | ATOM_CONNECTOR_INFO_ACCESS sucConnectorInfo; | ||
| 4435 | ATOM_I2C_ID_CONFIG_ACCESS sucI2cId; | ||
| 4436 | } ATOM_CONNECTOR_INFO_I2C; | ||
| 4437 | |||
| 4438 | typedef struct _ATOM_SUPPORTED_DEVICES_INFO { | ||
| 4439 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 4440 | USHORT usDeviceSupport; | ||
| 4441 | ATOM_CONNECTOR_INFO_I2C asConnInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO]; | ||
| 4442 | } ATOM_SUPPORTED_DEVICES_INFO; | ||
| 4443 | |||
| 4444 | #define NO_INT_SRC_MAPPED 0xFF | ||
| 4445 | |||
| 4446 | typedef struct _ATOM_CONNECTOR_INC_SRC_BITMAP { | ||
| 4447 | UCHAR ucIntSrcBitmap; | ||
| 4448 | } ATOM_CONNECTOR_INC_SRC_BITMAP; | ||
| 4449 | |||
| 4450 | typedef struct _ATOM_SUPPORTED_DEVICES_INFO_2 { | ||
| 4451 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 4452 | USHORT usDeviceSupport; | ||
| 4453 | ATOM_CONNECTOR_INFO_I2C asConnInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO_2]; | ||
| 4454 | ATOM_CONNECTOR_INC_SRC_BITMAP | ||
| 4455 | asIntSrcInfo[ATOM_MAX_SUPPORTED_DEVICE_INFO_2]; | ||
| 4456 | } ATOM_SUPPORTED_DEVICES_INFO_2; | ||
| 4457 | |||
| 4458 | typedef struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 { | ||
| 4459 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 4460 | USHORT usDeviceSupport; | ||
| 4461 | ATOM_CONNECTOR_INFO_I2C asConnInfo[ATOM_MAX_SUPPORTED_DEVICE]; | ||
| 4462 | ATOM_CONNECTOR_INC_SRC_BITMAP asIntSrcInfo[ATOM_MAX_SUPPORTED_DEVICE]; | ||
| 4463 | } ATOM_SUPPORTED_DEVICES_INFO_2d1; | ||
| 4464 | |||
| 4465 | #define ATOM_SUPPORTED_DEVICES_INFO_LAST ATOM_SUPPORTED_DEVICES_INFO_2d1 | ||
| 4466 | |||
| 4467 | typedef struct _ATOM_MISC_CONTROL_INFO { | ||
| 4468 | USHORT usFrequency; | ||
| 4469 | UCHAR ucPLL_ChargePump; /* PLL charge-pump gain control */ | ||
| 4470 | UCHAR ucPLL_DutyCycle; /* PLL duty cycle control */ | ||
| 4471 | UCHAR ucPLL_VCO_Gain; /* PLL VCO gain control */ | ||
| 4472 | UCHAR ucPLL_VoltageSwing; /* PLL driver voltage swing control */ | ||
| 4473 | } ATOM_MISC_CONTROL_INFO; | ||
| 4474 | |||
| 4475 | #define ATOM_MAX_MISC_INFO 4 | ||
| 4476 | |||
| 4477 | typedef struct _ATOM_TMDS_INFO { | ||
| 4478 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 4479 | USHORT usMaxFrequency; /* in 10Khz */ | ||
| 4480 | ATOM_MISC_CONTROL_INFO asMiscInfo[ATOM_MAX_MISC_INFO]; | ||
| 4481 | } ATOM_TMDS_INFO; | ||
| 4482 | |||
| 4483 | typedef struct _ATOM_ENCODER_ANALOG_ATTRIBUTE { | ||
| 4484 | UCHAR ucTVStandard; /* Same as TV standards defined above, */ | ||
| 4485 | UCHAR ucPadding[1]; | ||
| 4486 | } ATOM_ENCODER_ANALOG_ATTRIBUTE; | ||
| 4487 | |||
| 4488 | typedef struct _ATOM_ENCODER_DIGITAL_ATTRIBUTE { | ||
| 4489 | UCHAR ucAttribute; /* Same as other digital encoder attributes defined above */ | ||
| 4490 | UCHAR ucPadding[1]; | ||
| 4491 | } ATOM_ENCODER_DIGITAL_ATTRIBUTE; | ||
| 4492 | |||
| 4493 | typedef union _ATOM_ENCODER_ATTRIBUTE { | ||
| 4494 | ATOM_ENCODER_ANALOG_ATTRIBUTE sAlgAttrib; | ||
| 4495 | ATOM_ENCODER_DIGITAL_ATTRIBUTE sDigAttrib; | ||
| 4496 | } ATOM_ENCODER_ATTRIBUTE; | ||
| 4497 | |||
| 4498 | typedef struct _DVO_ENCODER_CONTROL_PARAMETERS { | ||
| 4499 | USHORT usPixelClock; | ||
| 4500 | USHORT usEncoderID; | ||
| 4501 | UCHAR ucDeviceType; /* Use ATOM_DEVICE_xxx1_Index to indicate device type only. */ | ||
| 4502 | UCHAR ucAction; /* ATOM_ENABLE/ATOM_DISABLE/ATOM_HPD_INIT */ | ||
| 4503 | ATOM_ENCODER_ATTRIBUTE usDevAttr; | ||
| 4504 | } DVO_ENCODER_CONTROL_PARAMETERS; | ||
| 4505 | |||
| 4506 | typedef struct _DVO_ENCODER_CONTROL_PS_ALLOCATION { | ||
| 4507 | DVO_ENCODER_CONTROL_PARAMETERS sDVOEncoder; | ||
| 4508 | WRITE_ONE_BYTE_HW_I2C_DATA_PS_ALLOCATION sReserved; /* Caller doesn't need to init this portion */ | ||
| 4509 | } DVO_ENCODER_CONTROL_PS_ALLOCATION; | ||
| 4510 | |||
| 4511 | #define ATOM_XTMDS_ASIC_SI164_ID 1 | ||
| 4512 | #define ATOM_XTMDS_ASIC_SI178_ID 2 | ||
| 4513 | #define ATOM_XTMDS_ASIC_TFP513_ID 3 | ||
| 4514 | #define ATOM_XTMDS_SUPPORTED_SINGLELINK 0x00000001 | ||
| 4515 | #define ATOM_XTMDS_SUPPORTED_DUALLINK 0x00000002 | ||
| 4516 | #define ATOM_XTMDS_MVPU_FPGA 0x00000004 | ||
| 4517 | |||
| 4518 | typedef struct _ATOM_XTMDS_INFO { | ||
| 4519 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 4520 | USHORT usSingleLinkMaxFrequency; | ||
| 4521 | ATOM_I2C_ID_CONFIG_ACCESS sucI2cId; /* Point the ID on which I2C is used to control external chip */ | ||
| 4522 | UCHAR ucXtransimitterID; | ||
| 4523 | UCHAR ucSupportedLink; /* Bit field, bit0=1, single link supported;bit1=1,dual link supported */ | ||
| 4524 | UCHAR ucSequnceAlterID; /* Even with the same external TMDS asic, it's possible that the program seqence alters */ | ||
| 4525 | /* due to design. This ID is used to alert driver that the sequence is not "standard"! */ | ||
| 4526 | UCHAR ucMasterAddress; /* Address to control Master xTMDS Chip */ | ||
| 4527 | UCHAR ucSlaveAddress; /* Address to control Slave xTMDS Chip */ | ||
| 4528 | } ATOM_XTMDS_INFO; | ||
| 4529 | |||
| 4530 | typedef struct _DFP_DPMS_STATUS_CHANGE_PARAMETERS { | ||
| 4531 | UCHAR ucEnable; /* ATOM_ENABLE=On or ATOM_DISABLE=Off */ | ||
| 4532 | UCHAR ucDevice; /* ATOM_DEVICE_DFP1_INDEX.... */ | ||
| 4533 | UCHAR ucPadding[2]; | ||
| 4534 | } DFP_DPMS_STATUS_CHANGE_PARAMETERS; | ||
| 4535 | |||
| 4536 | /****************************Legacy Power Play Table Definitions **********************/ | ||
| 4537 | |||
| 4538 | /* Definitions for ulPowerPlayMiscInfo */ | ||
| 4539 | #define ATOM_PM_MISCINFO_SPLIT_CLOCK 0x00000000L | ||
| 4540 | #define ATOM_PM_MISCINFO_USING_MCLK_SRC 0x00000001L | ||
| 4541 | #define ATOM_PM_MISCINFO_USING_SCLK_SRC 0x00000002L | ||
| 4542 | |||
| 4543 | #define ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT 0x00000004L | ||
| 4544 | #define ATOM_PM_MISCINFO_VOLTAGE_DROP_ACTIVE_HIGH 0x00000008L | ||
| 4545 | |||
| 4546 | #define ATOM_PM_MISCINFO_LOAD_PERFORMANCE_EN 0x00000010L | ||
| 4547 | |||
| 4548 | #define ATOM_PM_MISCINFO_ENGINE_CLOCK_CONTRL_EN 0x00000020L | ||
| 4549 | #define ATOM_PM_MISCINFO_MEMORY_CLOCK_CONTRL_EN 0x00000040L | ||
| 4550 | #define ATOM_PM_MISCINFO_PROGRAM_VOLTAGE 0x00000080L /* When this bit set, ucVoltageDropIndex is not an index for GPIO pin, but a voltage ID that SW needs program */ | ||
| 4551 | |||
| 4552 | #define ATOM_PM_MISCINFO_ASIC_REDUCED_SPEED_SCLK_EN 0x00000100L | ||
| 4553 | #define ATOM_PM_MISCINFO_ASIC_DYNAMIC_VOLTAGE_EN 0x00000200L | ||
| 4554 | #define ATOM_PM_MISCINFO_ASIC_SLEEP_MODE_EN 0x00000400L | ||
| 4555 | #define ATOM_PM_MISCINFO_LOAD_BALANCE_EN 0x00000800L | ||
| 4556 | #define ATOM_PM_MISCINFO_DEFAULT_DC_STATE_ENTRY_TRUE 0x00001000L | ||
| 4557 | #define ATOM_PM_MISCINFO_DEFAULT_LOW_DC_STATE_ENTRY_TRUE 0x00002000L | ||
| 4558 | #define ATOM_PM_MISCINFO_LOW_LCD_REFRESH_RATE 0x00004000L | ||
| 4559 | |||
| 4560 | #define ATOM_PM_MISCINFO_DRIVER_DEFAULT_MODE 0x00008000L | ||
| 4561 | #define ATOM_PM_MISCINFO_OVER_CLOCK_MODE 0x00010000L | ||
| 4562 | #define ATOM_PM_MISCINFO_OVER_DRIVE_MODE 0x00020000L | ||
| 4563 | #define ATOM_PM_MISCINFO_POWER_SAVING_MODE 0x00040000L | ||
| 4564 | #define ATOM_PM_MISCINFO_THERMAL_DIODE_MODE 0x00080000L | ||
| 4565 | |||
| 4566 | #define ATOM_PM_MISCINFO_FRAME_MODULATION_MASK 0x00300000L /* 0-FM Disable, 1-2 level FM, 2-4 level FM, 3-Reserved */ | ||
| 4567 | #define ATOM_PM_MISCINFO_FRAME_MODULATION_SHIFT 20 | ||
| 4568 | |||
| 4569 | #define ATOM_PM_MISCINFO_DYN_CLK_3D_IDLE 0x00400000L | ||
| 4570 | #define ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_2 0x00800000L | ||
| 4571 | #define ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_4 0x01000000L | ||
| 4572 | #define ATOM_PM_MISCINFO_DYNAMIC_HDP_BLOCK_EN 0x02000000L /* When set, Dynamic */ | ||
| 4573 | #define ATOM_PM_MISCINFO_DYNAMIC_MC_HOST_BLOCK_EN 0x04000000L /* When set, Dynamic */ | ||
| 4574 | #define ATOM_PM_MISCINFO_3D_ACCELERATION_EN 0x08000000L /* When set, This mode is for acceleated 3D mode */ | ||
| 4575 | |||
| 4576 | #define ATOM_PM_MISCINFO_POWERPLAY_SETTINGS_GROUP_MASK 0x70000000L /* 1-Optimal Battery Life Group, 2-High Battery, 3-Balanced, 4-High Performance, 5- Optimal Performance (Default state with Default clocks) */ | ||
| 4577 | #define ATOM_PM_MISCINFO_POWERPLAY_SETTINGS_GROUP_SHIFT 28 | ||
| 4578 | #define ATOM_PM_MISCINFO_ENABLE_BACK_BIAS 0x80000000L | ||
| 4579 | |||
| 4580 | #define ATOM_PM_MISCINFO2_SYSTEM_AC_LITE_MODE 0x00000001L | ||
| 4581 | #define ATOM_PM_MISCINFO2_MULTI_DISPLAY_SUPPORT 0x00000002L | ||
| 4582 | #define ATOM_PM_MISCINFO2_DYNAMIC_BACK_BIAS_EN 0x00000004L | ||
| 4583 | #define ATOM_PM_MISCINFO2_FS3D_OVERDRIVE_INFO 0x00000008L | ||
| 4584 | #define ATOM_PM_MISCINFO2_FORCEDLOWPWR_MODE 0x00000010L | ||
| 4585 | #define ATOM_PM_MISCINFO2_VDDCI_DYNAMIC_VOLTAGE_EN 0x00000020L | ||
| 4586 | #define ATOM_PM_MISCINFO2_VIDEO_PLAYBACK_CAPABLE 0x00000040L /* If this bit is set in multi-pp mode, then driver will pack up one with the minior power consumption. */ | ||
| 4587 | /* If it's not set in any pp mode, driver will use its default logic to pick a pp mode in video playback */ | ||
| 4588 | #define ATOM_PM_MISCINFO2_NOT_VALID_ON_DC 0x00000080L | ||
| 4589 | #define ATOM_PM_MISCINFO2_STUTTER_MODE_EN 0x00000100L | ||
| 4590 | #define ATOM_PM_MISCINFO2_UVD_SUPPORT_MODE 0x00000200L | ||
| 4591 | |||
| 4592 | /* ucTableFormatRevision=1 */ | ||
| 4593 | /* ucTableContentRevision=1 */ | ||
| 4594 | typedef struct _ATOM_POWERMODE_INFO { | ||
| 4595 | ULONG ulMiscInfo; /* The power level should be arranged in ascending order */ | ||
| 4596 | ULONG ulReserved1; /* must set to 0 */ | ||
| 4597 | ULONG ulReserved2; /* must set to 0 */ | ||
| 4598 | USHORT usEngineClock; | ||
| 4599 | USHORT usMemoryClock; | ||
| 4600 | UCHAR ucVoltageDropIndex; /* index to GPIO table */ | ||
| 4601 | UCHAR ucSelectedPanel_RefreshRate; /* panel refresh rate */ | ||
| 4602 | UCHAR ucMinTemperature; | ||
| 4603 | UCHAR ucMaxTemperature; | ||
| 4604 | UCHAR ucNumPciELanes; /* number of PCIE lanes */ | ||
| 4605 | } ATOM_POWERMODE_INFO; | ||
| 4606 | |||
| 4607 | /* ucTableFormatRevision=2 */ | ||
| 4608 | /* ucTableContentRevision=1 */ | ||
| 4609 | typedef struct _ATOM_POWERMODE_INFO_V2 { | ||
| 4610 | ULONG ulMiscInfo; /* The power level should be arranged in ascending order */ | ||
| 4611 | ULONG ulMiscInfo2; | ||
| 4612 | ULONG ulEngineClock; | ||
| 4613 | ULONG ulMemoryClock; | ||
| 4614 | UCHAR ucVoltageDropIndex; /* index to GPIO table */ | ||
| 4615 | UCHAR ucSelectedPanel_RefreshRate; /* panel refresh rate */ | ||
| 4616 | UCHAR ucMinTemperature; | ||
| 4617 | UCHAR ucMaxTemperature; | ||
| 4618 | UCHAR ucNumPciELanes; /* number of PCIE lanes */ | ||
| 4619 | } ATOM_POWERMODE_INFO_V2; | ||
| 4620 | |||
| 4621 | /* ucTableFormatRevision=2 */ | ||
| 4622 | /* ucTableContentRevision=2 */ | ||
| 4623 | typedef struct _ATOM_POWERMODE_INFO_V3 { | ||
| 4624 | ULONG ulMiscInfo; /* The power level should be arranged in ascending order */ | ||
| 4625 | ULONG ulMiscInfo2; | ||
| 4626 | ULONG ulEngineClock; | ||
| 4627 | ULONG ulMemoryClock; | ||
| 4628 | UCHAR ucVoltageDropIndex; /* index to Core (VDDC) votage table */ | ||
| 4629 | UCHAR ucSelectedPanel_RefreshRate; /* panel refresh rate */ | ||
| 4630 | UCHAR ucMinTemperature; | ||
| 4631 | UCHAR ucMaxTemperature; | ||
| 4632 | UCHAR ucNumPciELanes; /* number of PCIE lanes */ | ||
| 4633 | UCHAR ucVDDCI_VoltageDropIndex; /* index to VDDCI votage table */ | ||
| 4634 | } ATOM_POWERMODE_INFO_V3; | ||
| 4635 | |||
| 4636 | #define ATOM_MAX_NUMBEROF_POWER_BLOCK 8 | ||
| 4637 | |||
| 4638 | #define ATOM_PP_OVERDRIVE_INTBITMAP_AUXWIN 0x01 | ||
| 4639 | #define ATOM_PP_OVERDRIVE_INTBITMAP_OVERDRIVE 0x02 | ||
| 4640 | |||
| 4641 | #define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_LM63 0x01 | ||
| 4642 | #define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_ADM1032 0x02 | ||
| 4643 | #define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_ADM1030 0x03 | ||
| 4644 | #define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_MUA6649 0x04 | ||
| 4645 | #define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_LM64 0x05 | ||
| 4646 | #define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_F75375 0x06 | ||
| 4647 | #define ATOM_PP_OVERDRIVE_THERMALCONTROLLER_ASC7512 0x07 /* Andigilog */ | ||
| 4648 | |||
| 4649 | typedef struct _ATOM_POWERPLAY_INFO { | ||
| 4650 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 4651 | UCHAR ucOverdriveThermalController; | ||
| 4652 | UCHAR ucOverdriveI2cLine; | ||
| 4653 | UCHAR ucOverdriveIntBitmap; | ||
| 4654 | UCHAR ucOverdriveControllerAddress; | ||
| 4655 | UCHAR ucSizeOfPowerModeEntry; | ||
| 4656 | UCHAR ucNumOfPowerModeEntries; | ||
| 4657 | ATOM_POWERMODE_INFO asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK]; | ||
| 4658 | } ATOM_POWERPLAY_INFO; | ||
| 4659 | |||
| 4660 | typedef struct _ATOM_POWERPLAY_INFO_V2 { | ||
| 4661 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 4662 | UCHAR ucOverdriveThermalController; | ||
| 4663 | UCHAR ucOverdriveI2cLine; | ||
| 4664 | UCHAR ucOverdriveIntBitmap; | ||
| 4665 | UCHAR ucOverdriveControllerAddress; | ||
| 4666 | UCHAR ucSizeOfPowerModeEntry; | ||
| 4667 | UCHAR ucNumOfPowerModeEntries; | ||
| 4668 | ATOM_POWERMODE_INFO_V2 asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK]; | ||
| 4669 | } ATOM_POWERPLAY_INFO_V2; | ||
| 4670 | |||
| 4671 | typedef struct _ATOM_POWERPLAY_INFO_V3 { | ||
| 4672 | ATOM_COMMON_TABLE_HEADER sHeader; | ||
| 4673 | UCHAR ucOverdriveThermalController; | ||
| 4674 | UCHAR ucOverdriveI2cLine; | ||
| 4675 | UCHAR ucOverdriveIntBitmap; | ||
| 4676 | UCHAR ucOverdriveControllerAddress; | ||
| 4677 | UCHAR ucSizeOfPowerModeEntry; | ||
| 4678 | UCHAR ucNumOfPowerModeEntries; | ||
| 4679 | ATOM_POWERMODE_INFO_V3 asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK]; | ||
| 4680 | } ATOM_POWERPLAY_INFO_V3; | ||
| 4681 | |||
| 4682 | /**************************************************************************/ | ||
| 4683 | |||
| 4684 | /* Following definitions are for compatiblity issue in different SW components. */ | ||
| 4685 | #define ATOM_MASTER_DATA_TABLE_REVISION 0x01 | ||
| 4686 | #define Object_Info Object_Header | ||
| 4687 | #define AdjustARB_SEQ MC_InitParameter | ||
| 4688 | #define VRAM_GPIO_DetectionInfo VoltageObjectInfo | ||
| 4689 | #define ASIC_VDDCI_Info ASIC_ProfilingInfo | ||
| 4690 | #define ASIC_MVDDQ_Info MemoryTrainingInfo | ||
| 4691 | #define SS_Info PPLL_SS_Info | ||
| 4692 | #define ASIC_MVDDC_Info ASIC_InternalSS_Info | ||
| 4693 | #define DispDevicePriorityInfo SaveRestoreInfo | ||
| 4694 | #define DispOutInfo TV_VideoMode | ||
| 4695 | |||
| 4696 | #define ATOM_ENCODER_OBJECT_TABLE ATOM_OBJECT_TABLE | ||
| 4697 | #define ATOM_CONNECTOR_OBJECT_TABLE ATOM_OBJECT_TABLE | ||
| 4698 | |||
| 4699 | /* New device naming, remove them when both DAL/VBIOS is ready */ | ||
| 4700 | #define DFP2I_OUTPUT_CONTROL_PARAMETERS CRT1_OUTPUT_CONTROL_PARAMETERS | ||
| 4701 | #define DFP2I_OUTPUT_CONTROL_PS_ALLOCATION DFP2I_OUTPUT_CONTROL_PARAMETERS | ||
| 4702 | |||
| 4703 | #define DFP1X_OUTPUT_CONTROL_PARAMETERS CRT1_OUTPUT_CONTROL_PARAMETERS | ||
| 4704 | #define DFP1X_OUTPUT_CONTROL_PS_ALLOCATION DFP1X_OUTPUT_CONTROL_PARAMETERS | ||
| 4705 | |||
| 4706 | #define DFP1I_OUTPUT_CONTROL_PARAMETERS DFP1_OUTPUT_CONTROL_PARAMETERS | ||
| 4707 | #define DFP1I_OUTPUT_CONTROL_PS_ALLOCATION DFP1_OUTPUT_CONTROL_PS_ALLOCATION | ||
| 4708 | |||
| 4709 | #define ATOM_DEVICE_DFP1I_SUPPORT ATOM_DEVICE_DFP1_SUPPORT | ||
| 4710 | #define ATOM_DEVICE_DFP1X_SUPPORT ATOM_DEVICE_DFP2_SUPPORT | ||
| 4711 | |||
| 4712 | #define ATOM_DEVICE_DFP1I_INDEX ATOM_DEVICE_DFP1_INDEX | ||
| 4713 | #define ATOM_DEVICE_DFP1X_INDEX ATOM_DEVICE_DFP2_INDEX | ||
| 4714 | |||
| 4715 | #define ATOM_DEVICE_DFP2I_INDEX 0x00000009 | ||
| 4716 | #define ATOM_DEVICE_DFP2I_SUPPORT (0x1L << ATOM_DEVICE_DFP2I_INDEX) | ||
| 4717 | |||
| 4718 | #define ATOM_S0_DFP1I ATOM_S0_DFP1 | ||
| 4719 | #define ATOM_S0_DFP1X ATOM_S0_DFP2 | ||
| 4720 | |||
| 4721 | #define ATOM_S0_DFP2I 0x00200000L | ||
| 4722 | #define ATOM_S0_DFP2Ib2 0x20 | ||
| 4723 | |||
| 4724 | #define ATOM_S2_DFP1I_DPMS_STATE ATOM_S2_DFP1_DPMS_STATE | ||
| 4725 | #define ATOM_S2_DFP1X_DPMS_STATE ATOM_S2_DFP2_DPMS_STATE | ||
| 4726 | |||
| 4727 | #define ATOM_S2_DFP2I_DPMS_STATE 0x02000000L | ||
| 4728 | #define ATOM_S2_DFP2I_DPMS_STATEb3 0x02 | ||
| 4729 | |||
| 4730 | #define ATOM_S3_DFP2I_ACTIVEb1 0x02 | ||
| 4731 | |||
| 4732 | #define ATOM_S3_DFP1I_ACTIVE ATOM_S3_DFP1_ACTIVE | ||
| 4733 | #define ATOM_S3_DFP1X_ACTIVE ATOM_S3_DFP2_ACTIVE | ||
| 4734 | |||
| 4735 | #define ATOM_S3_DFP2I_ACTIVE 0x00000200L | ||
| 4736 | |||
| 4737 | #define ATOM_S3_DFP1I_CRTC_ACTIVE ATOM_S3_DFP1_CRTC_ACTIVE | ||
| 4738 | #define ATOM_S3_DFP1X_CRTC_ACTIVE ATOM_S3_DFP2_CRTC_ACTIVE | ||
| 4739 | #define ATOM_S3_DFP2I_CRTC_ACTIVE 0x02000000L | ||
| 4740 | |||
| 4741 | #define ATOM_S3_DFP2I_CRTC_ACTIVEb3 0x02 | ||
| 4742 | #define ATOM_S5_DOS_REQ_DFP2Ib1 0x02 | ||
| 4743 | |||
| 4744 | #define ATOM_S5_DOS_REQ_DFP2I 0x0200 | ||
| 4745 | #define ATOM_S6_ACC_REQ_DFP1I ATOM_S6_ACC_REQ_DFP1 | ||
| 4746 | #define ATOM_S6_ACC_REQ_DFP1X ATOM_S6_ACC_REQ_DFP2 | ||
| 4747 | |||
| 4748 | #define ATOM_S6_ACC_REQ_DFP2Ib3 0x02 | ||
| 4749 | #define ATOM_S6_ACC_REQ_DFP2I 0x02000000L | ||
| 4750 | |||
| 4751 | #define TMDS1XEncoderControl DVOEncoderControl | ||
| 4752 | #define DFP1XOutputControl DVOOutputControl | ||
| 4753 | |||
| 4754 | #define ExternalDFPOutputControl DFP1XOutputControl | ||
| 4755 | #define EnableExternalTMDS_Encoder TMDS1XEncoderControl | ||
| 4756 | |||
| 4757 | #define DFP1IOutputControl TMDSAOutputControl | ||
| 4758 | #define DFP2IOutputControl LVTMAOutputControl | ||
| 4759 | |||
| 4760 | #define DAC1_ENCODER_CONTROL_PARAMETERS DAC_ENCODER_CONTROL_PARAMETERS | ||
| 4761 | #define DAC1_ENCODER_CONTROL_PS_ALLOCATION DAC_ENCODER_CONTROL_PS_ALLOCATION | ||
| 4762 | |||
| 4763 | #define DAC2_ENCODER_CONTROL_PARAMETERS DAC_ENCODER_CONTROL_PARAMETERS | ||
| 4764 | #define DAC2_ENCODER_CONTROL_PS_ALLOCATION DAC_ENCODER_CONTROL_PS_ALLOCATION | ||
| 4765 | |||
| 4766 | #define ucDac1Standard ucDacStandard | ||
| 4767 | #define ucDac2Standard ucDacStandard | ||
| 4768 | |||
| 4769 | #define TMDS1EncoderControl TMDSAEncoderControl | ||
| 4770 | #define TMDS2EncoderControl LVTMAEncoderControl | ||
| 4771 | |||
| 4772 | #define DFP1OutputControl TMDSAOutputControl | ||
| 4773 | #define DFP2OutputControl LVTMAOutputControl | ||
| 4774 | #define CRT1OutputControl DAC1OutputControl | ||
| 4775 | #define CRT2OutputControl DAC2OutputControl | ||
| 4776 | |||
| 4777 | /* These two lines will be removed for sure in a few days, will follow up with Michael V. */ | ||
| 4778 | #define EnableLVDS_SS EnableSpreadSpectrumOnPPLL | ||
| 4779 | #define ENABLE_LVDS_SS_PARAMETERS_V3 ENABLE_SPREAD_SPECTRUM_ON_PPLL | ||
| 4780 | |||
| 4781 | /*********************************************************************************/ | ||
| 4782 | |||
| 4783 | #pragma pack() /* BIOS data must use byte aligment */ | ||
| 4784 | |||
| 4785 | #endif /* _ATOMBIOS_H */ | ||
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c new file mode 100644 index 000000000000..c0080cc9bf8d --- /dev/null +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
| @@ -0,0 +1,695 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2007-8 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * copy of this software and associated documentation files (the "Software"), | ||
| 7 | * to deal in the Software without restriction, including without limitation | ||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 10 | * Software is furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 21 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: Dave Airlie | ||
| 24 | * Alex Deucher | ||
| 25 | */ | ||
| 26 | #include <drm/drmP.h> | ||
| 27 | #include <drm/drm_crtc_helper.h> | ||
| 28 | #include <drm/radeon_drm.h> | ||
| 29 | #include "radeon_fixed.h" | ||
| 30 | #include "radeon.h" | ||
| 31 | #include "atom.h" | ||
| 32 | #include "atom-bits.h" | ||
| 33 | |||
| 34 | static void atombios_lock_crtc(struct drm_crtc *crtc, int lock) | ||
| 35 | { | ||
| 36 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 37 | struct drm_device *dev = crtc->dev; | ||
| 38 | struct radeon_device *rdev = dev->dev_private; | ||
| 39 | int index = | ||
| 40 | GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters); | ||
| 41 | ENABLE_CRTC_PS_ALLOCATION args; | ||
| 42 | |||
| 43 | memset(&args, 0, sizeof(args)); | ||
| 44 | |||
| 45 | args.ucCRTC = radeon_crtc->crtc_id; | ||
| 46 | args.ucEnable = lock; | ||
| 47 | |||
| 48 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 49 | } | ||
| 50 | |||
| 51 | static void atombios_enable_crtc(struct drm_crtc *crtc, int state) | ||
| 52 | { | ||
| 53 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 54 | struct drm_device *dev = crtc->dev; | ||
| 55 | struct radeon_device *rdev = dev->dev_private; | ||
| 56 | int index = GetIndexIntoMasterTable(COMMAND, EnableCRTC); | ||
| 57 | ENABLE_CRTC_PS_ALLOCATION args; | ||
| 58 | |||
| 59 | memset(&args, 0, sizeof(args)); | ||
| 60 | |||
| 61 | args.ucCRTC = radeon_crtc->crtc_id; | ||
| 62 | args.ucEnable = state; | ||
| 63 | |||
| 64 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 65 | } | ||
| 66 | |||
| 67 | static void atombios_enable_crtc_memreq(struct drm_crtc *crtc, int state) | ||
| 68 | { | ||
| 69 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 70 | struct drm_device *dev = crtc->dev; | ||
| 71 | struct radeon_device *rdev = dev->dev_private; | ||
| 72 | int index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq); | ||
| 73 | ENABLE_CRTC_PS_ALLOCATION args; | ||
| 74 | |||
| 75 | memset(&args, 0, sizeof(args)); | ||
| 76 | |||
| 77 | args.ucCRTC = radeon_crtc->crtc_id; | ||
| 78 | args.ucEnable = state; | ||
| 79 | |||
| 80 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 81 | } | ||
| 82 | |||
| 83 | static void atombios_blank_crtc(struct drm_crtc *crtc, int state) | ||
| 84 | { | ||
| 85 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 86 | struct drm_device *dev = crtc->dev; | ||
| 87 | struct radeon_device *rdev = dev->dev_private; | ||
| 88 | int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC); | ||
| 89 | BLANK_CRTC_PS_ALLOCATION args; | ||
| 90 | |||
| 91 | memset(&args, 0, sizeof(args)); | ||
| 92 | |||
| 93 | args.ucCRTC = radeon_crtc->crtc_id; | ||
| 94 | args.ucBlanking = state; | ||
| 95 | |||
| 96 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 97 | } | ||
| 98 | |||
| 99 | void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) | ||
| 100 | { | ||
| 101 | struct drm_device *dev = crtc->dev; | ||
| 102 | struct radeon_device *rdev = dev->dev_private; | ||
| 103 | |||
| 104 | switch (mode) { | ||
| 105 | case DRM_MODE_DPMS_ON: | ||
| 106 | if (ASIC_IS_DCE3(rdev)) | ||
| 107 | atombios_enable_crtc_memreq(crtc, 1); | ||
| 108 | atombios_enable_crtc(crtc, 1); | ||
| 109 | atombios_blank_crtc(crtc, 0); | ||
| 110 | break; | ||
| 111 | case DRM_MODE_DPMS_STANDBY: | ||
| 112 | case DRM_MODE_DPMS_SUSPEND: | ||
| 113 | case DRM_MODE_DPMS_OFF: | ||
| 114 | atombios_blank_crtc(crtc, 1); | ||
| 115 | atombios_enable_crtc(crtc, 0); | ||
| 116 | if (ASIC_IS_DCE3(rdev)) | ||
| 117 | atombios_enable_crtc_memreq(crtc, 0); | ||
| 118 | break; | ||
| 119 | } | ||
| 120 | |||
| 121 | if (mode != DRM_MODE_DPMS_OFF) { | ||
| 122 | radeon_crtc_load_lut(crtc); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | static void | ||
| 127 | atombios_set_crtc_dtd_timing(struct drm_crtc *crtc, | ||
| 128 | SET_CRTC_USING_DTD_TIMING_PARAMETERS * crtc_param) | ||
| 129 | { | ||
| 130 | struct drm_device *dev = crtc->dev; | ||
| 131 | struct radeon_device *rdev = dev->dev_private; | ||
| 132 | SET_CRTC_USING_DTD_TIMING_PARAMETERS conv_param; | ||
| 133 | int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming); | ||
| 134 | |||
| 135 | conv_param.usH_Size = cpu_to_le16(crtc_param->usH_Size); | ||
| 136 | conv_param.usH_Blanking_Time = | ||
| 137 | cpu_to_le16(crtc_param->usH_Blanking_Time); | ||
| 138 | conv_param.usV_Size = cpu_to_le16(crtc_param->usV_Size); | ||
| 139 | conv_param.usV_Blanking_Time = | ||
| 140 | cpu_to_le16(crtc_param->usV_Blanking_Time); | ||
| 141 | conv_param.usH_SyncOffset = cpu_to_le16(crtc_param->usH_SyncOffset); | ||
| 142 | conv_param.usH_SyncWidth = cpu_to_le16(crtc_param->usH_SyncWidth); | ||
| 143 | conv_param.usV_SyncOffset = cpu_to_le16(crtc_param->usV_SyncOffset); | ||
| 144 | conv_param.usV_SyncWidth = cpu_to_le16(crtc_param->usV_SyncWidth); | ||
| 145 | conv_param.susModeMiscInfo.usAccess = | ||
| 146 | cpu_to_le16(crtc_param->susModeMiscInfo.usAccess); | ||
| 147 | conv_param.ucCRTC = crtc_param->ucCRTC; | ||
| 148 | |||
| 149 | printk("executing set crtc dtd timing\n"); | ||
| 150 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&conv_param); | ||
| 151 | } | ||
| 152 | |||
| 153 | void atombios_crtc_set_timing(struct drm_crtc *crtc, | ||
| 154 | SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION * | ||
| 155 | crtc_param) | ||
| 156 | { | ||
| 157 | struct drm_device *dev = crtc->dev; | ||
| 158 | struct radeon_device *rdev = dev->dev_private; | ||
| 159 | SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION conv_param; | ||
| 160 | int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing); | ||
| 161 | |||
| 162 | conv_param.usH_Total = cpu_to_le16(crtc_param->usH_Total); | ||
| 163 | conv_param.usH_Disp = cpu_to_le16(crtc_param->usH_Disp); | ||
| 164 | conv_param.usH_SyncStart = cpu_to_le16(crtc_param->usH_SyncStart); | ||
| 165 | conv_param.usH_SyncWidth = cpu_to_le16(crtc_param->usH_SyncWidth); | ||
| 166 | conv_param.usV_Total = cpu_to_le16(crtc_param->usV_Total); | ||
| 167 | conv_param.usV_Disp = cpu_to_le16(crtc_param->usV_Disp); | ||
| 168 | conv_param.usV_SyncStart = cpu_to_le16(crtc_param->usV_SyncStart); | ||
| 169 | conv_param.usV_SyncWidth = cpu_to_le16(crtc_param->usV_SyncWidth); | ||
| 170 | conv_param.susModeMiscInfo.usAccess = | ||
| 171 | cpu_to_le16(crtc_param->susModeMiscInfo.usAccess); | ||
| 172 | conv_param.ucCRTC = crtc_param->ucCRTC; | ||
| 173 | conv_param.ucOverscanRight = crtc_param->ucOverscanRight; | ||
| 174 | conv_param.ucOverscanLeft = crtc_param->ucOverscanLeft; | ||
| 175 | conv_param.ucOverscanBottom = crtc_param->ucOverscanBottom; | ||
| 176 | conv_param.ucOverscanTop = crtc_param->ucOverscanTop; | ||
| 177 | conv_param.ucReserved = crtc_param->ucReserved; | ||
| 178 | |||
| 179 | printk("executing set crtc timing\n"); | ||
| 180 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&conv_param); | ||
| 181 | } | ||
| 182 | |||
| 183 | void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | ||
| 184 | { | ||
| 185 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 186 | struct drm_device *dev = crtc->dev; | ||
| 187 | struct radeon_device *rdev = dev->dev_private; | ||
| 188 | struct drm_encoder *encoder = NULL; | ||
| 189 | struct radeon_encoder *radeon_encoder = NULL; | ||
| 190 | uint8_t frev, crev; | ||
| 191 | int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); | ||
| 192 | SET_PIXEL_CLOCK_PS_ALLOCATION args; | ||
| 193 | PIXEL_CLOCK_PARAMETERS *spc1_ptr; | ||
| 194 | PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr; | ||
| 195 | PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr; | ||
| 196 | uint32_t sclock = mode->clock; | ||
| 197 | uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; | ||
| 198 | struct radeon_pll *pll; | ||
| 199 | int pll_flags = 0; | ||
| 200 | |||
| 201 | memset(&args, 0, sizeof(args)); | ||
| 202 | |||
| 203 | if (ASIC_IS_AVIVO(rdev)) { | ||
| 204 | uint32_t ss_cntl; | ||
| 205 | |||
| 206 | if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */ | ||
| 207 | pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; | ||
| 208 | else | ||
| 209 | pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; | ||
| 210 | |||
| 211 | /* disable spread spectrum clocking for now -- thanks Hedy Lamarr */ | ||
| 212 | if (radeon_crtc->crtc_id == 0) { | ||
| 213 | ss_cntl = RREG32(AVIVO_P1PLL_INT_SS_CNTL); | ||
| 214 | WREG32(AVIVO_P1PLL_INT_SS_CNTL, ss_cntl & ~1); | ||
| 215 | } else { | ||
| 216 | ss_cntl = RREG32(AVIVO_P2PLL_INT_SS_CNTL); | ||
| 217 | WREG32(AVIVO_P2PLL_INT_SS_CNTL, ss_cntl & ~1); | ||
| 218 | } | ||
| 219 | } else { | ||
| 220 | pll_flags |= RADEON_PLL_LEGACY; | ||
| 221 | |||
| 222 | if (mode->clock > 200000) /* range limits??? */ | ||
| 223 | pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; | ||
| 224 | else | ||
| 225 | pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; | ||
| 226 | |||
| 227 | } | ||
| 228 | |||
| 229 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 230 | if (encoder->crtc == crtc) { | ||
| 231 | if (!ASIC_IS_AVIVO(rdev)) { | ||
| 232 | if (encoder->encoder_type != | ||
| 233 | DRM_MODE_ENCODER_DAC) | ||
| 234 | pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; | ||
| 235 | if (!ASIC_IS_AVIVO(rdev) | ||
| 236 | && (encoder->encoder_type == | ||
| 237 | DRM_MODE_ENCODER_LVDS)) | ||
| 238 | pll_flags |= RADEON_PLL_USE_REF_DIV; | ||
| 239 | } | ||
| 240 | radeon_encoder = to_radeon_encoder(encoder); | ||
| 241 | } | ||
| 242 | } | ||
| 243 | |||
| 244 | if (radeon_crtc->crtc_id == 0) | ||
| 245 | pll = &rdev->clock.p1pll; | ||
| 246 | else | ||
| 247 | pll = &rdev->clock.p2pll; | ||
| 248 | |||
| 249 | radeon_compute_pll(pll, mode->clock, &sclock, &fb_div, &frac_fb_div, | ||
| 250 | &ref_div, &post_div, pll_flags); | ||
| 251 | |||
| 252 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, | ||
| 253 | &crev); | ||
| 254 | |||
| 255 | switch (frev) { | ||
| 256 | case 1: | ||
| 257 | switch (crev) { | ||
| 258 | case 1: | ||
| 259 | spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput; | ||
| 260 | spc1_ptr->usPixelClock = cpu_to_le16(sclock); | ||
| 261 | spc1_ptr->usRefDiv = cpu_to_le16(ref_div); | ||
| 262 | spc1_ptr->usFbDiv = cpu_to_le16(fb_div); | ||
| 263 | spc1_ptr->ucFracFbDiv = frac_fb_div; | ||
| 264 | spc1_ptr->ucPostDiv = post_div; | ||
| 265 | spc1_ptr->ucPpll = | ||
| 266 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | ||
| 267 | spc1_ptr->ucCRTC = radeon_crtc->crtc_id; | ||
| 268 | spc1_ptr->ucRefDivSrc = 1; | ||
| 269 | break; | ||
| 270 | case 2: | ||
| 271 | spc2_ptr = | ||
| 272 | (PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput; | ||
| 273 | spc2_ptr->usPixelClock = cpu_to_le16(sclock); | ||
| 274 | spc2_ptr->usRefDiv = cpu_to_le16(ref_div); | ||
| 275 | spc2_ptr->usFbDiv = cpu_to_le16(fb_div); | ||
| 276 | spc2_ptr->ucFracFbDiv = frac_fb_div; | ||
| 277 | spc2_ptr->ucPostDiv = post_div; | ||
| 278 | spc2_ptr->ucPpll = | ||
| 279 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | ||
| 280 | spc2_ptr->ucCRTC = radeon_crtc->crtc_id; | ||
| 281 | spc2_ptr->ucRefDivSrc = 1; | ||
| 282 | break; | ||
| 283 | case 3: | ||
| 284 | if (!encoder) | ||
| 285 | return; | ||
| 286 | spc3_ptr = | ||
| 287 | (PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput; | ||
| 288 | spc3_ptr->usPixelClock = cpu_to_le16(sclock); | ||
| 289 | spc3_ptr->usRefDiv = cpu_to_le16(ref_div); | ||
| 290 | spc3_ptr->usFbDiv = cpu_to_le16(fb_div); | ||
| 291 | spc3_ptr->ucFracFbDiv = frac_fb_div; | ||
| 292 | spc3_ptr->ucPostDiv = post_div; | ||
| 293 | spc3_ptr->ucPpll = | ||
| 294 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | ||
| 295 | spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2); | ||
| 296 | spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id; | ||
| 297 | spc3_ptr->ucEncoderMode = | ||
| 298 | atombios_get_encoder_mode(encoder); | ||
| 299 | break; | ||
| 300 | default: | ||
| 301 | DRM_ERROR("Unknown table version %d %d\n", frev, crev); | ||
| 302 | return; | ||
| 303 | } | ||
| 304 | break; | ||
| 305 | default: | ||
| 306 | DRM_ERROR("Unknown table version %d %d\n", frev, crev); | ||
| 307 | return; | ||
| 308 | } | ||
| 309 | |||
| 310 | printk("executing set pll\n"); | ||
| 311 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 312 | } | ||
| 313 | |||
| 314 | int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, | ||
| 315 | struct drm_framebuffer *old_fb) | ||
| 316 | { | ||
| 317 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 318 | struct drm_device *dev = crtc->dev; | ||
| 319 | struct radeon_device *rdev = dev->dev_private; | ||
| 320 | struct radeon_framebuffer *radeon_fb; | ||
| 321 | struct drm_gem_object *obj; | ||
| 322 | struct drm_radeon_gem_object *obj_priv; | ||
| 323 | uint64_t fb_location; | ||
| 324 | uint32_t fb_format, fb_pitch_pixels; | ||
| 325 | |||
| 326 | if (!crtc->fb) | ||
| 327 | return -EINVAL; | ||
| 328 | |||
| 329 | radeon_fb = to_radeon_framebuffer(crtc->fb); | ||
| 330 | |||
| 331 | obj = radeon_fb->obj; | ||
| 332 | obj_priv = obj->driver_private; | ||
| 333 | |||
| 334 | if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &fb_location)) { | ||
| 335 | return -EINVAL; | ||
| 336 | } | ||
| 337 | |||
| 338 | switch (crtc->fb->bits_per_pixel) { | ||
| 339 | case 15: | ||
| 340 | fb_format = | ||
| 341 | AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | | ||
| 342 | AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555; | ||
| 343 | break; | ||
| 344 | case 16: | ||
| 345 | fb_format = | ||
| 346 | AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | | ||
| 347 | AVIVO_D1GRPH_CONTROL_16BPP_RGB565; | ||
| 348 | break; | ||
| 349 | case 24: | ||
| 350 | case 32: | ||
| 351 | fb_format = | ||
| 352 | AVIVO_D1GRPH_CONTROL_DEPTH_32BPP | | ||
| 353 | AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888; | ||
| 354 | break; | ||
| 355 | default: | ||
| 356 | DRM_ERROR("Unsupported screen depth %d\n", | ||
| 357 | crtc->fb->bits_per_pixel); | ||
| 358 | return -EINVAL; | ||
| 359 | } | ||
| 360 | |||
| 361 | /* TODO tiling */ | ||
| 362 | if (radeon_crtc->crtc_id == 0) | ||
| 363 | WREG32(AVIVO_D1VGA_CONTROL, 0); | ||
| 364 | else | ||
| 365 | WREG32(AVIVO_D2VGA_CONTROL, 0); | ||
| 366 | WREG32(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, | ||
| 367 | (u32) fb_location); | ||
| 368 | WREG32(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + | ||
| 369 | radeon_crtc->crtc_offset, (u32) fb_location); | ||
| 370 | WREG32(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format); | ||
| 371 | |||
| 372 | WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0); | ||
| 373 | WREG32(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0); | ||
| 374 | WREG32(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, 0); | ||
| 375 | WREG32(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, 0); | ||
| 376 | WREG32(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, crtc->fb->width); | ||
| 377 | WREG32(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, crtc->fb->height); | ||
| 378 | |||
| 379 | fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8); | ||
| 380 | WREG32(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels); | ||
| 381 | WREG32(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1); | ||
| 382 | |||
| 383 | WREG32(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset, | ||
| 384 | crtc->mode.vdisplay); | ||
| 385 | x &= ~3; | ||
| 386 | y &= ~1; | ||
| 387 | WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, | ||
| 388 | (x << 16) | y); | ||
| 389 | WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, | ||
| 390 | (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); | ||
| 391 | |||
| 392 | if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) | ||
| 393 | WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, | ||
| 394 | AVIVO_D1MODE_INTERLEAVE_EN); | ||
| 395 | else | ||
| 396 | WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0); | ||
| 397 | |||
| 398 | if (old_fb && old_fb != crtc->fb) { | ||
| 399 | radeon_fb = to_radeon_framebuffer(old_fb); | ||
| 400 | radeon_gem_object_unpin(radeon_fb->obj); | ||
| 401 | } | ||
| 402 | return 0; | ||
| 403 | } | ||
| 404 | |||
| 405 | int atombios_crtc_mode_set(struct drm_crtc *crtc, | ||
| 406 | struct drm_display_mode *mode, | ||
| 407 | struct drm_display_mode *adjusted_mode, | ||
| 408 | int x, int y, struct drm_framebuffer *old_fb) | ||
| 409 | { | ||
| 410 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 411 | struct drm_device *dev = crtc->dev; | ||
| 412 | struct radeon_device *rdev = dev->dev_private; | ||
| 413 | struct drm_encoder *encoder; | ||
| 414 | SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing; | ||
| 415 | |||
| 416 | /* TODO color tiling */ | ||
| 417 | memset(&crtc_timing, 0, sizeof(crtc_timing)); | ||
| 418 | |||
| 419 | /* TODO tv */ | ||
| 420 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 421 | |||
| 422 | } | ||
| 423 | |||
| 424 | crtc_timing.ucCRTC = radeon_crtc->crtc_id; | ||
| 425 | crtc_timing.usH_Total = adjusted_mode->crtc_htotal; | ||
| 426 | crtc_timing.usH_Disp = adjusted_mode->crtc_hdisplay; | ||
| 427 | crtc_timing.usH_SyncStart = adjusted_mode->crtc_hsync_start; | ||
| 428 | crtc_timing.usH_SyncWidth = | ||
| 429 | adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start; | ||
| 430 | |||
| 431 | crtc_timing.usV_Total = adjusted_mode->crtc_vtotal; | ||
| 432 | crtc_timing.usV_Disp = adjusted_mode->crtc_vdisplay; | ||
| 433 | crtc_timing.usV_SyncStart = adjusted_mode->crtc_vsync_start; | ||
| 434 | crtc_timing.usV_SyncWidth = | ||
| 435 | adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start; | ||
| 436 | |||
| 437 | if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
| 438 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY; | ||
| 439 | |||
| 440 | if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
| 441 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY; | ||
| 442 | |||
| 443 | if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC) | ||
| 444 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC; | ||
| 445 | |||
| 446 | if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) | ||
| 447 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE; | ||
| 448 | |||
| 449 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) | ||
| 450 | crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE; | ||
| 451 | |||
| 452 | atombios_crtc_set_pll(crtc, adjusted_mode); | ||
| 453 | atombios_crtc_set_timing(crtc, &crtc_timing); | ||
| 454 | |||
| 455 | if (ASIC_IS_AVIVO(rdev)) | ||
| 456 | atombios_crtc_set_base(crtc, x, y, old_fb); | ||
| 457 | else { | ||
| 458 | if (radeon_crtc->crtc_id == 0) { | ||
| 459 | SET_CRTC_USING_DTD_TIMING_PARAMETERS crtc_dtd_timing; | ||
| 460 | memset(&crtc_dtd_timing, 0, sizeof(crtc_dtd_timing)); | ||
| 461 | |||
| 462 | /* setup FP shadow regs on R4xx */ | ||
| 463 | crtc_dtd_timing.ucCRTC = radeon_crtc->crtc_id; | ||
| 464 | crtc_dtd_timing.usH_Size = adjusted_mode->crtc_hdisplay; | ||
| 465 | crtc_dtd_timing.usV_Size = adjusted_mode->crtc_vdisplay; | ||
| 466 | crtc_dtd_timing.usH_Blanking_Time = | ||
| 467 | adjusted_mode->crtc_hblank_end - | ||
| 468 | adjusted_mode->crtc_hdisplay; | ||
| 469 | crtc_dtd_timing.usV_Blanking_Time = | ||
| 470 | adjusted_mode->crtc_vblank_end - | ||
| 471 | adjusted_mode->crtc_vdisplay; | ||
| 472 | crtc_dtd_timing.usH_SyncOffset = | ||
| 473 | adjusted_mode->crtc_hsync_start - | ||
| 474 | adjusted_mode->crtc_hdisplay; | ||
| 475 | crtc_dtd_timing.usV_SyncOffset = | ||
| 476 | adjusted_mode->crtc_vsync_start - | ||
| 477 | adjusted_mode->crtc_vdisplay; | ||
| 478 | crtc_dtd_timing.usH_SyncWidth = | ||
| 479 | adjusted_mode->crtc_hsync_end - | ||
| 480 | adjusted_mode->crtc_hsync_start; | ||
| 481 | crtc_dtd_timing.usV_SyncWidth = | ||
| 482 | adjusted_mode->crtc_vsync_end - | ||
| 483 | adjusted_mode->crtc_vsync_start; | ||
| 484 | /* crtc_dtd_timing.ucH_Border = adjusted_mode->crtc_hborder; */ | ||
| 485 | /* crtc_dtd_timing.ucV_Border = adjusted_mode->crtc_vborder; */ | ||
| 486 | |||
| 487 | if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
| 488 | crtc_dtd_timing.susModeMiscInfo.usAccess |= | ||
| 489 | ATOM_VSYNC_POLARITY; | ||
| 490 | |||
| 491 | if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
| 492 | crtc_dtd_timing.susModeMiscInfo.usAccess |= | ||
| 493 | ATOM_HSYNC_POLARITY; | ||
| 494 | |||
| 495 | if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC) | ||
| 496 | crtc_dtd_timing.susModeMiscInfo.usAccess |= | ||
| 497 | ATOM_COMPOSITESYNC; | ||
| 498 | |||
| 499 | if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) | ||
| 500 | crtc_dtd_timing.susModeMiscInfo.usAccess |= | ||
| 501 | ATOM_INTERLACE; | ||
| 502 | |||
| 503 | if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) | ||
| 504 | crtc_dtd_timing.susModeMiscInfo.usAccess |= | ||
| 505 | ATOM_DOUBLE_CLOCK_MODE; | ||
| 506 | |||
| 507 | atombios_set_crtc_dtd_timing(crtc, &crtc_dtd_timing); | ||
| 508 | } | ||
| 509 | radeon_crtc_set_base(crtc, x, y, old_fb); | ||
| 510 | radeon_legacy_atom_set_surface(crtc); | ||
| 511 | } | ||
| 512 | return 0; | ||
| 513 | } | ||
| 514 | |||
| 515 | static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, | ||
| 516 | struct drm_display_mode *mode, | ||
| 517 | struct drm_display_mode *adjusted_mode) | ||
| 518 | { | ||
| 519 | return true; | ||
| 520 | } | ||
| 521 | |||
| 522 | static void atombios_crtc_prepare(struct drm_crtc *crtc) | ||
| 523 | { | ||
| 524 | atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); | ||
| 525 | atombios_lock_crtc(crtc, 1); | ||
| 526 | } | ||
| 527 | |||
| 528 | static void atombios_crtc_commit(struct drm_crtc *crtc) | ||
| 529 | { | ||
| 530 | atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON); | ||
| 531 | atombios_lock_crtc(crtc, 0); | ||
| 532 | } | ||
| 533 | |||
| 534 | static const struct drm_crtc_helper_funcs atombios_helper_funcs = { | ||
| 535 | .dpms = atombios_crtc_dpms, | ||
| 536 | .mode_fixup = atombios_crtc_mode_fixup, | ||
| 537 | .mode_set = atombios_crtc_mode_set, | ||
| 538 | .mode_set_base = atombios_crtc_set_base, | ||
| 539 | .prepare = atombios_crtc_prepare, | ||
| 540 | .commit = atombios_crtc_commit, | ||
| 541 | }; | ||
| 542 | |||
| 543 | void radeon_atombios_init_crtc(struct drm_device *dev, | ||
| 544 | struct radeon_crtc *radeon_crtc) | ||
| 545 | { | ||
| 546 | if (radeon_crtc->crtc_id == 1) | ||
| 547 | radeon_crtc->crtc_offset = | ||
| 548 | AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL; | ||
| 549 | drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs); | ||
| 550 | } | ||
| 551 | |||
| 552 | void radeon_init_disp_bw_avivo(struct drm_device *dev, | ||
| 553 | struct drm_display_mode *mode1, | ||
| 554 | uint32_t pixel_bytes1, | ||
| 555 | struct drm_display_mode *mode2, | ||
| 556 | uint32_t pixel_bytes2) | ||
| 557 | { | ||
| 558 | struct radeon_device *rdev = dev->dev_private; | ||
| 559 | fixed20_12 min_mem_eff; | ||
| 560 | fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff; | ||
| 561 | fixed20_12 sclk_ff, mclk_ff; | ||
| 562 | uint32_t dc_lb_memory_split, temp; | ||
| 563 | |||
| 564 | min_mem_eff.full = rfixed_const_8(0); | ||
| 565 | if (rdev->disp_priority == 2) { | ||
| 566 | uint32_t mc_init_misc_lat_timer = 0; | ||
| 567 | if (rdev->family == CHIP_RV515) | ||
| 568 | mc_init_misc_lat_timer = | ||
| 569 | RREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER); | ||
| 570 | else if (rdev->family == CHIP_RS690) | ||
| 571 | mc_init_misc_lat_timer = | ||
| 572 | RREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER); | ||
| 573 | |||
| 574 | mc_init_misc_lat_timer &= | ||
| 575 | ~(R300_MC_DISP1R_INIT_LAT_MASK << | ||
| 576 | R300_MC_DISP1R_INIT_LAT_SHIFT); | ||
| 577 | mc_init_misc_lat_timer &= | ||
| 578 | ~(R300_MC_DISP0R_INIT_LAT_MASK << | ||
| 579 | R300_MC_DISP0R_INIT_LAT_SHIFT); | ||
| 580 | |||
| 581 | if (mode2) | ||
| 582 | mc_init_misc_lat_timer |= | ||
| 583 | (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); | ||
| 584 | if (mode1) | ||
| 585 | mc_init_misc_lat_timer |= | ||
| 586 | (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); | ||
| 587 | |||
| 588 | if (rdev->family == CHIP_RV515) | ||
| 589 | WREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER, | ||
| 590 | mc_init_misc_lat_timer); | ||
| 591 | else if (rdev->family == CHIP_RS690) | ||
| 592 | WREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER, | ||
| 593 | mc_init_misc_lat_timer); | ||
| 594 | } | ||
| 595 | |||
| 596 | /* | ||
| 597 | * determine is there is enough bw for current mode | ||
| 598 | */ | ||
| 599 | temp_ff.full = rfixed_const(100); | ||
| 600 | mclk_ff.full = rfixed_const(rdev->clock.default_mclk); | ||
| 601 | mclk_ff.full = rfixed_div(mclk_ff, temp_ff); | ||
| 602 | sclk_ff.full = rfixed_const(rdev->clock.default_sclk); | ||
| 603 | sclk_ff.full = rfixed_div(sclk_ff, temp_ff); | ||
| 604 | |||
| 605 | temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); | ||
| 606 | temp_ff.full = rfixed_const(temp); | ||
| 607 | mem_bw.full = rfixed_mul(mclk_ff, temp_ff); | ||
| 608 | mem_bw.full = rfixed_mul(mem_bw, min_mem_eff); | ||
| 609 | |||
| 610 | pix_clk.full = 0; | ||
| 611 | pix_clk2.full = 0; | ||
| 612 | peak_disp_bw.full = 0; | ||
| 613 | if (mode1) { | ||
| 614 | temp_ff.full = rfixed_const(1000); | ||
| 615 | pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */ | ||
| 616 | pix_clk.full = rfixed_div(pix_clk, temp_ff); | ||
| 617 | temp_ff.full = rfixed_const(pixel_bytes1); | ||
| 618 | peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff); | ||
| 619 | } | ||
| 620 | if (mode2) { | ||
| 621 | temp_ff.full = rfixed_const(1000); | ||
| 622 | pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */ | ||
| 623 | pix_clk2.full = rfixed_div(pix_clk2, temp_ff); | ||
| 624 | temp_ff.full = rfixed_const(pixel_bytes2); | ||
| 625 | peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff); | ||
| 626 | } | ||
| 627 | |||
| 628 | if (peak_disp_bw.full >= mem_bw.full) { | ||
| 629 | DRM_ERROR | ||
| 630 | ("You may not have enough display bandwidth for current mode\n" | ||
| 631 | "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); | ||
| 632 | printk("peak disp bw %d, mem_bw %d\n", | ||
| 633 | rfixed_trunc(peak_disp_bw), rfixed_trunc(mem_bw)); | ||
| 634 | } | ||
| 635 | |||
| 636 | /* | ||
| 637 | * Line Buffer Setup | ||
| 638 | * There is a single line buffer shared by both display controllers. | ||
| 639 | * DC_LB_MEMORY_SPLIT controls how that line buffer is shared between the display | ||
| 640 | * controllers. The paritioning can either be done manually or via one of four | ||
| 641 | * preset allocations specified in bits 1:0: | ||
| 642 | * 0 - line buffer is divided in half and shared between each display controller | ||
| 643 | * 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4 | ||
| 644 | * 2 - D1 gets the whole buffer | ||
| 645 | * 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4 | ||
| 646 | * Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual allocation mode. | ||
| 647 | * In manual allocation mode, D1 always starts at 0, D1 end/2 is specified in bits | ||
| 648 | * 14:4; D2 allocation follows D1. | ||
| 649 | */ | ||
| 650 | |||
| 651 | /* is auto or manual better ? */ | ||
| 652 | dc_lb_memory_split = | ||
| 653 | RREG32(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK; | ||
| 654 | dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE; | ||
| 655 | #if 1 | ||
| 656 | /* auto */ | ||
| 657 | if (mode1 && mode2) { | ||
| 658 | if (mode1->hdisplay > mode2->hdisplay) { | ||
| 659 | if (mode1->hdisplay > 2560) | ||
| 660 | dc_lb_memory_split |= | ||
| 661 | AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q; | ||
| 662 | else | ||
| 663 | dc_lb_memory_split |= | ||
| 664 | AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; | ||
| 665 | } else if (mode2->hdisplay > mode1->hdisplay) { | ||
| 666 | if (mode2->hdisplay > 2560) | ||
| 667 | dc_lb_memory_split |= | ||
| 668 | AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; | ||
| 669 | else | ||
| 670 | dc_lb_memory_split |= | ||
| 671 | AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; | ||
| 672 | } else | ||
| 673 | dc_lb_memory_split |= | ||
| 674 | AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF; | ||
| 675 | } else if (mode1) { | ||
| 676 | dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY; | ||
| 677 | } else if (mode2) { | ||
| 678 | dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q; | ||
| 679 | } | ||
| 680 | #else | ||
| 681 | /* manual */ | ||
| 682 | dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE; | ||
| 683 | dc_lb_memory_split &= | ||
| 684 | ~(AVIVO_DC_LB_DISP1_END_ADR_MASK << | ||
| 685 | AVIVO_DC_LB_DISP1_END_ADR_SHIFT); | ||
| 686 | if (mode1) { | ||
| 687 | dc_lb_memory_split |= | ||
| 688 | ((((mode1->hdisplay / 2) + 64) & AVIVO_DC_LB_DISP1_END_ADR_MASK) | ||
| 689 | << AVIVO_DC_LB_DISP1_END_ADR_SHIFT); | ||
| 690 | } else if (mode2) { | ||
| 691 | dc_lb_memory_split |= (0 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT); | ||
| 692 | } | ||
| 693 | #endif | ||
| 694 | WREG32(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split); | ||
| 695 | } | ||
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c new file mode 100644 index 000000000000..5225f5be7ea7 --- /dev/null +++ b/drivers/gpu/drm/radeon/r100.c | |||
| @@ -0,0 +1,1524 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include <linux/seq_file.h> | ||
| 29 | #include "drmP.h" | ||
| 30 | #include "drm.h" | ||
| 31 | #include "radeon_drm.h" | ||
| 32 | #include "radeon_microcode.h" | ||
| 33 | #include "radeon_reg.h" | ||
| 34 | #include "radeon.h" | ||
| 35 | |||
| 36 | /* This files gather functions specifics to: | ||
| 37 | * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 | ||
| 38 | * | ||
| 39 | * Some of these functions might be used by newer ASICs. | ||
| 40 | */ | ||
| 41 | void r100_hdp_reset(struct radeon_device *rdev); | ||
| 42 | void r100_gpu_init(struct radeon_device *rdev); | ||
| 43 | int r100_gui_wait_for_idle(struct radeon_device *rdev); | ||
| 44 | int r100_mc_wait_for_idle(struct radeon_device *rdev); | ||
| 45 | void r100_gpu_wait_for_vsync(struct radeon_device *rdev); | ||
| 46 | void r100_gpu_wait_for_vsync2(struct radeon_device *rdev); | ||
| 47 | int r100_debugfs_mc_info_init(struct radeon_device *rdev); | ||
| 48 | |||
| 49 | |||
| 50 | /* | ||
| 51 | * PCI GART | ||
| 52 | */ | ||
| 53 | void r100_pci_gart_tlb_flush(struct radeon_device *rdev) | ||
| 54 | { | ||
| 55 | /* TODO: can we do somethings here ? */ | ||
| 56 | /* It seems hw only cache one entry so we should discard this | ||
| 57 | * entry otherwise if first GPU GART read hit this entry it | ||
| 58 | * could end up in wrong address. */ | ||
| 59 | } | ||
| 60 | |||
| 61 | int r100_pci_gart_enable(struct radeon_device *rdev) | ||
| 62 | { | ||
| 63 | uint32_t tmp; | ||
| 64 | int r; | ||
| 65 | |||
| 66 | /* Initialize common gart structure */ | ||
| 67 | r = radeon_gart_init(rdev); | ||
| 68 | if (r) { | ||
| 69 | return r; | ||
| 70 | } | ||
| 71 | if (rdev->gart.table.ram.ptr == NULL) { | ||
| 72 | rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; | ||
| 73 | r = radeon_gart_table_ram_alloc(rdev); | ||
| 74 | if (r) { | ||
| 75 | return r; | ||
| 76 | } | ||
| 77 | } | ||
| 78 | /* discard memory request outside of configured range */ | ||
| 79 | tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; | ||
| 80 | WREG32(RADEON_AIC_CNTL, tmp); | ||
| 81 | /* set address range for PCI address translate */ | ||
| 82 | WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_location); | ||
| 83 | tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; | ||
| 84 | WREG32(RADEON_AIC_HI_ADDR, tmp); | ||
| 85 | /* Enable bus mastering */ | ||
| 86 | tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; | ||
| 87 | WREG32(RADEON_BUS_CNTL, tmp); | ||
| 88 | /* set PCI GART page-table base address */ | ||
| 89 | WREG32(RADEON_AIC_PT_BASE, rdev->gart.table_addr); | ||
| 90 | tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN; | ||
| 91 | WREG32(RADEON_AIC_CNTL, tmp); | ||
| 92 | r100_pci_gart_tlb_flush(rdev); | ||
| 93 | rdev->gart.ready = true; | ||
| 94 | return 0; | ||
| 95 | } | ||
| 96 | |||
| 97 | void r100_pci_gart_disable(struct radeon_device *rdev) | ||
| 98 | { | ||
| 99 | uint32_t tmp; | ||
| 100 | |||
| 101 | /* discard memory request outside of configured range */ | ||
| 102 | tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; | ||
| 103 | WREG32(RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN); | ||
| 104 | WREG32(RADEON_AIC_LO_ADDR, 0); | ||
| 105 | WREG32(RADEON_AIC_HI_ADDR, 0); | ||
| 106 | } | ||
| 107 | |||
| 108 | int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) | ||
| 109 | { | ||
| 110 | if (i < 0 || i > rdev->gart.num_gpu_pages) { | ||
| 111 | return -EINVAL; | ||
| 112 | } | ||
| 113 | rdev->gart.table.ram.ptr[i] = cpu_to_le32((uint32_t)addr); | ||
| 114 | return 0; | ||
| 115 | } | ||
| 116 | |||
| 117 | int r100_gart_enable(struct radeon_device *rdev) | ||
| 118 | { | ||
| 119 | if (rdev->flags & RADEON_IS_AGP) { | ||
| 120 | r100_pci_gart_disable(rdev); | ||
| 121 | return 0; | ||
| 122 | } | ||
| 123 | return r100_pci_gart_enable(rdev); | ||
| 124 | } | ||
| 125 | |||
| 126 | |||
| 127 | /* | ||
| 128 | * MC | ||
| 129 | */ | ||
| 130 | void r100_mc_disable_clients(struct radeon_device *rdev) | ||
| 131 | { | ||
| 132 | uint32_t ov0_scale_cntl, crtc_ext_cntl, crtc_gen_cntl, crtc2_gen_cntl; | ||
| 133 | |||
| 134 | /* FIXME: is this function correct for rs100,rs200,rs300 ? */ | ||
| 135 | if (r100_gui_wait_for_idle(rdev)) { | ||
| 136 | printk(KERN_WARNING "Failed to wait GUI idle while " | ||
| 137 | "programming pipes. Bad things might happen.\n"); | ||
| 138 | } | ||
| 139 | |||
| 140 | /* stop display and memory access */ | ||
| 141 | ov0_scale_cntl = RREG32(RADEON_OV0_SCALE_CNTL); | ||
| 142 | WREG32(RADEON_OV0_SCALE_CNTL, ov0_scale_cntl & ~RADEON_SCALER_ENABLE); | ||
| 143 | crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); | ||
| 144 | WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl | RADEON_CRTC_DISPLAY_DIS); | ||
| 145 | crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); | ||
| 146 | |||
| 147 | r100_gpu_wait_for_vsync(rdev); | ||
| 148 | |||
| 149 | WREG32(RADEON_CRTC_GEN_CNTL, | ||
| 150 | (crtc_gen_cntl & ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_ICON_EN)) | | ||
| 151 | RADEON_CRTC_DISP_REQ_EN_B | RADEON_CRTC_EXT_DISP_EN); | ||
| 152 | |||
| 153 | if (!(rdev->flags & RADEON_SINGLE_CRTC)) { | ||
| 154 | crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); | ||
| 155 | |||
| 156 | r100_gpu_wait_for_vsync2(rdev); | ||
| 157 | WREG32(RADEON_CRTC2_GEN_CNTL, | ||
| 158 | (crtc2_gen_cntl & | ||
| 159 | ~(RADEON_CRTC2_CUR_EN | RADEON_CRTC2_ICON_EN)) | | ||
| 160 | RADEON_CRTC2_DISP_REQ_EN_B); | ||
| 161 | } | ||
| 162 | |||
| 163 | udelay(500); | ||
| 164 | } | ||
| 165 | |||
| 166 | void r100_mc_setup(struct radeon_device *rdev) | ||
| 167 | { | ||
| 168 | uint32_t tmp; | ||
| 169 | int r; | ||
| 170 | |||
| 171 | r = r100_debugfs_mc_info_init(rdev); | ||
| 172 | if (r) { | ||
| 173 | DRM_ERROR("Failed to register debugfs file for R100 MC !\n"); | ||
| 174 | } | ||
| 175 | /* Write VRAM size in case we are limiting it */ | ||
| 176 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); | ||
| 177 | tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; | ||
| 178 | tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16); | ||
| 179 | tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16); | ||
| 180 | WREG32(RADEON_MC_FB_LOCATION, tmp); | ||
| 181 | |||
| 182 | /* Enable bus mastering */ | ||
| 183 | tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; | ||
| 184 | WREG32(RADEON_BUS_CNTL, tmp); | ||
| 185 | |||
| 186 | if (rdev->flags & RADEON_IS_AGP) { | ||
| 187 | tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; | ||
| 188 | tmp = REG_SET(RADEON_MC_AGP_TOP, tmp >> 16); | ||
| 189 | tmp |= REG_SET(RADEON_MC_AGP_START, rdev->mc.gtt_location >> 16); | ||
| 190 | WREG32(RADEON_MC_AGP_LOCATION, tmp); | ||
| 191 | WREG32(RADEON_AGP_BASE, rdev->mc.agp_base); | ||
| 192 | } else { | ||
| 193 | WREG32(RADEON_MC_AGP_LOCATION, 0x0FFFFFFF); | ||
| 194 | WREG32(RADEON_AGP_BASE, 0); | ||
| 195 | } | ||
| 196 | |||
| 197 | tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL; | ||
| 198 | tmp |= (7 << 28); | ||
| 199 | WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE); | ||
| 200 | (void)RREG32(RADEON_HOST_PATH_CNTL); | ||
| 201 | WREG32(RADEON_HOST_PATH_CNTL, tmp); | ||
| 202 | (void)RREG32(RADEON_HOST_PATH_CNTL); | ||
| 203 | } | ||
| 204 | |||
| 205 | int r100_mc_init(struct radeon_device *rdev) | ||
| 206 | { | ||
| 207 | int r; | ||
| 208 | |||
| 209 | if (r100_debugfs_rbbm_init(rdev)) { | ||
| 210 | DRM_ERROR("Failed to register debugfs file for RBBM !\n"); | ||
| 211 | } | ||
| 212 | |||
| 213 | r100_gpu_init(rdev); | ||
| 214 | /* Disable gart which also disable out of gart access */ | ||
| 215 | r100_pci_gart_disable(rdev); | ||
| 216 | |||
| 217 | /* Setup GPU memory space */ | ||
| 218 | rdev->mc.vram_location = 0xFFFFFFFFUL; | ||
| 219 | rdev->mc.gtt_location = 0xFFFFFFFFUL; | ||
| 220 | if (rdev->flags & RADEON_IS_AGP) { | ||
| 221 | r = radeon_agp_init(rdev); | ||
| 222 | if (r) { | ||
| 223 | printk(KERN_WARNING "[drm] Disabling AGP\n"); | ||
| 224 | rdev->flags &= ~RADEON_IS_AGP; | ||
| 225 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; | ||
| 226 | } else { | ||
| 227 | rdev->mc.gtt_location = rdev->mc.agp_base; | ||
| 228 | } | ||
| 229 | } | ||
| 230 | r = radeon_mc_setup(rdev); | ||
| 231 | if (r) { | ||
| 232 | return r; | ||
| 233 | } | ||
| 234 | |||
| 235 | r100_mc_disable_clients(rdev); | ||
| 236 | if (r100_mc_wait_for_idle(rdev)) { | ||
| 237 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 238 | "programming pipes. Bad things might happen.\n"); | ||
| 239 | } | ||
| 240 | |||
| 241 | r100_mc_setup(rdev); | ||
| 242 | return 0; | ||
| 243 | } | ||
| 244 | |||
| 245 | void r100_mc_fini(struct radeon_device *rdev) | ||
| 246 | { | ||
| 247 | r100_pci_gart_disable(rdev); | ||
| 248 | radeon_gart_table_ram_free(rdev); | ||
| 249 | radeon_gart_fini(rdev); | ||
| 250 | } | ||
| 251 | |||
| 252 | |||
| 253 | /* | ||
| 254 | * Fence emission | ||
| 255 | */ | ||
| 256 | void r100_fence_ring_emit(struct radeon_device *rdev, | ||
| 257 | struct radeon_fence *fence) | ||
| 258 | { | ||
| 259 | /* Who ever call radeon_fence_emit should call ring_lock and ask | ||
| 260 | * for enough space (today caller are ib schedule and buffer move) */ | ||
| 261 | /* Wait until IDLE & CLEAN */ | ||
| 262 | radeon_ring_write(rdev, PACKET0(0x1720, 0)); | ||
| 263 | radeon_ring_write(rdev, (1 << 16) | (1 << 17)); | ||
| 264 | /* Emit fence sequence & fire IRQ */ | ||
| 265 | radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0)); | ||
| 266 | radeon_ring_write(rdev, fence->seq); | ||
| 267 | radeon_ring_write(rdev, PACKET0(RADEON_GEN_INT_STATUS, 0)); | ||
| 268 | radeon_ring_write(rdev, RADEON_SW_INT_FIRE); | ||
| 269 | } | ||
| 270 | |||
| 271 | |||
| 272 | /* | ||
| 273 | * Writeback | ||
| 274 | */ | ||
| 275 | int r100_wb_init(struct radeon_device *rdev) | ||
| 276 | { | ||
| 277 | int r; | ||
| 278 | |||
| 279 | if (rdev->wb.wb_obj == NULL) { | ||
| 280 | r = radeon_object_create(rdev, NULL, 4096, | ||
| 281 | true, | ||
| 282 | RADEON_GEM_DOMAIN_GTT, | ||
| 283 | false, &rdev->wb.wb_obj); | ||
| 284 | if (r) { | ||
| 285 | DRM_ERROR("radeon: failed to create WB buffer (%d).\n", r); | ||
| 286 | return r; | ||
| 287 | } | ||
| 288 | r = radeon_object_pin(rdev->wb.wb_obj, | ||
| 289 | RADEON_GEM_DOMAIN_GTT, | ||
| 290 | &rdev->wb.gpu_addr); | ||
| 291 | if (r) { | ||
| 292 | DRM_ERROR("radeon: failed to pin WB buffer (%d).\n", r); | ||
| 293 | return r; | ||
| 294 | } | ||
| 295 | r = radeon_object_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); | ||
| 296 | if (r) { | ||
| 297 | DRM_ERROR("radeon: failed to map WB buffer (%d).\n", r); | ||
| 298 | return r; | ||
| 299 | } | ||
| 300 | } | ||
| 301 | WREG32(0x774, rdev->wb.gpu_addr); | ||
| 302 | WREG32(0x70C, rdev->wb.gpu_addr + 1024); | ||
| 303 | WREG32(0x770, 0xff); | ||
| 304 | return 0; | ||
| 305 | } | ||
| 306 | |||
| 307 | void r100_wb_fini(struct radeon_device *rdev) | ||
| 308 | { | ||
| 309 | if (rdev->wb.wb_obj) { | ||
| 310 | radeon_object_kunmap(rdev->wb.wb_obj); | ||
| 311 | radeon_object_unpin(rdev->wb.wb_obj); | ||
| 312 | radeon_object_unref(&rdev->wb.wb_obj); | ||
| 313 | rdev->wb.wb = NULL; | ||
| 314 | rdev->wb.wb_obj = NULL; | ||
| 315 | } | ||
| 316 | } | ||
| 317 | |||
| 318 | int r100_copy_blit(struct radeon_device *rdev, | ||
| 319 | uint64_t src_offset, | ||
| 320 | uint64_t dst_offset, | ||
| 321 | unsigned num_pages, | ||
| 322 | struct radeon_fence *fence) | ||
| 323 | { | ||
| 324 | uint32_t cur_pages; | ||
| 325 | uint32_t stride_bytes = PAGE_SIZE; | ||
| 326 | uint32_t pitch; | ||
| 327 | uint32_t stride_pixels; | ||
| 328 | unsigned ndw; | ||
| 329 | int num_loops; | ||
| 330 | int r = 0; | ||
| 331 | |||
| 332 | /* radeon limited to 16k stride */ | ||
| 333 | stride_bytes &= 0x3fff; | ||
| 334 | /* radeon pitch is /64 */ | ||
| 335 | pitch = stride_bytes / 64; | ||
| 336 | stride_pixels = stride_bytes / 4; | ||
| 337 | num_loops = DIV_ROUND_UP(num_pages, 8191); | ||
| 338 | |||
| 339 | /* Ask for enough room for blit + flush + fence */ | ||
| 340 | ndw = 64 + (10 * num_loops); | ||
| 341 | r = radeon_ring_lock(rdev, ndw); | ||
| 342 | if (r) { | ||
| 343 | DRM_ERROR("radeon: moving bo (%d) asking for %u dw.\n", r, ndw); | ||
| 344 | return -EINVAL; | ||
| 345 | } | ||
| 346 | while (num_pages > 0) { | ||
| 347 | cur_pages = num_pages; | ||
| 348 | if (cur_pages > 8191) { | ||
| 349 | cur_pages = 8191; | ||
| 350 | } | ||
| 351 | num_pages -= cur_pages; | ||
| 352 | |||
| 353 | /* pages are in Y direction - height | ||
| 354 | page width in X direction - width */ | ||
| 355 | radeon_ring_write(rdev, PACKET3(PACKET3_BITBLT_MULTI, 8)); | ||
| 356 | radeon_ring_write(rdev, | ||
| 357 | RADEON_GMC_SRC_PITCH_OFFSET_CNTL | | ||
| 358 | RADEON_GMC_DST_PITCH_OFFSET_CNTL | | ||
| 359 | RADEON_GMC_SRC_CLIPPING | | ||
| 360 | RADEON_GMC_DST_CLIPPING | | ||
| 361 | RADEON_GMC_BRUSH_NONE | | ||
| 362 | (RADEON_COLOR_FORMAT_ARGB8888 << 8) | | ||
| 363 | RADEON_GMC_SRC_DATATYPE_COLOR | | ||
| 364 | RADEON_ROP3_S | | ||
| 365 | RADEON_DP_SRC_SOURCE_MEMORY | | ||
| 366 | RADEON_GMC_CLR_CMP_CNTL_DIS | | ||
| 367 | RADEON_GMC_WR_MSK_DIS); | ||
| 368 | radeon_ring_write(rdev, (pitch << 22) | (src_offset >> 10)); | ||
| 369 | radeon_ring_write(rdev, (pitch << 22) | (dst_offset >> 10)); | ||
| 370 | radeon_ring_write(rdev, (0x1fff) | (0x1fff << 16)); | ||
| 371 | radeon_ring_write(rdev, 0); | ||
| 372 | radeon_ring_write(rdev, (0x1fff) | (0x1fff << 16)); | ||
| 373 | radeon_ring_write(rdev, num_pages); | ||
| 374 | radeon_ring_write(rdev, num_pages); | ||
| 375 | radeon_ring_write(rdev, cur_pages | (stride_pixels << 16)); | ||
| 376 | } | ||
| 377 | radeon_ring_write(rdev, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0)); | ||
| 378 | radeon_ring_write(rdev, RADEON_RB2D_DC_FLUSH_ALL); | ||
| 379 | radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); | ||
| 380 | radeon_ring_write(rdev, | ||
| 381 | RADEON_WAIT_2D_IDLECLEAN | | ||
| 382 | RADEON_WAIT_HOST_IDLECLEAN | | ||
| 383 | RADEON_WAIT_DMA_GUI_IDLE); | ||
| 384 | if (fence) { | ||
| 385 | r = radeon_fence_emit(rdev, fence); | ||
| 386 | } | ||
| 387 | radeon_ring_unlock_commit(rdev); | ||
| 388 | return r; | ||
| 389 | } | ||
| 390 | |||
| 391 | |||
| 392 | /* | ||
| 393 | * CP | ||
| 394 | */ | ||
| 395 | void r100_ring_start(struct radeon_device *rdev) | ||
| 396 | { | ||
| 397 | int r; | ||
| 398 | |||
| 399 | r = radeon_ring_lock(rdev, 2); | ||
| 400 | if (r) { | ||
| 401 | return; | ||
| 402 | } | ||
| 403 | radeon_ring_write(rdev, PACKET0(RADEON_ISYNC_CNTL, 0)); | ||
| 404 | radeon_ring_write(rdev, | ||
| 405 | RADEON_ISYNC_ANY2D_IDLE3D | | ||
| 406 | RADEON_ISYNC_ANY3D_IDLE2D | | ||
| 407 | RADEON_ISYNC_WAIT_IDLEGUI | | ||
| 408 | RADEON_ISYNC_CPSCRATCH_IDLEGUI); | ||
| 409 | radeon_ring_unlock_commit(rdev); | ||
| 410 | } | ||
| 411 | |||
| 412 | static void r100_cp_load_microcode(struct radeon_device *rdev) | ||
| 413 | { | ||
| 414 | int i; | ||
| 415 | |||
| 416 | if (r100_gui_wait_for_idle(rdev)) { | ||
| 417 | printk(KERN_WARNING "Failed to wait GUI idle while " | ||
| 418 | "programming pipes. Bad things might happen.\n"); | ||
| 419 | } | ||
| 420 | |||
| 421 | WREG32(RADEON_CP_ME_RAM_ADDR, 0); | ||
| 422 | if ((rdev->family == CHIP_R100) || (rdev->family == CHIP_RV100) || | ||
| 423 | (rdev->family == CHIP_RV200) || (rdev->family == CHIP_RS100) || | ||
| 424 | (rdev->family == CHIP_RS200)) { | ||
| 425 | DRM_INFO("Loading R100 Microcode\n"); | ||
| 426 | for (i = 0; i < 256; i++) { | ||
| 427 | WREG32(RADEON_CP_ME_RAM_DATAH, R100_cp_microcode[i][1]); | ||
| 428 | WREG32(RADEON_CP_ME_RAM_DATAL, R100_cp_microcode[i][0]); | ||
| 429 | } | ||
| 430 | } else if ((rdev->family == CHIP_R200) || | ||
| 431 | (rdev->family == CHIP_RV250) || | ||
| 432 | (rdev->family == CHIP_RV280) || | ||
| 433 | (rdev->family == CHIP_RS300)) { | ||
| 434 | DRM_INFO("Loading R200 Microcode\n"); | ||
| 435 | for (i = 0; i < 256; i++) { | ||
| 436 | WREG32(RADEON_CP_ME_RAM_DATAH, R200_cp_microcode[i][1]); | ||
| 437 | WREG32(RADEON_CP_ME_RAM_DATAL, R200_cp_microcode[i][0]); | ||
| 438 | } | ||
| 439 | } else if ((rdev->family == CHIP_R300) || | ||
| 440 | (rdev->family == CHIP_R350) || | ||
| 441 | (rdev->family == CHIP_RV350) || | ||
| 442 | (rdev->family == CHIP_RV380) || | ||
| 443 | (rdev->family == CHIP_RS400) || | ||
| 444 | (rdev->family == CHIP_RS480)) { | ||
| 445 | DRM_INFO("Loading R300 Microcode\n"); | ||
| 446 | for (i = 0; i < 256; i++) { | ||
| 447 | WREG32(RADEON_CP_ME_RAM_DATAH, R300_cp_microcode[i][1]); | ||
| 448 | WREG32(RADEON_CP_ME_RAM_DATAL, R300_cp_microcode[i][0]); | ||
| 449 | } | ||
| 450 | } else if ((rdev->family == CHIP_R420) || | ||
| 451 | (rdev->family == CHIP_R423) || | ||
| 452 | (rdev->family == CHIP_RV410)) { | ||
| 453 | DRM_INFO("Loading R400 Microcode\n"); | ||
| 454 | for (i = 0; i < 256; i++) { | ||
| 455 | WREG32(RADEON_CP_ME_RAM_DATAH, R420_cp_microcode[i][1]); | ||
| 456 | WREG32(RADEON_CP_ME_RAM_DATAL, R420_cp_microcode[i][0]); | ||
| 457 | } | ||
| 458 | } else if ((rdev->family == CHIP_RS690) || | ||
| 459 | (rdev->family == CHIP_RS740)) { | ||
| 460 | DRM_INFO("Loading RS690/RS740 Microcode\n"); | ||
| 461 | for (i = 0; i < 256; i++) { | ||
| 462 | WREG32(RADEON_CP_ME_RAM_DATAH, RS690_cp_microcode[i][1]); | ||
| 463 | WREG32(RADEON_CP_ME_RAM_DATAL, RS690_cp_microcode[i][0]); | ||
| 464 | } | ||
| 465 | } else if (rdev->family == CHIP_RS600) { | ||
| 466 | DRM_INFO("Loading RS600 Microcode\n"); | ||
| 467 | for (i = 0; i < 256; i++) { | ||
| 468 | WREG32(RADEON_CP_ME_RAM_DATAH, RS600_cp_microcode[i][1]); | ||
| 469 | WREG32(RADEON_CP_ME_RAM_DATAL, RS600_cp_microcode[i][0]); | ||
| 470 | } | ||
| 471 | } else if ((rdev->family == CHIP_RV515) || | ||
| 472 | (rdev->family == CHIP_R520) || | ||
| 473 | (rdev->family == CHIP_RV530) || | ||
| 474 | (rdev->family == CHIP_R580) || | ||
| 475 | (rdev->family == CHIP_RV560) || | ||
| 476 | (rdev->family == CHIP_RV570)) { | ||
| 477 | DRM_INFO("Loading R500 Microcode\n"); | ||
| 478 | for (i = 0; i < 256; i++) { | ||
| 479 | WREG32(RADEON_CP_ME_RAM_DATAH, R520_cp_microcode[i][1]); | ||
| 480 | WREG32(RADEON_CP_ME_RAM_DATAL, R520_cp_microcode[i][0]); | ||
| 481 | } | ||
| 482 | } | ||
| 483 | } | ||
| 484 | |||
| 485 | int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) | ||
| 486 | { | ||
| 487 | unsigned rb_bufsz; | ||
| 488 | unsigned rb_blksz; | ||
| 489 | unsigned max_fetch; | ||
| 490 | unsigned pre_write_timer; | ||
| 491 | unsigned pre_write_limit; | ||
| 492 | unsigned indirect2_start; | ||
| 493 | unsigned indirect1_start; | ||
| 494 | uint32_t tmp; | ||
| 495 | int r; | ||
| 496 | |||
| 497 | if (r100_debugfs_cp_init(rdev)) { | ||
| 498 | DRM_ERROR("Failed to register debugfs file for CP !\n"); | ||
| 499 | } | ||
| 500 | /* Reset CP */ | ||
| 501 | tmp = RREG32(RADEON_CP_CSQ_STAT); | ||
| 502 | if ((tmp & (1 << 31))) { | ||
| 503 | DRM_INFO("radeon: cp busy (0x%08X) resetting\n", tmp); | ||
| 504 | WREG32(RADEON_CP_CSQ_MODE, 0); | ||
| 505 | WREG32(RADEON_CP_CSQ_CNTL, 0); | ||
| 506 | WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_CP); | ||
| 507 | tmp = RREG32(RADEON_RBBM_SOFT_RESET); | ||
| 508 | mdelay(2); | ||
| 509 | WREG32(RADEON_RBBM_SOFT_RESET, 0); | ||
| 510 | tmp = RREG32(RADEON_RBBM_SOFT_RESET); | ||
| 511 | mdelay(2); | ||
| 512 | tmp = RREG32(RADEON_CP_CSQ_STAT); | ||
| 513 | if ((tmp & (1 << 31))) { | ||
| 514 | DRM_INFO("radeon: cp reset failed (0x%08X)\n", tmp); | ||
| 515 | } | ||
| 516 | } else { | ||
| 517 | DRM_INFO("radeon: cp idle (0x%08X)\n", tmp); | ||
| 518 | } | ||
| 519 | /* Align ring size */ | ||
| 520 | rb_bufsz = drm_order(ring_size / 8); | ||
| 521 | ring_size = (1 << (rb_bufsz + 1)) * 4; | ||
| 522 | r100_cp_load_microcode(rdev); | ||
| 523 | r = radeon_ring_init(rdev, ring_size); | ||
| 524 | if (r) { | ||
| 525 | return r; | ||
| 526 | } | ||
| 527 | /* Each time the cp read 1024 bytes (16 dword/quadword) update | ||
| 528 | * the rptr copy in system ram */ | ||
| 529 | rb_blksz = 9; | ||
| 530 | /* cp will read 128bytes at a time (4 dwords) */ | ||
| 531 | max_fetch = 1; | ||
| 532 | rdev->cp.align_mask = 16 - 1; | ||
| 533 | /* Write to CP_RB_WPTR will be delayed for pre_write_timer clocks */ | ||
| 534 | pre_write_timer = 64; | ||
| 535 | /* Force CP_RB_WPTR write if written more than one time before the | ||
| 536 | * delay expire | ||
| 537 | */ | ||
| 538 | pre_write_limit = 0; | ||
| 539 | /* Setup the cp cache like this (cache size is 96 dwords) : | ||
| 540 | * RING 0 to 15 | ||
| 541 | * INDIRECT1 16 to 79 | ||
| 542 | * INDIRECT2 80 to 95 | ||
| 543 | * So ring cache size is 16dwords (> (2 * max_fetch = 2 * 4dwords)) | ||
| 544 | * indirect1 cache size is 64dwords (> (2 * max_fetch = 2 * 4dwords)) | ||
| 545 | * indirect2 cache size is 16dwords (> (2 * max_fetch = 2 * 4dwords)) | ||
| 546 | * Idea being that most of the gpu cmd will be through indirect1 buffer | ||
| 547 | * so it gets the bigger cache. | ||
| 548 | */ | ||
| 549 | indirect2_start = 80; | ||
| 550 | indirect1_start = 16; | ||
| 551 | /* cp setup */ | ||
| 552 | WREG32(0x718, pre_write_timer | (pre_write_limit << 28)); | ||
| 553 | WREG32(RADEON_CP_RB_CNTL, | ||
| 554 | REG_SET(RADEON_RB_BUFSZ, rb_bufsz) | | ||
| 555 | REG_SET(RADEON_RB_BLKSZ, rb_blksz) | | ||
| 556 | REG_SET(RADEON_MAX_FETCH, max_fetch) | | ||
| 557 | RADEON_RB_NO_UPDATE); | ||
| 558 | /* Set ring address */ | ||
| 559 | DRM_INFO("radeon: ring at 0x%016lX\n", (unsigned long)rdev->cp.gpu_addr); | ||
| 560 | WREG32(RADEON_CP_RB_BASE, rdev->cp.gpu_addr); | ||
| 561 | /* Force read & write ptr to 0 */ | ||
| 562 | tmp = RREG32(RADEON_CP_RB_CNTL); | ||
| 563 | WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA); | ||
| 564 | WREG32(RADEON_CP_RB_RPTR_WR, 0); | ||
| 565 | WREG32(RADEON_CP_RB_WPTR, 0); | ||
| 566 | WREG32(RADEON_CP_RB_CNTL, tmp); | ||
| 567 | udelay(10); | ||
| 568 | rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); | ||
| 569 | rdev->cp.wptr = RREG32(RADEON_CP_RB_WPTR); | ||
| 570 | /* Set cp mode to bus mastering & enable cp*/ | ||
| 571 | WREG32(RADEON_CP_CSQ_MODE, | ||
| 572 | REG_SET(RADEON_INDIRECT2_START, indirect2_start) | | ||
| 573 | REG_SET(RADEON_INDIRECT1_START, indirect1_start)); | ||
| 574 | WREG32(0x718, 0); | ||
| 575 | WREG32(0x744, 0x00004D4D); | ||
| 576 | WREG32(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM); | ||
| 577 | radeon_ring_start(rdev); | ||
| 578 | r = radeon_ring_test(rdev); | ||
| 579 | if (r) { | ||
| 580 | DRM_ERROR("radeon: cp isn't working (%d).\n", r); | ||
| 581 | return r; | ||
| 582 | } | ||
| 583 | rdev->cp.ready = true; | ||
| 584 | return 0; | ||
| 585 | } | ||
| 586 | |||
| 587 | void r100_cp_fini(struct radeon_device *rdev) | ||
| 588 | { | ||
| 589 | /* Disable ring */ | ||
| 590 | rdev->cp.ready = false; | ||
| 591 | WREG32(RADEON_CP_CSQ_CNTL, 0); | ||
| 592 | radeon_ring_fini(rdev); | ||
| 593 | DRM_INFO("radeon: cp finalized\n"); | ||
| 594 | } | ||
| 595 | |||
| 596 | void r100_cp_disable(struct radeon_device *rdev) | ||
| 597 | { | ||
| 598 | /* Disable ring */ | ||
| 599 | rdev->cp.ready = false; | ||
| 600 | WREG32(RADEON_CP_CSQ_MODE, 0); | ||
| 601 | WREG32(RADEON_CP_CSQ_CNTL, 0); | ||
| 602 | if (r100_gui_wait_for_idle(rdev)) { | ||
| 603 | printk(KERN_WARNING "Failed to wait GUI idle while " | ||
| 604 | "programming pipes. Bad things might happen.\n"); | ||
| 605 | } | ||
| 606 | } | ||
| 607 | |||
| 608 | int r100_cp_reset(struct radeon_device *rdev) | ||
| 609 | { | ||
| 610 | uint32_t tmp; | ||
| 611 | bool reinit_cp; | ||
| 612 | int i; | ||
| 613 | |||
| 614 | reinit_cp = rdev->cp.ready; | ||
| 615 | rdev->cp.ready = false; | ||
| 616 | WREG32(RADEON_CP_CSQ_MODE, 0); | ||
| 617 | WREG32(RADEON_CP_CSQ_CNTL, 0); | ||
| 618 | WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_CP); | ||
| 619 | (void)RREG32(RADEON_RBBM_SOFT_RESET); | ||
| 620 | udelay(200); | ||
| 621 | WREG32(RADEON_RBBM_SOFT_RESET, 0); | ||
| 622 | /* Wait to prevent race in RBBM_STATUS */ | ||
| 623 | mdelay(1); | ||
| 624 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 625 | tmp = RREG32(RADEON_RBBM_STATUS); | ||
| 626 | if (!(tmp & (1 << 16))) { | ||
| 627 | DRM_INFO("CP reset succeed (RBBM_STATUS=0x%08X)\n", | ||
| 628 | tmp); | ||
| 629 | if (reinit_cp) { | ||
| 630 | return r100_cp_init(rdev, rdev->cp.ring_size); | ||
| 631 | } | ||
| 632 | return 0; | ||
| 633 | } | ||
| 634 | DRM_UDELAY(1); | ||
| 635 | } | ||
| 636 | tmp = RREG32(RADEON_RBBM_STATUS); | ||
| 637 | DRM_ERROR("Failed to reset CP (RBBM_STATUS=0x%08X)!\n", tmp); | ||
| 638 | return -1; | ||
| 639 | } | ||
| 640 | |||
| 641 | |||
| 642 | /* | ||
| 643 | * CS functions | ||
| 644 | */ | ||
| 645 | int r100_cs_parse_packet0(struct radeon_cs_parser *p, | ||
| 646 | struct radeon_cs_packet *pkt, | ||
| 647 | unsigned *auth, unsigned n, | ||
| 648 | radeon_packet0_check_t check) | ||
| 649 | { | ||
| 650 | unsigned reg; | ||
| 651 | unsigned i, j, m; | ||
| 652 | unsigned idx; | ||
| 653 | int r; | ||
| 654 | |||
| 655 | idx = pkt->idx + 1; | ||
| 656 | reg = pkt->reg; | ||
| 657 | if (pkt->one_reg_wr) { | ||
| 658 | if ((reg >> 7) > n) { | ||
| 659 | return -EINVAL; | ||
| 660 | } | ||
| 661 | } else { | ||
| 662 | if (((reg + (pkt->count << 2)) >> 7) > n) { | ||
| 663 | return -EINVAL; | ||
| 664 | } | ||
| 665 | } | ||
| 666 | for (i = 0; i <= pkt->count; i++, idx++) { | ||
| 667 | j = (reg >> 7); | ||
| 668 | m = 1 << ((reg >> 2) & 31); | ||
| 669 | if (auth[j] & m) { | ||
| 670 | r = check(p, pkt, idx, reg); | ||
| 671 | if (r) { | ||
| 672 | return r; | ||
| 673 | } | ||
| 674 | } | ||
| 675 | if (pkt->one_reg_wr) { | ||
| 676 | if (!(auth[j] & m)) { | ||
| 677 | break; | ||
| 678 | } | ||
| 679 | } else { | ||
| 680 | reg += 4; | ||
| 681 | } | ||
| 682 | } | ||
| 683 | return 0; | ||
| 684 | } | ||
| 685 | |||
| 686 | int r100_cs_parse_packet3(struct radeon_cs_parser *p, | ||
| 687 | struct radeon_cs_packet *pkt, | ||
| 688 | unsigned *auth, unsigned n, | ||
| 689 | radeon_packet3_check_t check) | ||
| 690 | { | ||
| 691 | unsigned i, m; | ||
| 692 | |||
| 693 | if ((pkt->opcode >> 5) > n) { | ||
| 694 | return -EINVAL; | ||
| 695 | } | ||
| 696 | i = pkt->opcode >> 5; | ||
| 697 | m = 1 << (pkt->opcode & 31); | ||
| 698 | if (auth[i] & m) { | ||
| 699 | return check(p, pkt); | ||
| 700 | } | ||
| 701 | return 0; | ||
| 702 | } | ||
| 703 | |||
| 704 | void r100_cs_dump_packet(struct radeon_cs_parser *p, | ||
| 705 | struct radeon_cs_packet *pkt) | ||
| 706 | { | ||
| 707 | struct radeon_cs_chunk *ib_chunk; | ||
| 708 | volatile uint32_t *ib; | ||
| 709 | unsigned i; | ||
| 710 | unsigned idx; | ||
| 711 | |||
| 712 | ib = p->ib->ptr; | ||
| 713 | ib_chunk = &p->chunks[p->chunk_ib_idx]; | ||
| 714 | idx = pkt->idx; | ||
| 715 | for (i = 0; i <= (pkt->count + 1); i++, idx++) { | ||
| 716 | DRM_INFO("ib[%d]=0x%08X\n", idx, ib[idx]); | ||
| 717 | } | ||
| 718 | } | ||
| 719 | |||
| 720 | /** | ||
| 721 | * r100_cs_packet_parse() - parse cp packet and point ib index to next packet | ||
| 722 | * @parser: parser structure holding parsing context. | ||
| 723 | * @pkt: where to store packet informations | ||
| 724 | * | ||
| 725 | * Assume that chunk_ib_index is properly set. Will return -EINVAL | ||
| 726 | * if packet is bigger than remaining ib size. or if packets is unknown. | ||
| 727 | **/ | ||
| 728 | int r100_cs_packet_parse(struct radeon_cs_parser *p, | ||
| 729 | struct radeon_cs_packet *pkt, | ||
| 730 | unsigned idx) | ||
| 731 | { | ||
| 732 | struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; | ||
| 733 | uint32_t header = ib_chunk->kdata[idx]; | ||
| 734 | |||
| 735 | if (idx >= ib_chunk->length_dw) { | ||
| 736 | DRM_ERROR("Can not parse packet at %d after CS end %d !\n", | ||
| 737 | idx, ib_chunk->length_dw); | ||
| 738 | return -EINVAL; | ||
| 739 | } | ||
| 740 | pkt->idx = idx; | ||
| 741 | pkt->type = CP_PACKET_GET_TYPE(header); | ||
| 742 | pkt->count = CP_PACKET_GET_COUNT(header); | ||
| 743 | switch (pkt->type) { | ||
| 744 | case PACKET_TYPE0: | ||
| 745 | pkt->reg = CP_PACKET0_GET_REG(header); | ||
| 746 | pkt->one_reg_wr = CP_PACKET0_GET_ONE_REG_WR(header); | ||
| 747 | break; | ||
| 748 | case PACKET_TYPE3: | ||
| 749 | pkt->opcode = CP_PACKET3_GET_OPCODE(header); | ||
| 750 | break; | ||
| 751 | case PACKET_TYPE2: | ||
| 752 | pkt->count = -1; | ||
| 753 | break; | ||
| 754 | default: | ||
| 755 | DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx); | ||
| 756 | return -EINVAL; | ||
| 757 | } | ||
| 758 | if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) { | ||
| 759 | DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n", | ||
| 760 | pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw); | ||
| 761 | return -EINVAL; | ||
| 762 | } | ||
| 763 | return 0; | ||
| 764 | } | ||
| 765 | |||
| 766 | /** | ||
| 767 | * r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3 | ||
| 768 | * @parser: parser structure holding parsing context. | ||
| 769 | * @data: pointer to relocation data | ||
| 770 | * @offset_start: starting offset | ||
| 771 | * @offset_mask: offset mask (to align start offset on) | ||
| 772 | * @reloc: reloc informations | ||
| 773 | * | ||
| 774 | * Check next packet is relocation packet3, do bo validation and compute | ||
| 775 | * GPU offset using the provided start. | ||
| 776 | **/ | ||
| 777 | int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, | ||
| 778 | struct radeon_cs_reloc **cs_reloc) | ||
| 779 | { | ||
| 780 | struct radeon_cs_chunk *ib_chunk; | ||
| 781 | struct radeon_cs_chunk *relocs_chunk; | ||
| 782 | struct radeon_cs_packet p3reloc; | ||
| 783 | unsigned idx; | ||
| 784 | int r; | ||
| 785 | |||
| 786 | if (p->chunk_relocs_idx == -1) { | ||
| 787 | DRM_ERROR("No relocation chunk !\n"); | ||
| 788 | return -EINVAL; | ||
| 789 | } | ||
| 790 | *cs_reloc = NULL; | ||
| 791 | ib_chunk = &p->chunks[p->chunk_ib_idx]; | ||
| 792 | relocs_chunk = &p->chunks[p->chunk_relocs_idx]; | ||
| 793 | r = r100_cs_packet_parse(p, &p3reloc, p->idx); | ||
| 794 | if (r) { | ||
| 795 | return r; | ||
| 796 | } | ||
| 797 | p->idx += p3reloc.count + 2; | ||
| 798 | if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { | ||
| 799 | DRM_ERROR("No packet3 for relocation for packet at %d.\n", | ||
| 800 | p3reloc.idx); | ||
| 801 | r100_cs_dump_packet(p, &p3reloc); | ||
| 802 | return -EINVAL; | ||
| 803 | } | ||
| 804 | idx = ib_chunk->kdata[p3reloc.idx + 1]; | ||
| 805 | if (idx >= relocs_chunk->length_dw) { | ||
| 806 | DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", | ||
| 807 | idx, relocs_chunk->length_dw); | ||
| 808 | r100_cs_dump_packet(p, &p3reloc); | ||
| 809 | return -EINVAL; | ||
| 810 | } | ||
| 811 | /* FIXME: we assume reloc size is 4 dwords */ | ||
| 812 | *cs_reloc = p->relocs_ptr[(idx / 4)]; | ||
| 813 | return 0; | ||
| 814 | } | ||
| 815 | |||
| 816 | static int r100_packet0_check(struct radeon_cs_parser *p, | ||
| 817 | struct radeon_cs_packet *pkt) | ||
| 818 | { | ||
| 819 | struct radeon_cs_chunk *ib_chunk; | ||
| 820 | struct radeon_cs_reloc *reloc; | ||
| 821 | volatile uint32_t *ib; | ||
| 822 | uint32_t tmp; | ||
| 823 | unsigned reg; | ||
| 824 | unsigned i; | ||
| 825 | unsigned idx; | ||
| 826 | bool onereg; | ||
| 827 | int r; | ||
| 828 | |||
| 829 | ib = p->ib->ptr; | ||
| 830 | ib_chunk = &p->chunks[p->chunk_ib_idx]; | ||
| 831 | idx = pkt->idx + 1; | ||
| 832 | reg = pkt->reg; | ||
| 833 | onereg = false; | ||
| 834 | if (CP_PACKET0_GET_ONE_REG_WR(ib_chunk->kdata[pkt->idx])) { | ||
| 835 | onereg = true; | ||
| 836 | } | ||
| 837 | for (i = 0; i <= pkt->count; i++, idx++, reg += 4) { | ||
| 838 | switch (reg) { | ||
| 839 | /* FIXME: only allow PACKET3 blit? easier to check for out of | ||
| 840 | * range access */ | ||
| 841 | case RADEON_DST_PITCH_OFFSET: | ||
| 842 | case RADEON_SRC_PITCH_OFFSET: | ||
| 843 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 844 | if (r) { | ||
| 845 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
| 846 | idx, reg); | ||
| 847 | r100_cs_dump_packet(p, pkt); | ||
| 848 | return r; | ||
| 849 | } | ||
| 850 | tmp = ib_chunk->kdata[idx] & 0x003fffff; | ||
| 851 | tmp += (((u32)reloc->lobj.gpu_offset) >> 10); | ||
| 852 | ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp; | ||
| 853 | break; | ||
| 854 | case RADEON_RB3D_DEPTHOFFSET: | ||
| 855 | case RADEON_RB3D_COLOROFFSET: | ||
| 856 | case R300_RB3D_COLOROFFSET0: | ||
| 857 | case R300_ZB_DEPTHOFFSET: | ||
| 858 | case R200_PP_TXOFFSET_0: | ||
| 859 | case R200_PP_TXOFFSET_1: | ||
| 860 | case R200_PP_TXOFFSET_2: | ||
| 861 | case R200_PP_TXOFFSET_3: | ||
| 862 | case R200_PP_TXOFFSET_4: | ||
| 863 | case R200_PP_TXOFFSET_5: | ||
| 864 | case RADEON_PP_TXOFFSET_0: | ||
| 865 | case RADEON_PP_TXOFFSET_1: | ||
| 866 | case RADEON_PP_TXOFFSET_2: | ||
| 867 | case R300_TX_OFFSET_0: | ||
| 868 | case R300_TX_OFFSET_0+4: | ||
| 869 | case R300_TX_OFFSET_0+8: | ||
| 870 | case R300_TX_OFFSET_0+12: | ||
| 871 | case R300_TX_OFFSET_0+16: | ||
| 872 | case R300_TX_OFFSET_0+20: | ||
| 873 | case R300_TX_OFFSET_0+24: | ||
| 874 | case R300_TX_OFFSET_0+28: | ||
| 875 | case R300_TX_OFFSET_0+32: | ||
| 876 | case R300_TX_OFFSET_0+36: | ||
| 877 | case R300_TX_OFFSET_0+40: | ||
| 878 | case R300_TX_OFFSET_0+44: | ||
| 879 | case R300_TX_OFFSET_0+48: | ||
| 880 | case R300_TX_OFFSET_0+52: | ||
| 881 | case R300_TX_OFFSET_0+56: | ||
| 882 | case R300_TX_OFFSET_0+60: | ||
| 883 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 884 | if (r) { | ||
| 885 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
| 886 | idx, reg); | ||
| 887 | r100_cs_dump_packet(p, pkt); | ||
| 888 | return r; | ||
| 889 | } | ||
| 890 | ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); | ||
| 891 | break; | ||
| 892 | default: | ||
| 893 | /* FIXME: we don't want to allow anyothers packet */ | ||
| 894 | break; | ||
| 895 | } | ||
| 896 | if (onereg) { | ||
| 897 | /* FIXME: forbid onereg write to register on relocate */ | ||
| 898 | break; | ||
| 899 | } | ||
| 900 | } | ||
| 901 | return 0; | ||
| 902 | } | ||
| 903 | |||
| 904 | static int r100_packet3_check(struct radeon_cs_parser *p, | ||
| 905 | struct radeon_cs_packet *pkt) | ||
| 906 | { | ||
| 907 | struct radeon_cs_chunk *ib_chunk; | ||
| 908 | struct radeon_cs_reloc *reloc; | ||
| 909 | unsigned idx; | ||
| 910 | unsigned i, c; | ||
| 911 | volatile uint32_t *ib; | ||
| 912 | int r; | ||
| 913 | |||
| 914 | ib = p->ib->ptr; | ||
| 915 | ib_chunk = &p->chunks[p->chunk_ib_idx]; | ||
| 916 | idx = pkt->idx + 1; | ||
| 917 | switch (pkt->opcode) { | ||
| 918 | case PACKET3_3D_LOAD_VBPNTR: | ||
| 919 | c = ib_chunk->kdata[idx++]; | ||
| 920 | for (i = 0; i < (c - 1); i += 2, idx += 3) { | ||
| 921 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 922 | if (r) { | ||
| 923 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 924 | pkt->opcode); | ||
| 925 | r100_cs_dump_packet(p, pkt); | ||
| 926 | return r; | ||
| 927 | } | ||
| 928 | ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); | ||
| 929 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 930 | if (r) { | ||
| 931 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 932 | pkt->opcode); | ||
| 933 | r100_cs_dump_packet(p, pkt); | ||
| 934 | return r; | ||
| 935 | } | ||
| 936 | ib[idx+2] = ib_chunk->kdata[idx+2] + ((u32)reloc->lobj.gpu_offset); | ||
| 937 | } | ||
| 938 | if (c & 1) { | ||
| 939 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 940 | if (r) { | ||
| 941 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 942 | pkt->opcode); | ||
| 943 | r100_cs_dump_packet(p, pkt); | ||
| 944 | return r; | ||
| 945 | } | ||
| 946 | ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); | ||
| 947 | } | ||
| 948 | break; | ||
| 949 | case PACKET3_INDX_BUFFER: | ||
| 950 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 951 | if (r) { | ||
| 952 | DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); | ||
| 953 | r100_cs_dump_packet(p, pkt); | ||
| 954 | return r; | ||
| 955 | } | ||
| 956 | ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); | ||
| 957 | break; | ||
| 958 | case 0x23: | ||
| 959 | /* FIXME: cleanup */ | ||
| 960 | /* 3D_RNDR_GEN_INDX_PRIM on r100/r200 */ | ||
| 961 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 962 | if (r) { | ||
| 963 | DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); | ||
| 964 | r100_cs_dump_packet(p, pkt); | ||
| 965 | return r; | ||
| 966 | } | ||
| 967 | ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); | ||
| 968 | break; | ||
| 969 | case PACKET3_3D_DRAW_IMMD: | ||
| 970 | /* triggers drawing using in-packet vertex data */ | ||
| 971 | case PACKET3_3D_DRAW_IMMD_2: | ||
| 972 | /* triggers drawing using in-packet vertex data */ | ||
| 973 | case PACKET3_3D_DRAW_VBUF_2: | ||
| 974 | /* triggers drawing of vertex buffers setup elsewhere */ | ||
| 975 | case PACKET3_3D_DRAW_INDX_2: | ||
| 976 | /* triggers drawing using indices to vertex buffer */ | ||
| 977 | case PACKET3_3D_DRAW_VBUF: | ||
| 978 | /* triggers drawing of vertex buffers setup elsewhere */ | ||
| 979 | case PACKET3_3D_DRAW_INDX: | ||
| 980 | /* triggers drawing using indices to vertex buffer */ | ||
| 981 | case PACKET3_NOP: | ||
| 982 | break; | ||
| 983 | default: | ||
| 984 | DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode); | ||
| 985 | return -EINVAL; | ||
| 986 | } | ||
| 987 | return 0; | ||
| 988 | } | ||
| 989 | |||
| 990 | int r100_cs_parse(struct radeon_cs_parser *p) | ||
| 991 | { | ||
| 992 | struct radeon_cs_packet pkt; | ||
| 993 | int r; | ||
| 994 | |||
| 995 | do { | ||
| 996 | r = r100_cs_packet_parse(p, &pkt, p->idx); | ||
| 997 | if (r) { | ||
| 998 | return r; | ||
| 999 | } | ||
| 1000 | p->idx += pkt.count + 2; | ||
| 1001 | switch (pkt.type) { | ||
| 1002 | case PACKET_TYPE0: | ||
| 1003 | r = r100_packet0_check(p, &pkt); | ||
| 1004 | break; | ||
| 1005 | case PACKET_TYPE2: | ||
| 1006 | break; | ||
| 1007 | case PACKET_TYPE3: | ||
| 1008 | r = r100_packet3_check(p, &pkt); | ||
| 1009 | break; | ||
| 1010 | default: | ||
| 1011 | DRM_ERROR("Unknown packet type %d !\n", | ||
| 1012 | pkt.type); | ||
| 1013 | return -EINVAL; | ||
| 1014 | } | ||
| 1015 | if (r) { | ||
| 1016 | return r; | ||
| 1017 | } | ||
| 1018 | } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); | ||
| 1019 | return 0; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | |||
| 1023 | /* | ||
| 1024 | * Global GPU functions | ||
| 1025 | */ | ||
| 1026 | void r100_errata(struct radeon_device *rdev) | ||
| 1027 | { | ||
| 1028 | rdev->pll_errata = 0; | ||
| 1029 | |||
| 1030 | if (rdev->family == CHIP_RV200 || rdev->family == CHIP_RS200) { | ||
| 1031 | rdev->pll_errata |= CHIP_ERRATA_PLL_DUMMYREADS; | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | if (rdev->family == CHIP_RV100 || | ||
| 1035 | rdev->family == CHIP_RS100 || | ||
| 1036 | rdev->family == CHIP_RS200) { | ||
| 1037 | rdev->pll_errata |= CHIP_ERRATA_PLL_DELAY; | ||
| 1038 | } | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | /* Wait for vertical sync on primary CRTC */ | ||
| 1042 | void r100_gpu_wait_for_vsync(struct radeon_device *rdev) | ||
| 1043 | { | ||
| 1044 | uint32_t crtc_gen_cntl, tmp; | ||
| 1045 | int i; | ||
| 1046 | |||
| 1047 | crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); | ||
| 1048 | if ((crtc_gen_cntl & RADEON_CRTC_DISP_REQ_EN_B) || | ||
| 1049 | !(crtc_gen_cntl & RADEON_CRTC_EN)) { | ||
| 1050 | return; | ||
| 1051 | } | ||
| 1052 | /* Clear the CRTC_VBLANK_SAVE bit */ | ||
| 1053 | WREG32(RADEON_CRTC_STATUS, RADEON_CRTC_VBLANK_SAVE_CLEAR); | ||
| 1054 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 1055 | tmp = RREG32(RADEON_CRTC_STATUS); | ||
| 1056 | if (tmp & RADEON_CRTC_VBLANK_SAVE) { | ||
| 1057 | return; | ||
| 1058 | } | ||
| 1059 | DRM_UDELAY(1); | ||
| 1060 | } | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | /* Wait for vertical sync on secondary CRTC */ | ||
| 1064 | void r100_gpu_wait_for_vsync2(struct radeon_device *rdev) | ||
| 1065 | { | ||
| 1066 | uint32_t crtc2_gen_cntl, tmp; | ||
| 1067 | int i; | ||
| 1068 | |||
| 1069 | crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); | ||
| 1070 | if ((crtc2_gen_cntl & RADEON_CRTC2_DISP_REQ_EN_B) || | ||
| 1071 | !(crtc2_gen_cntl & RADEON_CRTC2_EN)) | ||
| 1072 | return; | ||
| 1073 | |||
| 1074 | /* Clear the CRTC_VBLANK_SAVE bit */ | ||
| 1075 | WREG32(RADEON_CRTC2_STATUS, RADEON_CRTC2_VBLANK_SAVE_CLEAR); | ||
| 1076 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 1077 | tmp = RREG32(RADEON_CRTC2_STATUS); | ||
| 1078 | if (tmp & RADEON_CRTC2_VBLANK_SAVE) { | ||
| 1079 | return; | ||
| 1080 | } | ||
| 1081 | DRM_UDELAY(1); | ||
| 1082 | } | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | int r100_rbbm_fifo_wait_for_entry(struct radeon_device *rdev, unsigned n) | ||
| 1086 | { | ||
| 1087 | unsigned i; | ||
| 1088 | uint32_t tmp; | ||
| 1089 | |||
| 1090 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 1091 | tmp = RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; | ||
| 1092 | if (tmp >= n) { | ||
| 1093 | return 0; | ||
| 1094 | } | ||
| 1095 | DRM_UDELAY(1); | ||
| 1096 | } | ||
| 1097 | return -1; | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | int r100_gui_wait_for_idle(struct radeon_device *rdev) | ||
| 1101 | { | ||
| 1102 | unsigned i; | ||
| 1103 | uint32_t tmp; | ||
| 1104 | |||
| 1105 | if (r100_rbbm_fifo_wait_for_entry(rdev, 64)) { | ||
| 1106 | printk(KERN_WARNING "radeon: wait for empty RBBM fifo failed !" | ||
| 1107 | " Bad things might happen.\n"); | ||
| 1108 | } | ||
| 1109 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 1110 | tmp = RREG32(RADEON_RBBM_STATUS); | ||
| 1111 | if (!(tmp & (1 << 31))) { | ||
| 1112 | return 0; | ||
| 1113 | } | ||
| 1114 | DRM_UDELAY(1); | ||
| 1115 | } | ||
| 1116 | return -1; | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | int r100_mc_wait_for_idle(struct radeon_device *rdev) | ||
| 1120 | { | ||
| 1121 | unsigned i; | ||
| 1122 | uint32_t tmp; | ||
| 1123 | |||
| 1124 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 1125 | /* read MC_STATUS */ | ||
| 1126 | tmp = RREG32(0x0150); | ||
| 1127 | if (tmp & (1 << 2)) { | ||
| 1128 | return 0; | ||
| 1129 | } | ||
| 1130 | DRM_UDELAY(1); | ||
| 1131 | } | ||
| 1132 | return -1; | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | void r100_gpu_init(struct radeon_device *rdev) | ||
| 1136 | { | ||
| 1137 | /* TODO: anythings to do here ? pipes ? */ | ||
| 1138 | r100_hdp_reset(rdev); | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | void r100_hdp_reset(struct radeon_device *rdev) | ||
| 1142 | { | ||
| 1143 | uint32_t tmp; | ||
| 1144 | |||
| 1145 | tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL; | ||
| 1146 | tmp |= (7 << 28); | ||
| 1147 | WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE); | ||
| 1148 | (void)RREG32(RADEON_HOST_PATH_CNTL); | ||
| 1149 | udelay(200); | ||
| 1150 | WREG32(RADEON_RBBM_SOFT_RESET, 0); | ||
| 1151 | WREG32(RADEON_HOST_PATH_CNTL, tmp); | ||
| 1152 | (void)RREG32(RADEON_HOST_PATH_CNTL); | ||
| 1153 | } | ||
| 1154 | |||
| 1155 | int r100_rb2d_reset(struct radeon_device *rdev) | ||
| 1156 | { | ||
| 1157 | uint32_t tmp; | ||
| 1158 | int i; | ||
| 1159 | |||
| 1160 | WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_E2); | ||
| 1161 | (void)RREG32(RADEON_RBBM_SOFT_RESET); | ||
| 1162 | udelay(200); | ||
| 1163 | WREG32(RADEON_RBBM_SOFT_RESET, 0); | ||
| 1164 | /* Wait to prevent race in RBBM_STATUS */ | ||
| 1165 | mdelay(1); | ||
| 1166 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 1167 | tmp = RREG32(RADEON_RBBM_STATUS); | ||
| 1168 | if (!(tmp & (1 << 26))) { | ||
| 1169 | DRM_INFO("RB2D reset succeed (RBBM_STATUS=0x%08X)\n", | ||
| 1170 | tmp); | ||
| 1171 | return 0; | ||
| 1172 | } | ||
| 1173 | DRM_UDELAY(1); | ||
| 1174 | } | ||
| 1175 | tmp = RREG32(RADEON_RBBM_STATUS); | ||
| 1176 | DRM_ERROR("Failed to reset RB2D (RBBM_STATUS=0x%08X)!\n", tmp); | ||
| 1177 | return -1; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | int r100_gpu_reset(struct radeon_device *rdev) | ||
| 1181 | { | ||
| 1182 | uint32_t status; | ||
| 1183 | |||
| 1184 | /* reset order likely matter */ | ||
| 1185 | status = RREG32(RADEON_RBBM_STATUS); | ||
| 1186 | /* reset HDP */ | ||
| 1187 | r100_hdp_reset(rdev); | ||
| 1188 | /* reset rb2d */ | ||
| 1189 | if (status & ((1 << 17) | (1 << 18) | (1 << 27))) { | ||
| 1190 | r100_rb2d_reset(rdev); | ||
| 1191 | } | ||
| 1192 | /* TODO: reset 3D engine */ | ||
| 1193 | /* reset CP */ | ||
| 1194 | status = RREG32(RADEON_RBBM_STATUS); | ||
| 1195 | if (status & (1 << 16)) { | ||
| 1196 | r100_cp_reset(rdev); | ||
| 1197 | } | ||
| 1198 | /* Check if GPU is idle */ | ||
| 1199 | status = RREG32(RADEON_RBBM_STATUS); | ||
| 1200 | if (status & (1 << 31)) { | ||
| 1201 | DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status); | ||
| 1202 | return -1; | ||
| 1203 | } | ||
| 1204 | DRM_INFO("GPU reset succeed (RBBM_STATUS=0x%08X)\n", status); | ||
| 1205 | return 0; | ||
| 1206 | } | ||
| 1207 | |||
| 1208 | |||
| 1209 | /* | ||
| 1210 | * VRAM info | ||
| 1211 | */ | ||
| 1212 | static void r100_vram_get_type(struct radeon_device *rdev) | ||
| 1213 | { | ||
| 1214 | uint32_t tmp; | ||
| 1215 | |||
| 1216 | rdev->mc.vram_is_ddr = false; | ||
| 1217 | if (rdev->flags & RADEON_IS_IGP) | ||
| 1218 | rdev->mc.vram_is_ddr = true; | ||
| 1219 | else if (RREG32(RADEON_MEM_SDRAM_MODE_REG) & RADEON_MEM_CFG_TYPE_DDR) | ||
| 1220 | rdev->mc.vram_is_ddr = true; | ||
| 1221 | if ((rdev->family == CHIP_RV100) || | ||
| 1222 | (rdev->family == CHIP_RS100) || | ||
| 1223 | (rdev->family == CHIP_RS200)) { | ||
| 1224 | tmp = RREG32(RADEON_MEM_CNTL); | ||
| 1225 | if (tmp & RV100_HALF_MODE) { | ||
| 1226 | rdev->mc.vram_width = 32; | ||
| 1227 | } else { | ||
| 1228 | rdev->mc.vram_width = 64; | ||
| 1229 | } | ||
| 1230 | if (rdev->flags & RADEON_SINGLE_CRTC) { | ||
| 1231 | rdev->mc.vram_width /= 4; | ||
| 1232 | rdev->mc.vram_is_ddr = true; | ||
| 1233 | } | ||
| 1234 | } else if (rdev->family <= CHIP_RV280) { | ||
| 1235 | tmp = RREG32(RADEON_MEM_CNTL); | ||
| 1236 | if (tmp & RADEON_MEM_NUM_CHANNELS_MASK) { | ||
| 1237 | rdev->mc.vram_width = 128; | ||
| 1238 | } else { | ||
| 1239 | rdev->mc.vram_width = 64; | ||
| 1240 | } | ||
| 1241 | } else { | ||
| 1242 | /* newer IGPs */ | ||
| 1243 | rdev->mc.vram_width = 128; | ||
| 1244 | } | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | void r100_vram_info(struct radeon_device *rdev) | ||
| 1248 | { | ||
| 1249 | r100_vram_get_type(rdev); | ||
| 1250 | |||
| 1251 | if (rdev->flags & RADEON_IS_IGP) { | ||
| 1252 | uint32_t tom; | ||
| 1253 | /* read NB_TOM to get the amount of ram stolen for the GPU */ | ||
| 1254 | tom = RREG32(RADEON_NB_TOM); | ||
| 1255 | rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); | ||
| 1256 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); | ||
| 1257 | } else { | ||
| 1258 | rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); | ||
| 1259 | /* Some production boards of m6 will report 0 | ||
| 1260 | * if it's 8 MB | ||
| 1261 | */ | ||
| 1262 | if (rdev->mc.vram_size == 0) { | ||
| 1263 | rdev->mc.vram_size = 8192 * 1024; | ||
| 1264 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); | ||
| 1265 | } | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); | ||
| 1269 | rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); | ||
| 1270 | if (rdev->mc.aper_size > rdev->mc.vram_size) { | ||
| 1271 | /* Why does some hw doesn't have CONFIG_MEMSIZE properly | ||
| 1272 | * setup ? */ | ||
| 1273 | rdev->mc.vram_size = rdev->mc.aper_size; | ||
| 1274 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); | ||
| 1275 | } | ||
| 1276 | } | ||
| 1277 | |||
| 1278 | |||
| 1279 | /* | ||
| 1280 | * Indirect registers accessor | ||
| 1281 | */ | ||
| 1282 | void r100_pll_errata_after_index(struct radeon_device *rdev) | ||
| 1283 | { | ||
| 1284 | if (!(rdev->pll_errata & CHIP_ERRATA_PLL_DUMMYREADS)) { | ||
| 1285 | return; | ||
| 1286 | } | ||
| 1287 | (void)RREG32(RADEON_CLOCK_CNTL_DATA); | ||
| 1288 | (void)RREG32(RADEON_CRTC_GEN_CNTL); | ||
| 1289 | } | ||
| 1290 | |||
| 1291 | static void r100_pll_errata_after_data(struct radeon_device *rdev) | ||
| 1292 | { | ||
| 1293 | /* This workarounds is necessary on RV100, RS100 and RS200 chips | ||
| 1294 | * or the chip could hang on a subsequent access | ||
| 1295 | */ | ||
| 1296 | if (rdev->pll_errata & CHIP_ERRATA_PLL_DELAY) { | ||
| 1297 | udelay(5000); | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | /* This function is required to workaround a hardware bug in some (all?) | ||
| 1301 | * revisions of the R300. This workaround should be called after every | ||
| 1302 | * CLOCK_CNTL_INDEX register access. If not, register reads afterward | ||
| 1303 | * may not be correct. | ||
| 1304 | */ | ||
| 1305 | if (rdev->pll_errata & CHIP_ERRATA_R300_CG) { | ||
| 1306 | uint32_t save, tmp; | ||
| 1307 | |||
| 1308 | save = RREG32(RADEON_CLOCK_CNTL_INDEX); | ||
| 1309 | tmp = save & ~(0x3f | RADEON_PLL_WR_EN); | ||
| 1310 | WREG32(RADEON_CLOCK_CNTL_INDEX, tmp); | ||
| 1311 | tmp = RREG32(RADEON_CLOCK_CNTL_DATA); | ||
| 1312 | WREG32(RADEON_CLOCK_CNTL_INDEX, save); | ||
| 1313 | } | ||
| 1314 | } | ||
| 1315 | |||
| 1316 | uint32_t r100_pll_rreg(struct radeon_device *rdev, uint32_t reg) | ||
| 1317 | { | ||
| 1318 | uint32_t data; | ||
| 1319 | |||
| 1320 | WREG8(RADEON_CLOCK_CNTL_INDEX, reg & 0x3f); | ||
| 1321 | r100_pll_errata_after_index(rdev); | ||
| 1322 | data = RREG32(RADEON_CLOCK_CNTL_DATA); | ||
| 1323 | r100_pll_errata_after_data(rdev); | ||
| 1324 | return data; | ||
| 1325 | } | ||
| 1326 | |||
| 1327 | void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | ||
| 1328 | { | ||
| 1329 | WREG8(RADEON_CLOCK_CNTL_INDEX, ((reg & 0x3f) | RADEON_PLL_WR_EN)); | ||
| 1330 | r100_pll_errata_after_index(rdev); | ||
| 1331 | WREG32(RADEON_CLOCK_CNTL_DATA, v); | ||
| 1332 | r100_pll_errata_after_data(rdev); | ||
| 1333 | } | ||
| 1334 | |||
| 1335 | uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) | ||
| 1336 | { | ||
| 1337 | if (reg < 0x10000) | ||
| 1338 | return readl(((void __iomem *)rdev->rmmio) + reg); | ||
| 1339 | else { | ||
| 1340 | writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); | ||
| 1341 | return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); | ||
| 1342 | } | ||
| 1343 | } | ||
| 1344 | |||
| 1345 | void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | ||
| 1346 | { | ||
| 1347 | if (reg < 0x10000) | ||
| 1348 | writel(v, ((void __iomem *)rdev->rmmio) + reg); | ||
| 1349 | else { | ||
| 1350 | writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); | ||
| 1351 | writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); | ||
| 1352 | } | ||
| 1353 | } | ||
| 1354 | |||
| 1355 | /* | ||
| 1356 | * Debugfs info | ||
| 1357 | */ | ||
| 1358 | #if defined(CONFIG_DEBUG_FS) | ||
| 1359 | static int r100_debugfs_rbbm_info(struct seq_file *m, void *data) | ||
| 1360 | { | ||
| 1361 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
| 1362 | struct drm_device *dev = node->minor->dev; | ||
| 1363 | struct radeon_device *rdev = dev->dev_private; | ||
| 1364 | uint32_t reg, value; | ||
| 1365 | unsigned i; | ||
| 1366 | |||
| 1367 | seq_printf(m, "RBBM_STATUS 0x%08x\n", RREG32(RADEON_RBBM_STATUS)); | ||
| 1368 | seq_printf(m, "RBBM_CMDFIFO_STAT 0x%08x\n", RREG32(0xE7C)); | ||
| 1369 | seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); | ||
| 1370 | for (i = 0; i < 64; i++) { | ||
| 1371 | WREG32(RADEON_RBBM_CMDFIFO_ADDR, i | 0x100); | ||
| 1372 | reg = (RREG32(RADEON_RBBM_CMDFIFO_DATA) - 1) >> 2; | ||
| 1373 | WREG32(RADEON_RBBM_CMDFIFO_ADDR, i); | ||
| 1374 | value = RREG32(RADEON_RBBM_CMDFIFO_DATA); | ||
| 1375 | seq_printf(m, "[0x%03X] 0x%04X=0x%08X\n", i, reg, value); | ||
| 1376 | } | ||
| 1377 | return 0; | ||
| 1378 | } | ||
| 1379 | |||
| 1380 | static int r100_debugfs_cp_ring_info(struct seq_file *m, void *data) | ||
| 1381 | { | ||
| 1382 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
| 1383 | struct drm_device *dev = node->minor->dev; | ||
| 1384 | struct radeon_device *rdev = dev->dev_private; | ||
| 1385 | uint32_t rdp, wdp; | ||
| 1386 | unsigned count, i, j; | ||
| 1387 | |||
| 1388 | radeon_ring_free_size(rdev); | ||
| 1389 | rdp = RREG32(RADEON_CP_RB_RPTR); | ||
| 1390 | wdp = RREG32(RADEON_CP_RB_WPTR); | ||
| 1391 | count = (rdp + rdev->cp.ring_size - wdp) & rdev->cp.ptr_mask; | ||
| 1392 | seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); | ||
| 1393 | seq_printf(m, "CP_RB_WPTR 0x%08x\n", wdp); | ||
| 1394 | seq_printf(m, "CP_RB_RPTR 0x%08x\n", rdp); | ||
| 1395 | seq_printf(m, "%u free dwords in ring\n", rdev->cp.ring_free_dw); | ||
| 1396 | seq_printf(m, "%u dwords in ring\n", count); | ||
| 1397 | for (j = 0; j <= count; j++) { | ||
| 1398 | i = (rdp + j) & rdev->cp.ptr_mask; | ||
| 1399 | seq_printf(m, "r[%04d]=0x%08x\n", i, rdev->cp.ring[i]); | ||
| 1400 | } | ||
| 1401 | return 0; | ||
| 1402 | } | ||
| 1403 | |||
| 1404 | |||
| 1405 | static int r100_debugfs_cp_csq_fifo(struct seq_file *m, void *data) | ||
| 1406 | { | ||
| 1407 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
| 1408 | struct drm_device *dev = node->minor->dev; | ||
| 1409 | struct radeon_device *rdev = dev->dev_private; | ||
| 1410 | uint32_t csq_stat, csq2_stat, tmp; | ||
| 1411 | unsigned r_rptr, r_wptr, ib1_rptr, ib1_wptr, ib2_rptr, ib2_wptr; | ||
| 1412 | unsigned i; | ||
| 1413 | |||
| 1414 | seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); | ||
| 1415 | seq_printf(m, "CP_CSQ_MODE 0x%08x\n", RREG32(RADEON_CP_CSQ_MODE)); | ||
| 1416 | csq_stat = RREG32(RADEON_CP_CSQ_STAT); | ||
| 1417 | csq2_stat = RREG32(RADEON_CP_CSQ2_STAT); | ||
| 1418 | r_rptr = (csq_stat >> 0) & 0x3ff; | ||
| 1419 | r_wptr = (csq_stat >> 10) & 0x3ff; | ||
| 1420 | ib1_rptr = (csq_stat >> 20) & 0x3ff; | ||
| 1421 | ib1_wptr = (csq2_stat >> 0) & 0x3ff; | ||
| 1422 | ib2_rptr = (csq2_stat >> 10) & 0x3ff; | ||
| 1423 | ib2_wptr = (csq2_stat >> 20) & 0x3ff; | ||
| 1424 | seq_printf(m, "CP_CSQ_STAT 0x%08x\n", csq_stat); | ||
| 1425 | seq_printf(m, "CP_CSQ2_STAT 0x%08x\n", csq2_stat); | ||
| 1426 | seq_printf(m, "Ring rptr %u\n", r_rptr); | ||
| 1427 | seq_printf(m, "Ring wptr %u\n", r_wptr); | ||
| 1428 | seq_printf(m, "Indirect1 rptr %u\n", ib1_rptr); | ||
| 1429 | seq_printf(m, "Indirect1 wptr %u\n", ib1_wptr); | ||
| 1430 | seq_printf(m, "Indirect2 rptr %u\n", ib2_rptr); | ||
| 1431 | seq_printf(m, "Indirect2 wptr %u\n", ib2_wptr); | ||
| 1432 | /* FIXME: 0, 128, 640 depends on fifo setup see cp_init_kms | ||
| 1433 | * 128 = indirect1_start * 8 & 640 = indirect2_start * 8 */ | ||
| 1434 | seq_printf(m, "Ring fifo:\n"); | ||
| 1435 | for (i = 0; i < 256; i++) { | ||
| 1436 | WREG32(RADEON_CP_CSQ_ADDR, i << 2); | ||
| 1437 | tmp = RREG32(RADEON_CP_CSQ_DATA); | ||
| 1438 | seq_printf(m, "rfifo[%04d]=0x%08X\n", i, tmp); | ||
| 1439 | } | ||
| 1440 | seq_printf(m, "Indirect1 fifo:\n"); | ||
| 1441 | for (i = 256; i <= 512; i++) { | ||
| 1442 | WREG32(RADEON_CP_CSQ_ADDR, i << 2); | ||
| 1443 | tmp = RREG32(RADEON_CP_CSQ_DATA); | ||
| 1444 | seq_printf(m, "ib1fifo[%04d]=0x%08X\n", i, tmp); | ||
| 1445 | } | ||
| 1446 | seq_printf(m, "Indirect2 fifo:\n"); | ||
| 1447 | for (i = 640; i < ib1_wptr; i++) { | ||
| 1448 | WREG32(RADEON_CP_CSQ_ADDR, i << 2); | ||
| 1449 | tmp = RREG32(RADEON_CP_CSQ_DATA); | ||
| 1450 | seq_printf(m, "ib2fifo[%04d]=0x%08X\n", i, tmp); | ||
| 1451 | } | ||
| 1452 | return 0; | ||
| 1453 | } | ||
| 1454 | |||
| 1455 | static int r100_debugfs_mc_info(struct seq_file *m, void *data) | ||
| 1456 | { | ||
| 1457 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
| 1458 | struct drm_device *dev = node->minor->dev; | ||
| 1459 | struct radeon_device *rdev = dev->dev_private; | ||
| 1460 | uint32_t tmp; | ||
| 1461 | |||
| 1462 | tmp = RREG32(RADEON_CONFIG_MEMSIZE); | ||
| 1463 | seq_printf(m, "CONFIG_MEMSIZE 0x%08x\n", tmp); | ||
| 1464 | tmp = RREG32(RADEON_MC_FB_LOCATION); | ||
| 1465 | seq_printf(m, "MC_FB_LOCATION 0x%08x\n", tmp); | ||
| 1466 | tmp = RREG32(RADEON_BUS_CNTL); | ||
| 1467 | seq_printf(m, "BUS_CNTL 0x%08x\n", tmp); | ||
| 1468 | tmp = RREG32(RADEON_MC_AGP_LOCATION); | ||
| 1469 | seq_printf(m, "MC_AGP_LOCATION 0x%08x\n", tmp); | ||
| 1470 | tmp = RREG32(RADEON_AGP_BASE); | ||
| 1471 | seq_printf(m, "AGP_BASE 0x%08x\n", tmp); | ||
| 1472 | tmp = RREG32(RADEON_HOST_PATH_CNTL); | ||
| 1473 | seq_printf(m, "HOST_PATH_CNTL 0x%08x\n", tmp); | ||
| 1474 | tmp = RREG32(0x01D0); | ||
| 1475 | seq_printf(m, "AIC_CTRL 0x%08x\n", tmp); | ||
| 1476 | tmp = RREG32(RADEON_AIC_LO_ADDR); | ||
| 1477 | seq_printf(m, "AIC_LO_ADDR 0x%08x\n", tmp); | ||
| 1478 | tmp = RREG32(RADEON_AIC_HI_ADDR); | ||
| 1479 | seq_printf(m, "AIC_HI_ADDR 0x%08x\n", tmp); | ||
| 1480 | tmp = RREG32(0x01E4); | ||
| 1481 | seq_printf(m, "AIC_TLB_ADDR 0x%08x\n", tmp); | ||
| 1482 | return 0; | ||
| 1483 | } | ||
| 1484 | |||
| 1485 | static struct drm_info_list r100_debugfs_rbbm_list[] = { | ||
| 1486 | {"r100_rbbm_info", r100_debugfs_rbbm_info, 0, NULL}, | ||
| 1487 | }; | ||
| 1488 | |||
| 1489 | static struct drm_info_list r100_debugfs_cp_list[] = { | ||
| 1490 | {"r100_cp_ring_info", r100_debugfs_cp_ring_info, 0, NULL}, | ||
| 1491 | {"r100_cp_csq_fifo", r100_debugfs_cp_csq_fifo, 0, NULL}, | ||
| 1492 | }; | ||
| 1493 | |||
| 1494 | static struct drm_info_list r100_debugfs_mc_info_list[] = { | ||
| 1495 | {"r100_mc_info", r100_debugfs_mc_info, 0, NULL}, | ||
| 1496 | }; | ||
| 1497 | #endif | ||
| 1498 | |||
| 1499 | int r100_debugfs_rbbm_init(struct radeon_device *rdev) | ||
| 1500 | { | ||
| 1501 | #if defined(CONFIG_DEBUG_FS) | ||
| 1502 | return radeon_debugfs_add_files(rdev, r100_debugfs_rbbm_list, 1); | ||
| 1503 | #else | ||
| 1504 | return 0; | ||
| 1505 | #endif | ||
| 1506 | } | ||
| 1507 | |||
| 1508 | int r100_debugfs_cp_init(struct radeon_device *rdev) | ||
| 1509 | { | ||
| 1510 | #if defined(CONFIG_DEBUG_FS) | ||
| 1511 | return radeon_debugfs_add_files(rdev, r100_debugfs_cp_list, 2); | ||
| 1512 | #else | ||
| 1513 | return 0; | ||
| 1514 | #endif | ||
| 1515 | } | ||
| 1516 | |||
| 1517 | int r100_debugfs_mc_info_init(struct radeon_device *rdev) | ||
| 1518 | { | ||
| 1519 | #if defined(CONFIG_DEBUG_FS) | ||
| 1520 | return radeon_debugfs_add_files(rdev, r100_debugfs_mc_info_list, 1); | ||
| 1521 | #else | ||
| 1522 | return 0; | ||
| 1523 | #endif | ||
| 1524 | } | ||
diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c new file mode 100644 index 000000000000..f5870a099d4f --- /dev/null +++ b/drivers/gpu/drm/radeon/r300.c | |||
| @@ -0,0 +1,1116 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include <linux/seq_file.h> | ||
| 29 | #include "drmP.h" | ||
| 30 | #include "drm.h" | ||
| 31 | #include "radeon_reg.h" | ||
| 32 | #include "radeon.h" | ||
| 33 | |||
| 34 | /* r300,r350,rv350,rv370,rv380 depends on : */ | ||
| 35 | void r100_hdp_reset(struct radeon_device *rdev); | ||
| 36 | int r100_cp_reset(struct radeon_device *rdev); | ||
| 37 | int r100_rb2d_reset(struct radeon_device *rdev); | ||
| 38 | int r100_cp_init(struct radeon_device *rdev, unsigned ring_size); | ||
| 39 | int r100_pci_gart_enable(struct radeon_device *rdev); | ||
| 40 | void r100_pci_gart_disable(struct radeon_device *rdev); | ||
| 41 | void r100_mc_setup(struct radeon_device *rdev); | ||
| 42 | void r100_mc_disable_clients(struct radeon_device *rdev); | ||
| 43 | int r100_gui_wait_for_idle(struct radeon_device *rdev); | ||
| 44 | int r100_cs_packet_parse(struct radeon_cs_parser *p, | ||
| 45 | struct radeon_cs_packet *pkt, | ||
| 46 | unsigned idx); | ||
| 47 | int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, | ||
| 48 | struct radeon_cs_reloc **cs_reloc); | ||
| 49 | int r100_cs_parse_packet0(struct radeon_cs_parser *p, | ||
| 50 | struct radeon_cs_packet *pkt, | ||
| 51 | unsigned *auth, unsigned n, | ||
| 52 | radeon_packet0_check_t check); | ||
| 53 | int r100_cs_parse_packet3(struct radeon_cs_parser *p, | ||
| 54 | struct radeon_cs_packet *pkt, | ||
| 55 | unsigned *auth, unsigned n, | ||
| 56 | radeon_packet3_check_t check); | ||
| 57 | void r100_cs_dump_packet(struct radeon_cs_parser *p, | ||
| 58 | struct radeon_cs_packet *pkt); | ||
| 59 | |||
| 60 | /* This files gather functions specifics to: | ||
| 61 | * r300,r350,rv350,rv370,rv380 | ||
| 62 | * | ||
| 63 | * Some of these functions might be used by newer ASICs. | ||
| 64 | */ | ||
| 65 | void r300_gpu_init(struct radeon_device *rdev); | ||
| 66 | int r300_mc_wait_for_idle(struct radeon_device *rdev); | ||
| 67 | int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev); | ||
| 68 | |||
| 69 | |||
| 70 | /* | ||
| 71 | * rv370,rv380 PCIE GART | ||
| 72 | */ | ||
| 73 | void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev) | ||
| 74 | { | ||
| 75 | uint32_t tmp; | ||
| 76 | int i; | ||
| 77 | |||
| 78 | /* Workaround HW bug do flush 2 times */ | ||
| 79 | for (i = 0; i < 2; i++) { | ||
| 80 | tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); | ||
| 81 | WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp | RADEON_PCIE_TX_GART_INVALIDATE_TLB); | ||
| 82 | (void)RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); | ||
| 83 | WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); | ||
| 84 | mb(); | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | int rv370_pcie_gart_enable(struct radeon_device *rdev) | ||
| 89 | { | ||
| 90 | uint32_t table_addr; | ||
| 91 | uint32_t tmp; | ||
| 92 | int r; | ||
| 93 | |||
| 94 | /* Initialize common gart structure */ | ||
| 95 | r = radeon_gart_init(rdev); | ||
| 96 | if (r) { | ||
| 97 | return r; | ||
| 98 | } | ||
| 99 | r = rv370_debugfs_pcie_gart_info_init(rdev); | ||
| 100 | if (r) { | ||
| 101 | DRM_ERROR("Failed to register debugfs file for PCIE gart !\n"); | ||
| 102 | } | ||
| 103 | rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; | ||
| 104 | r = radeon_gart_table_vram_alloc(rdev); | ||
| 105 | if (r) { | ||
| 106 | return r; | ||
| 107 | } | ||
| 108 | /* discard memory request outside of configured range */ | ||
| 109 | tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; | ||
| 110 | WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); | ||
| 111 | WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, rdev->mc.gtt_location); | ||
| 112 | tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 4096; | ||
| 113 | WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, tmp); | ||
| 114 | WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0); | ||
| 115 | WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0); | ||
| 116 | table_addr = rdev->gart.table_addr; | ||
| 117 | WREG32_PCIE(RADEON_PCIE_TX_GART_BASE, table_addr); | ||
| 118 | /* FIXME: setup default page */ | ||
| 119 | WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_location); | ||
| 120 | WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_HI, 0); | ||
| 121 | /* Clear error */ | ||
| 122 | WREG32_PCIE(0x18, 0); | ||
| 123 | tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); | ||
| 124 | tmp |= RADEON_PCIE_TX_GART_EN; | ||
| 125 | tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; | ||
| 126 | WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp); | ||
| 127 | rv370_pcie_gart_tlb_flush(rdev); | ||
| 128 | DRM_INFO("PCIE GART of %uM enabled (table at 0x%08X).\n", | ||
| 129 | rdev->mc.gtt_size >> 20, table_addr); | ||
| 130 | rdev->gart.ready = true; | ||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | void rv370_pcie_gart_disable(struct radeon_device *rdev) | ||
| 135 | { | ||
| 136 | uint32_t tmp; | ||
| 137 | |||
| 138 | tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); | ||
| 139 | tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD; | ||
| 140 | WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN); | ||
| 141 | if (rdev->gart.table.vram.robj) { | ||
| 142 | radeon_object_kunmap(rdev->gart.table.vram.robj); | ||
| 143 | radeon_object_unpin(rdev->gart.table.vram.robj); | ||
| 144 | } | ||
| 145 | } | ||
| 146 | |||
| 147 | int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) | ||
| 148 | { | ||
| 149 | void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; | ||
| 150 | |||
| 151 | if (i < 0 || i > rdev->gart.num_gpu_pages) { | ||
| 152 | return -EINVAL; | ||
| 153 | } | ||
| 154 | addr = (((u32)addr) >> 8) | ((upper_32_bits(addr) & 0xff) << 4) | 0xC; | ||
| 155 | writel(cpu_to_le32(addr), ((void __iomem *)ptr) + (i * 4)); | ||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | |||
| 159 | int r300_gart_enable(struct radeon_device *rdev) | ||
| 160 | { | ||
| 161 | #if __OS_HAS_AGP | ||
| 162 | if (rdev->flags & RADEON_IS_AGP) { | ||
| 163 | if (rdev->family > CHIP_RV350) { | ||
| 164 | rv370_pcie_gart_disable(rdev); | ||
| 165 | } else { | ||
| 166 | r100_pci_gart_disable(rdev); | ||
| 167 | } | ||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | #endif | ||
| 171 | if (rdev->flags & RADEON_IS_PCIE) { | ||
| 172 | rdev->asic->gart_disable = &rv370_pcie_gart_disable; | ||
| 173 | rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush; | ||
| 174 | rdev->asic->gart_set_page = &rv370_pcie_gart_set_page; | ||
| 175 | return rv370_pcie_gart_enable(rdev); | ||
| 176 | } | ||
| 177 | return r100_pci_gart_enable(rdev); | ||
| 178 | } | ||
| 179 | |||
| 180 | |||
| 181 | /* | ||
| 182 | * MC | ||
| 183 | */ | ||
| 184 | int r300_mc_init(struct radeon_device *rdev) | ||
| 185 | { | ||
| 186 | int r; | ||
| 187 | |||
| 188 | if (r100_debugfs_rbbm_init(rdev)) { | ||
| 189 | DRM_ERROR("Failed to register debugfs file for RBBM !\n"); | ||
| 190 | } | ||
| 191 | |||
| 192 | r300_gpu_init(rdev); | ||
| 193 | r100_pci_gart_disable(rdev); | ||
| 194 | if (rdev->flags & RADEON_IS_PCIE) { | ||
| 195 | rv370_pcie_gart_disable(rdev); | ||
| 196 | } | ||
| 197 | |||
| 198 | /* Setup GPU memory space */ | ||
| 199 | rdev->mc.vram_location = 0xFFFFFFFFUL; | ||
| 200 | rdev->mc.gtt_location = 0xFFFFFFFFUL; | ||
| 201 | if (rdev->flags & RADEON_IS_AGP) { | ||
| 202 | r = radeon_agp_init(rdev); | ||
| 203 | if (r) { | ||
| 204 | printk(KERN_WARNING "[drm] Disabling AGP\n"); | ||
| 205 | rdev->flags &= ~RADEON_IS_AGP; | ||
| 206 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; | ||
| 207 | } else { | ||
| 208 | rdev->mc.gtt_location = rdev->mc.agp_base; | ||
| 209 | } | ||
| 210 | } | ||
| 211 | r = radeon_mc_setup(rdev); | ||
| 212 | if (r) { | ||
| 213 | return r; | ||
| 214 | } | ||
| 215 | |||
| 216 | /* Program GPU memory space */ | ||
| 217 | r100_mc_disable_clients(rdev); | ||
| 218 | if (r300_mc_wait_for_idle(rdev)) { | ||
| 219 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 220 | "programming pipes. Bad things might happen.\n"); | ||
| 221 | } | ||
| 222 | r100_mc_setup(rdev); | ||
| 223 | return 0; | ||
| 224 | } | ||
| 225 | |||
| 226 | void r300_mc_fini(struct radeon_device *rdev) | ||
| 227 | { | ||
| 228 | if (rdev->flags & RADEON_IS_PCIE) { | ||
| 229 | rv370_pcie_gart_disable(rdev); | ||
| 230 | radeon_gart_table_vram_free(rdev); | ||
| 231 | } else { | ||
| 232 | r100_pci_gart_disable(rdev); | ||
| 233 | radeon_gart_table_ram_free(rdev); | ||
| 234 | } | ||
| 235 | radeon_gart_fini(rdev); | ||
| 236 | } | ||
| 237 | |||
| 238 | |||
| 239 | /* | ||
| 240 | * Fence emission | ||
| 241 | */ | ||
| 242 | void r300_fence_ring_emit(struct radeon_device *rdev, | ||
| 243 | struct radeon_fence *fence) | ||
| 244 | { | ||
| 245 | /* Who ever call radeon_fence_emit should call ring_lock and ask | ||
| 246 | * for enough space (today caller are ib schedule and buffer move) */ | ||
| 247 | /* Write SC register so SC & US assert idle */ | ||
| 248 | radeon_ring_write(rdev, PACKET0(0x43E0, 0)); | ||
| 249 | radeon_ring_write(rdev, 0); | ||
| 250 | radeon_ring_write(rdev, PACKET0(0x43E4, 0)); | ||
| 251 | radeon_ring_write(rdev, 0); | ||
| 252 | /* Flush 3D cache */ | ||
| 253 | radeon_ring_write(rdev, PACKET0(0x4E4C, 0)); | ||
| 254 | radeon_ring_write(rdev, (2 << 0)); | ||
| 255 | radeon_ring_write(rdev, PACKET0(0x4F18, 0)); | ||
| 256 | radeon_ring_write(rdev, (1 << 0)); | ||
| 257 | /* Wait until IDLE & CLEAN */ | ||
| 258 | radeon_ring_write(rdev, PACKET0(0x1720, 0)); | ||
| 259 | radeon_ring_write(rdev, (1 << 17) | (1 << 16) | (1 << 9)); | ||
| 260 | /* Emit fence sequence & fire IRQ */ | ||
| 261 | radeon_ring_write(rdev, PACKET0(rdev->fence_drv.scratch_reg, 0)); | ||
| 262 | radeon_ring_write(rdev, fence->seq); | ||
| 263 | radeon_ring_write(rdev, PACKET0(RADEON_GEN_INT_STATUS, 0)); | ||
| 264 | radeon_ring_write(rdev, RADEON_SW_INT_FIRE); | ||
| 265 | } | ||
| 266 | |||
| 267 | |||
| 268 | /* | ||
| 269 | * Global GPU functions | ||
| 270 | */ | ||
| 271 | int r300_copy_dma(struct radeon_device *rdev, | ||
| 272 | uint64_t src_offset, | ||
| 273 | uint64_t dst_offset, | ||
| 274 | unsigned num_pages, | ||
| 275 | struct radeon_fence *fence) | ||
| 276 | { | ||
| 277 | uint32_t size; | ||
| 278 | uint32_t cur_size; | ||
| 279 | int i, num_loops; | ||
| 280 | int r = 0; | ||
| 281 | |||
| 282 | /* radeon pitch is /64 */ | ||
| 283 | size = num_pages << PAGE_SHIFT; | ||
| 284 | num_loops = DIV_ROUND_UP(size, 0x1FFFFF); | ||
| 285 | r = radeon_ring_lock(rdev, num_loops * 4 + 64); | ||
| 286 | if (r) { | ||
| 287 | DRM_ERROR("radeon: moving bo (%d).\n", r); | ||
| 288 | return r; | ||
| 289 | } | ||
| 290 | /* Must wait for 2D idle & clean before DMA or hangs might happen */ | ||
| 291 | radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); | ||
| 292 | radeon_ring_write(rdev, (1 << 16)); | ||
| 293 | for (i = 0; i < num_loops; i++) { | ||
| 294 | cur_size = size; | ||
| 295 | if (cur_size > 0x1FFFFF) { | ||
| 296 | cur_size = 0x1FFFFF; | ||
| 297 | } | ||
| 298 | size -= cur_size; | ||
| 299 | radeon_ring_write(rdev, PACKET0(0x720, 2)); | ||
| 300 | radeon_ring_write(rdev, src_offset); | ||
| 301 | radeon_ring_write(rdev, dst_offset); | ||
| 302 | radeon_ring_write(rdev, cur_size | (1 << 31) | (1 << 30)); | ||
| 303 | src_offset += cur_size; | ||
| 304 | dst_offset += cur_size; | ||
| 305 | } | ||
| 306 | radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); | ||
| 307 | radeon_ring_write(rdev, RADEON_WAIT_DMA_GUI_IDLE); | ||
| 308 | if (fence) { | ||
| 309 | r = radeon_fence_emit(rdev, fence); | ||
| 310 | } | ||
| 311 | radeon_ring_unlock_commit(rdev); | ||
| 312 | return r; | ||
| 313 | } | ||
| 314 | |||
| 315 | void r300_ring_start(struct radeon_device *rdev) | ||
| 316 | { | ||
| 317 | unsigned gb_tile_config; | ||
| 318 | int r; | ||
| 319 | |||
| 320 | /* Sub pixel 1/12 so we can have 4K rendering according to doc */ | ||
| 321 | gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16); | ||
| 322 | switch (rdev->num_gb_pipes) { | ||
| 323 | case 2: | ||
| 324 | gb_tile_config |= R300_PIPE_COUNT_R300; | ||
| 325 | break; | ||
| 326 | case 3: | ||
| 327 | gb_tile_config |= R300_PIPE_COUNT_R420_3P; | ||
| 328 | break; | ||
| 329 | case 4: | ||
| 330 | gb_tile_config |= R300_PIPE_COUNT_R420; | ||
| 331 | break; | ||
| 332 | case 1: | ||
| 333 | default: | ||
| 334 | gb_tile_config |= R300_PIPE_COUNT_RV350; | ||
| 335 | break; | ||
| 336 | } | ||
| 337 | |||
| 338 | r = radeon_ring_lock(rdev, 64); | ||
| 339 | if (r) { | ||
| 340 | return; | ||
| 341 | } | ||
| 342 | radeon_ring_write(rdev, PACKET0(RADEON_ISYNC_CNTL, 0)); | ||
| 343 | radeon_ring_write(rdev, | ||
| 344 | RADEON_ISYNC_ANY2D_IDLE3D | | ||
| 345 | RADEON_ISYNC_ANY3D_IDLE2D | | ||
| 346 | RADEON_ISYNC_WAIT_IDLEGUI | | ||
| 347 | RADEON_ISYNC_CPSCRATCH_IDLEGUI); | ||
| 348 | radeon_ring_write(rdev, PACKET0(R300_GB_TILE_CONFIG, 0)); | ||
| 349 | radeon_ring_write(rdev, gb_tile_config); | ||
| 350 | radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); | ||
| 351 | radeon_ring_write(rdev, | ||
| 352 | RADEON_WAIT_2D_IDLECLEAN | | ||
| 353 | RADEON_WAIT_3D_IDLECLEAN); | ||
| 354 | radeon_ring_write(rdev, PACKET0(0x170C, 0)); | ||
| 355 | radeon_ring_write(rdev, 1 << 31); | ||
| 356 | radeon_ring_write(rdev, PACKET0(R300_GB_SELECT, 0)); | ||
| 357 | radeon_ring_write(rdev, 0); | ||
| 358 | radeon_ring_write(rdev, PACKET0(R300_GB_ENABLE, 0)); | ||
| 359 | radeon_ring_write(rdev, 0); | ||
| 360 | radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); | ||
| 361 | radeon_ring_write(rdev, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); | ||
| 362 | radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); | ||
| 363 | radeon_ring_write(rdev, R300_ZC_FLUSH | R300_ZC_FREE); | ||
| 364 | radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); | ||
| 365 | radeon_ring_write(rdev, | ||
| 366 | RADEON_WAIT_2D_IDLECLEAN | | ||
| 367 | RADEON_WAIT_3D_IDLECLEAN); | ||
| 368 | radeon_ring_write(rdev, PACKET0(R300_GB_AA_CONFIG, 0)); | ||
| 369 | radeon_ring_write(rdev, 0); | ||
| 370 | radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); | ||
| 371 | radeon_ring_write(rdev, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); | ||
| 372 | radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); | ||
| 373 | radeon_ring_write(rdev, R300_ZC_FLUSH | R300_ZC_FREE); | ||
| 374 | radeon_ring_write(rdev, PACKET0(R300_GB_MSPOS0, 0)); | ||
| 375 | radeon_ring_write(rdev, | ||
| 376 | ((6 << R300_MS_X0_SHIFT) | | ||
| 377 | (6 << R300_MS_Y0_SHIFT) | | ||
| 378 | (6 << R300_MS_X1_SHIFT) | | ||
| 379 | (6 << R300_MS_Y1_SHIFT) | | ||
| 380 | (6 << R300_MS_X2_SHIFT) | | ||
| 381 | (6 << R300_MS_Y2_SHIFT) | | ||
| 382 | (6 << R300_MSBD0_Y_SHIFT) | | ||
| 383 | (6 << R300_MSBD0_X_SHIFT))); | ||
| 384 | radeon_ring_write(rdev, PACKET0(R300_GB_MSPOS1, 0)); | ||
| 385 | radeon_ring_write(rdev, | ||
| 386 | ((6 << R300_MS_X3_SHIFT) | | ||
| 387 | (6 << R300_MS_Y3_SHIFT) | | ||
| 388 | (6 << R300_MS_X4_SHIFT) | | ||
| 389 | (6 << R300_MS_Y4_SHIFT) | | ||
| 390 | (6 << R300_MS_X5_SHIFT) | | ||
| 391 | (6 << R300_MS_Y5_SHIFT) | | ||
| 392 | (6 << R300_MSBD1_SHIFT))); | ||
| 393 | radeon_ring_write(rdev, PACKET0(R300_GA_ENHANCE, 0)); | ||
| 394 | radeon_ring_write(rdev, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL); | ||
| 395 | radeon_ring_write(rdev, PACKET0(R300_GA_POLY_MODE, 0)); | ||
| 396 | radeon_ring_write(rdev, | ||
| 397 | R300_FRONT_PTYPE_TRIANGE | R300_BACK_PTYPE_TRIANGE); | ||
| 398 | radeon_ring_write(rdev, PACKET0(R300_GA_ROUND_MODE, 0)); | ||
| 399 | radeon_ring_write(rdev, | ||
| 400 | R300_GEOMETRY_ROUND_NEAREST | | ||
| 401 | R300_COLOR_ROUND_NEAREST); | ||
| 402 | radeon_ring_unlock_commit(rdev); | ||
| 403 | } | ||
| 404 | |||
| 405 | void r300_errata(struct radeon_device *rdev) | ||
| 406 | { | ||
| 407 | rdev->pll_errata = 0; | ||
| 408 | |||
| 409 | if (rdev->family == CHIP_R300 && | ||
| 410 | (RREG32(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) == RADEON_CFG_ATI_REV_A11) { | ||
| 411 | rdev->pll_errata |= CHIP_ERRATA_R300_CG; | ||
| 412 | } | ||
| 413 | } | ||
| 414 | |||
| 415 | int r300_mc_wait_for_idle(struct radeon_device *rdev) | ||
| 416 | { | ||
| 417 | unsigned i; | ||
| 418 | uint32_t tmp; | ||
| 419 | |||
| 420 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 421 | /* read MC_STATUS */ | ||
| 422 | tmp = RREG32(0x0150); | ||
| 423 | if (tmp & (1 << 4)) { | ||
| 424 | return 0; | ||
| 425 | } | ||
| 426 | DRM_UDELAY(1); | ||
| 427 | } | ||
| 428 | return -1; | ||
| 429 | } | ||
| 430 | |||
| 431 | void r300_gpu_init(struct radeon_device *rdev) | ||
| 432 | { | ||
| 433 | uint32_t gb_tile_config, tmp; | ||
| 434 | |||
| 435 | r100_hdp_reset(rdev); | ||
| 436 | /* FIXME: rv380 one pipes ? */ | ||
| 437 | if ((rdev->family == CHIP_R300) || (rdev->family == CHIP_R350)) { | ||
| 438 | /* r300,r350 */ | ||
| 439 | rdev->num_gb_pipes = 2; | ||
| 440 | } else { | ||
| 441 | /* rv350,rv370,rv380 */ | ||
| 442 | rdev->num_gb_pipes = 1; | ||
| 443 | } | ||
| 444 | gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16); | ||
| 445 | switch (rdev->num_gb_pipes) { | ||
| 446 | case 2: | ||
| 447 | gb_tile_config |= R300_PIPE_COUNT_R300; | ||
| 448 | break; | ||
| 449 | case 3: | ||
| 450 | gb_tile_config |= R300_PIPE_COUNT_R420_3P; | ||
| 451 | break; | ||
| 452 | case 4: | ||
| 453 | gb_tile_config |= R300_PIPE_COUNT_R420; | ||
| 454 | break; | ||
| 455 | case 1: | ||
| 456 | default: | ||
| 457 | gb_tile_config |= R300_PIPE_COUNT_RV350; | ||
| 458 | break; | ||
| 459 | } | ||
| 460 | WREG32(R300_GB_TILE_CONFIG, gb_tile_config); | ||
| 461 | |||
| 462 | if (r100_gui_wait_for_idle(rdev)) { | ||
| 463 | printk(KERN_WARNING "Failed to wait GUI idle while " | ||
| 464 | "programming pipes. Bad things might happen.\n"); | ||
| 465 | } | ||
| 466 | |||
| 467 | tmp = RREG32(0x170C); | ||
| 468 | WREG32(0x170C, tmp | (1 << 31)); | ||
| 469 | |||
| 470 | WREG32(R300_RB2D_DSTCACHE_MODE, | ||
| 471 | R300_DC_AUTOFLUSH_ENABLE | | ||
| 472 | R300_DC_DC_DISABLE_IGNORE_PE); | ||
| 473 | |||
| 474 | if (r100_gui_wait_for_idle(rdev)) { | ||
| 475 | printk(KERN_WARNING "Failed to wait GUI idle while " | ||
| 476 | "programming pipes. Bad things might happen.\n"); | ||
| 477 | } | ||
| 478 | if (r300_mc_wait_for_idle(rdev)) { | ||
| 479 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 480 | "programming pipes. Bad things might happen.\n"); | ||
| 481 | } | ||
| 482 | DRM_INFO("radeon: %d pipes initialized.\n", rdev->num_gb_pipes); | ||
| 483 | } | ||
| 484 | |||
| 485 | int r300_ga_reset(struct radeon_device *rdev) | ||
| 486 | { | ||
| 487 | uint32_t tmp; | ||
| 488 | bool reinit_cp; | ||
| 489 | int i; | ||
| 490 | |||
| 491 | reinit_cp = rdev->cp.ready; | ||
| 492 | rdev->cp.ready = false; | ||
| 493 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 494 | WREG32(RADEON_CP_CSQ_MODE, 0); | ||
| 495 | WREG32(RADEON_CP_CSQ_CNTL, 0); | ||
| 496 | WREG32(RADEON_RBBM_SOFT_RESET, 0x32005); | ||
| 497 | (void)RREG32(RADEON_RBBM_SOFT_RESET); | ||
| 498 | udelay(200); | ||
| 499 | WREG32(RADEON_RBBM_SOFT_RESET, 0); | ||
| 500 | /* Wait to prevent race in RBBM_STATUS */ | ||
| 501 | mdelay(1); | ||
| 502 | tmp = RREG32(RADEON_RBBM_STATUS); | ||
| 503 | if (tmp & ((1 << 20) | (1 << 26))) { | ||
| 504 | DRM_ERROR("VAP & CP still busy (RBBM_STATUS=0x%08X)", tmp); | ||
| 505 | /* GA still busy soft reset it */ | ||
| 506 | WREG32(0x429C, 0x200); | ||
| 507 | WREG32(R300_VAP_PVS_STATE_FLUSH_REG, 0); | ||
| 508 | WREG32(0x43E0, 0); | ||
| 509 | WREG32(0x43E4, 0); | ||
| 510 | WREG32(0x24AC, 0); | ||
| 511 | } | ||
| 512 | /* Wait to prevent race in RBBM_STATUS */ | ||
| 513 | mdelay(1); | ||
| 514 | tmp = RREG32(RADEON_RBBM_STATUS); | ||
| 515 | if (!(tmp & ((1 << 20) | (1 << 26)))) { | ||
| 516 | break; | ||
| 517 | } | ||
| 518 | } | ||
| 519 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 520 | tmp = RREG32(RADEON_RBBM_STATUS); | ||
| 521 | if (!(tmp & ((1 << 20) | (1 << 26)))) { | ||
| 522 | DRM_INFO("GA reset succeed (RBBM_STATUS=0x%08X)\n", | ||
| 523 | tmp); | ||
| 524 | if (reinit_cp) { | ||
| 525 | return r100_cp_init(rdev, rdev->cp.ring_size); | ||
| 526 | } | ||
| 527 | return 0; | ||
| 528 | } | ||
| 529 | DRM_UDELAY(1); | ||
| 530 | } | ||
| 531 | tmp = RREG32(RADEON_RBBM_STATUS); | ||
| 532 | DRM_ERROR("Failed to reset GA ! (RBBM_STATUS=0x%08X)\n", tmp); | ||
| 533 | return -1; | ||
| 534 | } | ||
| 535 | |||
| 536 | int r300_gpu_reset(struct radeon_device *rdev) | ||
| 537 | { | ||
| 538 | uint32_t status; | ||
| 539 | |||
| 540 | /* reset order likely matter */ | ||
| 541 | status = RREG32(RADEON_RBBM_STATUS); | ||
| 542 | /* reset HDP */ | ||
| 543 | r100_hdp_reset(rdev); | ||
| 544 | /* reset rb2d */ | ||
| 545 | if (status & ((1 << 17) | (1 << 18) | (1 << 27))) { | ||
| 546 | r100_rb2d_reset(rdev); | ||
| 547 | } | ||
| 548 | /* reset GA */ | ||
| 549 | if (status & ((1 << 20) | (1 << 26))) { | ||
| 550 | r300_ga_reset(rdev); | ||
| 551 | } | ||
| 552 | /* reset CP */ | ||
| 553 | status = RREG32(RADEON_RBBM_STATUS); | ||
| 554 | if (status & (1 << 16)) { | ||
| 555 | r100_cp_reset(rdev); | ||
| 556 | } | ||
| 557 | /* Check if GPU is idle */ | ||
| 558 | status = RREG32(RADEON_RBBM_STATUS); | ||
| 559 | if (status & (1 << 31)) { | ||
| 560 | DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status); | ||
| 561 | return -1; | ||
| 562 | } | ||
| 563 | DRM_INFO("GPU reset succeed (RBBM_STATUS=0x%08X)\n", status); | ||
| 564 | return 0; | ||
| 565 | } | ||
| 566 | |||
| 567 | |||
| 568 | /* | ||
| 569 | * r300,r350,rv350,rv380 VRAM info | ||
| 570 | */ | ||
| 571 | void r300_vram_info(struct radeon_device *rdev) | ||
| 572 | { | ||
| 573 | uint32_t tmp; | ||
| 574 | |||
| 575 | /* DDR for all card after R300 & IGP */ | ||
| 576 | rdev->mc.vram_is_ddr = true; | ||
| 577 | tmp = RREG32(RADEON_MEM_CNTL); | ||
| 578 | if (tmp & R300_MEM_NUM_CHANNELS_MASK) { | ||
| 579 | rdev->mc.vram_width = 128; | ||
| 580 | } else { | ||
| 581 | rdev->mc.vram_width = 64; | ||
| 582 | } | ||
| 583 | rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); | ||
| 584 | |||
| 585 | rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); | ||
| 586 | rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); | ||
| 587 | } | ||
| 588 | |||
| 589 | |||
| 590 | /* | ||
| 591 | * Indirect registers accessor | ||
| 592 | */ | ||
| 593 | uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg) | ||
| 594 | { | ||
| 595 | uint32_t r; | ||
| 596 | |||
| 597 | WREG8(RADEON_PCIE_INDEX, ((reg) & 0xff)); | ||
| 598 | (void)RREG32(RADEON_PCIE_INDEX); | ||
| 599 | r = RREG32(RADEON_PCIE_DATA); | ||
| 600 | return r; | ||
| 601 | } | ||
| 602 | |||
| 603 | void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | ||
| 604 | { | ||
| 605 | WREG8(RADEON_PCIE_INDEX, ((reg) & 0xff)); | ||
| 606 | (void)RREG32(RADEON_PCIE_INDEX); | ||
| 607 | WREG32(RADEON_PCIE_DATA, (v)); | ||
| 608 | (void)RREG32(RADEON_PCIE_DATA); | ||
| 609 | } | ||
| 610 | |||
| 611 | /* | ||
| 612 | * PCIE Lanes | ||
| 613 | */ | ||
| 614 | |||
| 615 | void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes) | ||
| 616 | { | ||
| 617 | uint32_t link_width_cntl, mask; | ||
| 618 | |||
| 619 | if (rdev->flags & RADEON_IS_IGP) | ||
| 620 | return; | ||
| 621 | |||
| 622 | if (!(rdev->flags & RADEON_IS_PCIE)) | ||
| 623 | return; | ||
| 624 | |||
| 625 | /* FIXME wait for idle */ | ||
| 626 | |||
| 627 | switch (lanes) { | ||
| 628 | case 0: | ||
| 629 | mask = RADEON_PCIE_LC_LINK_WIDTH_X0; | ||
| 630 | break; | ||
| 631 | case 1: | ||
| 632 | mask = RADEON_PCIE_LC_LINK_WIDTH_X1; | ||
| 633 | break; | ||
| 634 | case 2: | ||
| 635 | mask = RADEON_PCIE_LC_LINK_WIDTH_X2; | ||
| 636 | break; | ||
| 637 | case 4: | ||
| 638 | mask = RADEON_PCIE_LC_LINK_WIDTH_X4; | ||
| 639 | break; | ||
| 640 | case 8: | ||
| 641 | mask = RADEON_PCIE_LC_LINK_WIDTH_X8; | ||
| 642 | break; | ||
| 643 | case 12: | ||
| 644 | mask = RADEON_PCIE_LC_LINK_WIDTH_X12; | ||
| 645 | break; | ||
| 646 | case 16: | ||
| 647 | default: | ||
| 648 | mask = RADEON_PCIE_LC_LINK_WIDTH_X16; | ||
| 649 | break; | ||
| 650 | } | ||
| 651 | |||
| 652 | link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); | ||
| 653 | |||
| 654 | if ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) == | ||
| 655 | (mask << RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT)) | ||
| 656 | return; | ||
| 657 | |||
| 658 | link_width_cntl &= ~(RADEON_PCIE_LC_LINK_WIDTH_MASK | | ||
| 659 | RADEON_PCIE_LC_RECONFIG_NOW | | ||
| 660 | RADEON_PCIE_LC_RECONFIG_LATER | | ||
| 661 | RADEON_PCIE_LC_SHORT_RECONFIG_EN); | ||
| 662 | link_width_cntl |= mask; | ||
| 663 | WREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); | ||
| 664 | WREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL, (link_width_cntl | | ||
| 665 | RADEON_PCIE_LC_RECONFIG_NOW)); | ||
| 666 | |||
| 667 | /* wait for lane set to complete */ | ||
| 668 | link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); | ||
| 669 | while (link_width_cntl == 0xffffffff) | ||
| 670 | link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL); | ||
| 671 | |||
| 672 | } | ||
| 673 | |||
| 674 | |||
| 675 | /* | ||
| 676 | * Debugfs info | ||
| 677 | */ | ||
| 678 | #if defined(CONFIG_DEBUG_FS) | ||
| 679 | static int rv370_debugfs_pcie_gart_info(struct seq_file *m, void *data) | ||
| 680 | { | ||
| 681 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
| 682 | struct drm_device *dev = node->minor->dev; | ||
| 683 | struct radeon_device *rdev = dev->dev_private; | ||
| 684 | uint32_t tmp; | ||
| 685 | |||
| 686 | tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL); | ||
| 687 | seq_printf(m, "PCIE_TX_GART_CNTL 0x%08x\n", tmp); | ||
| 688 | tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_BASE); | ||
| 689 | seq_printf(m, "PCIE_TX_GART_BASE 0x%08x\n", tmp); | ||
| 690 | tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_START_LO); | ||
| 691 | seq_printf(m, "PCIE_TX_GART_START_LO 0x%08x\n", tmp); | ||
| 692 | tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_START_HI); | ||
| 693 | seq_printf(m, "PCIE_TX_GART_START_HI 0x%08x\n", tmp); | ||
| 694 | tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_END_LO); | ||
| 695 | seq_printf(m, "PCIE_TX_GART_END_LO 0x%08x\n", tmp); | ||
| 696 | tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_END_HI); | ||
| 697 | seq_printf(m, "PCIE_TX_GART_END_HI 0x%08x\n", tmp); | ||
| 698 | tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_ERROR); | ||
| 699 | seq_printf(m, "PCIE_TX_GART_ERROR 0x%08x\n", tmp); | ||
| 700 | return 0; | ||
| 701 | } | ||
| 702 | |||
| 703 | static struct drm_info_list rv370_pcie_gart_info_list[] = { | ||
| 704 | {"rv370_pcie_gart_info", rv370_debugfs_pcie_gart_info, 0, NULL}, | ||
| 705 | }; | ||
| 706 | #endif | ||
| 707 | |||
| 708 | int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev) | ||
| 709 | { | ||
| 710 | #if defined(CONFIG_DEBUG_FS) | ||
| 711 | return radeon_debugfs_add_files(rdev, rv370_pcie_gart_info_list, 1); | ||
| 712 | #else | ||
| 713 | return 0; | ||
| 714 | #endif | ||
| 715 | } | ||
| 716 | |||
| 717 | |||
| 718 | /* | ||
| 719 | * CS functions | ||
| 720 | */ | ||
| 721 | struct r300_cs_track_cb { | ||
| 722 | struct radeon_object *robj; | ||
| 723 | unsigned pitch; | ||
| 724 | unsigned cpp; | ||
| 725 | unsigned offset; | ||
| 726 | }; | ||
| 727 | |||
| 728 | struct r300_cs_track { | ||
| 729 | unsigned num_cb; | ||
| 730 | unsigned maxy; | ||
| 731 | struct r300_cs_track_cb cb[4]; | ||
| 732 | struct r300_cs_track_cb zb; | ||
| 733 | bool z_enabled; | ||
| 734 | }; | ||
| 735 | |||
| 736 | int r300_cs_track_check(struct radeon_device *rdev, struct r300_cs_track *track) | ||
| 737 | { | ||
| 738 | unsigned i; | ||
| 739 | unsigned long size; | ||
| 740 | |||
| 741 | for (i = 0; i < track->num_cb; i++) { | ||
| 742 | if (track->cb[i].robj == NULL) { | ||
| 743 | DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); | ||
| 744 | return -EINVAL; | ||
| 745 | } | ||
| 746 | size = track->cb[i].pitch * track->cb[i].cpp * track->maxy; | ||
| 747 | size += track->cb[i].offset; | ||
| 748 | if (size > radeon_object_size(track->cb[i].robj)) { | ||
| 749 | DRM_ERROR("[drm] Buffer too small for color buffer %d " | ||
| 750 | "(need %lu have %lu) !\n", i, size, | ||
| 751 | radeon_object_size(track->cb[i].robj)); | ||
| 752 | DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n", | ||
| 753 | i, track->cb[i].pitch, track->cb[i].cpp, | ||
| 754 | track->cb[i].offset, track->maxy); | ||
| 755 | return -EINVAL; | ||
| 756 | } | ||
| 757 | } | ||
| 758 | if (track->z_enabled) { | ||
| 759 | if (track->zb.robj == NULL) { | ||
| 760 | DRM_ERROR("[drm] No buffer for z buffer !\n"); | ||
| 761 | return -EINVAL; | ||
| 762 | } | ||
| 763 | size = track->zb.pitch * track->zb.cpp * track->maxy; | ||
| 764 | size += track->zb.offset; | ||
| 765 | if (size > radeon_object_size(track->zb.robj)) { | ||
| 766 | DRM_ERROR("[drm] Buffer too small for z buffer " | ||
| 767 | "(need %lu have %lu) !\n", size, | ||
| 768 | radeon_object_size(track->zb.robj)); | ||
| 769 | return -EINVAL; | ||
| 770 | } | ||
| 771 | } | ||
| 772 | return 0; | ||
| 773 | } | ||
| 774 | |||
| 775 | static inline void r300_cs_track_clear(struct r300_cs_track *track) | ||
| 776 | { | ||
| 777 | unsigned i; | ||
| 778 | |||
| 779 | track->num_cb = 4; | ||
| 780 | track->maxy = 4096; | ||
| 781 | for (i = 0; i < track->num_cb; i++) { | ||
| 782 | track->cb[i].robj = NULL; | ||
| 783 | track->cb[i].pitch = 8192; | ||
| 784 | track->cb[i].cpp = 16; | ||
| 785 | track->cb[i].offset = 0; | ||
| 786 | } | ||
| 787 | track->z_enabled = true; | ||
| 788 | track->zb.robj = NULL; | ||
| 789 | track->zb.pitch = 8192; | ||
| 790 | track->zb.cpp = 4; | ||
| 791 | track->zb.offset = 0; | ||
| 792 | } | ||
| 793 | |||
| 794 | static unsigned r300_auth_reg[] = { | ||
| 795 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 796 | 0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFBF, 0xFFFFFFFF, | ||
| 797 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 798 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 799 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 800 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 801 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 802 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 803 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 804 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 805 | 0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF, | ||
| 806 | 0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF, | ||
| 807 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 808 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 809 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F, | ||
| 810 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 811 | 0xFFFFFFFF, 0xFFFFCFCC, 0xF00E9FFF, 0x007C0000, | ||
| 812 | 0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 813 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 814 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 815 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 816 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 817 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 818 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 819 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 820 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 821 | 0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 822 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 823 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 824 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 825 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 826 | 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, | ||
| 827 | 0xFFFFFC78, 0xFFFFFFFF, 0xFFFFFFFC, 0xFFFFFFFF, | ||
| 828 | 0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE009FF, | ||
| 829 | 0x00000000, 0x00000000, 0xFFFF0000, 0x00000000, | ||
| 830 | 0x00000000, 0x0000C100, 0x00000000, 0x00000000, | ||
| 831 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||
| 832 | 0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF, | ||
| 833 | 0x00000000, 0x00000000, 0x00000000, 0x00000000, | ||
| 834 | 0x0003FC01, 0xFFFFFFF8, 0xFE800B19, | ||
| 835 | }; | ||
| 836 | |||
| 837 | static int r300_packet0_check(struct radeon_cs_parser *p, | ||
| 838 | struct radeon_cs_packet *pkt, | ||
| 839 | unsigned idx, unsigned reg) | ||
| 840 | { | ||
| 841 | struct radeon_cs_chunk *ib_chunk; | ||
| 842 | struct radeon_cs_reloc *reloc; | ||
| 843 | struct r300_cs_track *track; | ||
| 844 | volatile uint32_t *ib; | ||
| 845 | uint32_t tmp; | ||
| 846 | unsigned i; | ||
| 847 | int r; | ||
| 848 | |||
| 849 | ib = p->ib->ptr; | ||
| 850 | ib_chunk = &p->chunks[p->chunk_ib_idx]; | ||
| 851 | track = (struct r300_cs_track *)p->track; | ||
| 852 | switch (reg) { | ||
| 853 | case RADEON_DST_PITCH_OFFSET: | ||
| 854 | case RADEON_SRC_PITCH_OFFSET: | ||
| 855 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 856 | if (r) { | ||
| 857 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
| 858 | idx, reg); | ||
| 859 | r100_cs_dump_packet(p, pkt); | ||
| 860 | return r; | ||
| 861 | } | ||
| 862 | tmp = ib_chunk->kdata[idx] & 0x003fffff; | ||
| 863 | tmp += (((u32)reloc->lobj.gpu_offset) >> 10); | ||
| 864 | ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp; | ||
| 865 | break; | ||
| 866 | case R300_RB3D_COLOROFFSET0: | ||
| 867 | case R300_RB3D_COLOROFFSET1: | ||
| 868 | case R300_RB3D_COLOROFFSET2: | ||
| 869 | case R300_RB3D_COLOROFFSET3: | ||
| 870 | i = (reg - R300_RB3D_COLOROFFSET0) >> 2; | ||
| 871 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 872 | if (r) { | ||
| 873 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
| 874 | idx, reg); | ||
| 875 | r100_cs_dump_packet(p, pkt); | ||
| 876 | return r; | ||
| 877 | } | ||
| 878 | track->cb[i].robj = reloc->robj; | ||
| 879 | track->cb[i].offset = ib_chunk->kdata[idx]; | ||
| 880 | ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); | ||
| 881 | break; | ||
| 882 | case R300_ZB_DEPTHOFFSET: | ||
| 883 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 884 | if (r) { | ||
| 885 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
| 886 | idx, reg); | ||
| 887 | r100_cs_dump_packet(p, pkt); | ||
| 888 | return r; | ||
| 889 | } | ||
| 890 | track->zb.robj = reloc->robj; | ||
| 891 | track->zb.offset = ib_chunk->kdata[idx]; | ||
| 892 | ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); | ||
| 893 | break; | ||
| 894 | case R300_TX_OFFSET_0: | ||
| 895 | case R300_TX_OFFSET_0+4: | ||
| 896 | case R300_TX_OFFSET_0+8: | ||
| 897 | case R300_TX_OFFSET_0+12: | ||
| 898 | case R300_TX_OFFSET_0+16: | ||
| 899 | case R300_TX_OFFSET_0+20: | ||
| 900 | case R300_TX_OFFSET_0+24: | ||
| 901 | case R300_TX_OFFSET_0+28: | ||
| 902 | case R300_TX_OFFSET_0+32: | ||
| 903 | case R300_TX_OFFSET_0+36: | ||
| 904 | case R300_TX_OFFSET_0+40: | ||
| 905 | case R300_TX_OFFSET_0+44: | ||
| 906 | case R300_TX_OFFSET_0+48: | ||
| 907 | case R300_TX_OFFSET_0+52: | ||
| 908 | case R300_TX_OFFSET_0+56: | ||
| 909 | case R300_TX_OFFSET_0+60: | ||
| 910 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 911 | if (r) { | ||
| 912 | DRM_ERROR("No reloc for ib[%d]=0x%04X\n", | ||
| 913 | idx, reg); | ||
| 914 | r100_cs_dump_packet(p, pkt); | ||
| 915 | return r; | ||
| 916 | } | ||
| 917 | ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset); | ||
| 918 | break; | ||
| 919 | /* Tracked registers */ | ||
| 920 | case 0x43E4: | ||
| 921 | /* SC_SCISSOR1 */ | ||
| 922 | |||
| 923 | track->maxy = ((ib_chunk->kdata[idx] >> 13) & 0x1FFF) + 1; | ||
| 924 | if (p->rdev->family < CHIP_RV515) { | ||
| 925 | track->maxy -= 1440; | ||
| 926 | } | ||
| 927 | break; | ||
| 928 | case 0x4E00: | ||
| 929 | /* RB3D_CCTL */ | ||
| 930 | track->num_cb = ((ib_chunk->kdata[idx] >> 5) & 0x3) + 1; | ||
| 931 | break; | ||
| 932 | case 0x4E38: | ||
| 933 | case 0x4E3C: | ||
| 934 | case 0x4E40: | ||
| 935 | case 0x4E44: | ||
| 936 | /* RB3D_COLORPITCH0 */ | ||
| 937 | /* RB3D_COLORPITCH1 */ | ||
| 938 | /* RB3D_COLORPITCH2 */ | ||
| 939 | /* RB3D_COLORPITCH3 */ | ||
| 940 | i = (reg - 0x4E38) >> 2; | ||
| 941 | track->cb[i].pitch = ib_chunk->kdata[idx] & 0x3FFE; | ||
| 942 | switch (((ib_chunk->kdata[idx] >> 21) & 0xF)) { | ||
| 943 | case 9: | ||
| 944 | case 11: | ||
| 945 | case 12: | ||
| 946 | track->cb[i].cpp = 1; | ||
| 947 | break; | ||
| 948 | case 3: | ||
| 949 | case 4: | ||
| 950 | case 13: | ||
| 951 | case 15: | ||
| 952 | track->cb[i].cpp = 2; | ||
| 953 | break; | ||
| 954 | case 6: | ||
| 955 | track->cb[i].cpp = 4; | ||
| 956 | break; | ||
| 957 | case 10: | ||
| 958 | track->cb[i].cpp = 8; | ||
| 959 | break; | ||
| 960 | case 7: | ||
| 961 | track->cb[i].cpp = 16; | ||
| 962 | break; | ||
| 963 | default: | ||
| 964 | DRM_ERROR("Invalid color buffer format (%d) !\n", | ||
| 965 | ((ib_chunk->kdata[idx] >> 21) & 0xF)); | ||
| 966 | return -EINVAL; | ||
| 967 | } | ||
| 968 | break; | ||
| 969 | case 0x4F00: | ||
| 970 | /* ZB_CNTL */ | ||
| 971 | if (ib_chunk->kdata[idx] & 2) { | ||
| 972 | track->z_enabled = true; | ||
| 973 | } else { | ||
| 974 | track->z_enabled = false; | ||
| 975 | } | ||
| 976 | break; | ||
| 977 | case 0x4F10: | ||
| 978 | /* ZB_FORMAT */ | ||
| 979 | switch ((ib_chunk->kdata[idx] & 0xF)) { | ||
| 980 | case 0: | ||
| 981 | case 1: | ||
| 982 | track->zb.cpp = 2; | ||
| 983 | break; | ||
| 984 | case 2: | ||
| 985 | track->zb.cpp = 4; | ||
| 986 | break; | ||
| 987 | default: | ||
| 988 | DRM_ERROR("Invalid z buffer format (%d) !\n", | ||
| 989 | (ib_chunk->kdata[idx] & 0xF)); | ||
| 990 | return -EINVAL; | ||
| 991 | } | ||
| 992 | break; | ||
| 993 | case 0x4F24: | ||
| 994 | /* ZB_DEPTHPITCH */ | ||
| 995 | track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC; | ||
| 996 | break; | ||
| 997 | default: | ||
| 998 | printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n", reg, idx); | ||
| 999 | return -EINVAL; | ||
| 1000 | } | ||
| 1001 | return 0; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | static int r300_packet3_check(struct radeon_cs_parser *p, | ||
| 1005 | struct radeon_cs_packet *pkt) | ||
| 1006 | { | ||
| 1007 | struct radeon_cs_chunk *ib_chunk; | ||
| 1008 | struct radeon_cs_reloc *reloc; | ||
| 1009 | struct r300_cs_track *track; | ||
| 1010 | volatile uint32_t *ib; | ||
| 1011 | unsigned idx; | ||
| 1012 | unsigned i, c; | ||
| 1013 | int r; | ||
| 1014 | |||
| 1015 | ib = p->ib->ptr; | ||
| 1016 | ib_chunk = &p->chunks[p->chunk_ib_idx]; | ||
| 1017 | idx = pkt->idx + 1; | ||
| 1018 | track = (struct r300_cs_track *)p->track; | ||
| 1019 | switch (pkt->opcode) { | ||
| 1020 | case PACKET3_3D_LOAD_VBPNTR: | ||
| 1021 | c = ib_chunk->kdata[idx++]; | ||
| 1022 | for (i = 0; i < (c - 1); i += 2, idx += 3) { | ||
| 1023 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 1024 | if (r) { | ||
| 1025 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 1026 | pkt->opcode); | ||
| 1027 | r100_cs_dump_packet(p, pkt); | ||
| 1028 | return r; | ||
| 1029 | } | ||
| 1030 | ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); | ||
| 1031 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 1032 | if (r) { | ||
| 1033 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 1034 | pkt->opcode); | ||
| 1035 | r100_cs_dump_packet(p, pkt); | ||
| 1036 | return r; | ||
| 1037 | } | ||
| 1038 | ib[idx+2] = ib_chunk->kdata[idx+2] + ((u32)reloc->lobj.gpu_offset); | ||
| 1039 | } | ||
| 1040 | if (c & 1) { | ||
| 1041 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 1042 | if (r) { | ||
| 1043 | DRM_ERROR("No reloc for packet3 %d\n", | ||
| 1044 | pkt->opcode); | ||
| 1045 | r100_cs_dump_packet(p, pkt); | ||
| 1046 | return r; | ||
| 1047 | } | ||
| 1048 | ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); | ||
| 1049 | } | ||
| 1050 | break; | ||
| 1051 | case PACKET3_INDX_BUFFER: | ||
| 1052 | r = r100_cs_packet_next_reloc(p, &reloc); | ||
| 1053 | if (r) { | ||
| 1054 | DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); | ||
| 1055 | r100_cs_dump_packet(p, pkt); | ||
| 1056 | return r; | ||
| 1057 | } | ||
| 1058 | ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset); | ||
| 1059 | break; | ||
| 1060 | /* Draw packet */ | ||
| 1061 | case PACKET3_3D_DRAW_VBUF: | ||
| 1062 | case PACKET3_3D_DRAW_IMMD: | ||
| 1063 | case PACKET3_3D_DRAW_INDX: | ||
| 1064 | case PACKET3_3D_DRAW_VBUF_2: | ||
| 1065 | case PACKET3_3D_DRAW_IMMD_2: | ||
| 1066 | case PACKET3_3D_DRAW_INDX_2: | ||
| 1067 | r = r300_cs_track_check(p->rdev, track); | ||
| 1068 | if (r) { | ||
| 1069 | return r; | ||
| 1070 | } | ||
| 1071 | break; | ||
| 1072 | case PACKET3_NOP: | ||
| 1073 | break; | ||
| 1074 | default: | ||
| 1075 | DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode); | ||
| 1076 | return -EINVAL; | ||
| 1077 | } | ||
| 1078 | return 0; | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | int r300_cs_parse(struct radeon_cs_parser *p) | ||
| 1082 | { | ||
| 1083 | struct radeon_cs_packet pkt; | ||
| 1084 | struct r300_cs_track track; | ||
| 1085 | int r; | ||
| 1086 | |||
| 1087 | r300_cs_track_clear(&track); | ||
| 1088 | p->track = &track; | ||
| 1089 | do { | ||
| 1090 | r = r100_cs_packet_parse(p, &pkt, p->idx); | ||
| 1091 | if (r) { | ||
| 1092 | return r; | ||
| 1093 | } | ||
| 1094 | p->idx += pkt.count + 2; | ||
| 1095 | switch (pkt.type) { | ||
| 1096 | case PACKET_TYPE0: | ||
| 1097 | r = r100_cs_parse_packet0(p, &pkt, | ||
| 1098 | r300_auth_reg, | ||
| 1099 | ARRAY_SIZE(r300_auth_reg), | ||
| 1100 | &r300_packet0_check); | ||
| 1101 | break; | ||
| 1102 | case PACKET_TYPE2: | ||
| 1103 | break; | ||
| 1104 | case PACKET_TYPE3: | ||
| 1105 | r = r300_packet3_check(p, &pkt); | ||
| 1106 | break; | ||
| 1107 | default: | ||
| 1108 | DRM_ERROR("Unknown packet type %d !\n", pkt.type); | ||
| 1109 | return -EINVAL; | ||
| 1110 | } | ||
| 1111 | if (r) { | ||
| 1112 | return r; | ||
| 1113 | } | ||
| 1114 | } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); | ||
| 1115 | return 0; | ||
| 1116 | } | ||
diff --git a/drivers/gpu/drm/radeon/r300_reg.h b/drivers/gpu/drm/radeon/r300_reg.h index bdbc95fa6721..70f48609515e 100644 --- a/drivers/gpu/drm/radeon/r300_reg.h +++ b/drivers/gpu/drm/radeon/r300_reg.h | |||
| @@ -1,30 +1,34 @@ | |||
| 1 | /************************************************************************** | 1 | /* |
| 2 | 2 | * Copyright 2005 Nicolai Haehnle et al. | |
| 3 | Copyright (C) 2004-2005 Nicolai Haehnle et al. | 3 | * Copyright 2008 Advanced Micro Devices, Inc. |
| 4 | 4 | * Copyright 2009 Jerome Glisse. | |
| 5 | Permission is hereby granted, free of charge, to any person obtaining a | 5 | * |
| 6 | copy of this software and associated documentation files (the "Software"), | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
| 7 | to deal in the Software without restriction, including without limitation | 7 | * copy of this software and associated documentation files (the "Software"), |
| 8 | on the rights to use, copy, modify, merge, publish, distribute, sub | 8 | * to deal in the Software without restriction, including without limitation |
| 9 | license, and/or sell copies of the Software, and to permit persons to whom | 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| 10 | the Software is furnished to do so, subject to the following conditions: | 10 | * and/or sell copies of the Software, and to permit persons to whom the |
| 11 | 11 | * Software is furnished to do so, subject to the following conditions: | |
| 12 | The above copyright notice and this permission notice (including the next | 12 | * |
| 13 | paragraph) shall be included in all copies or substantial portions of the | 13 | * The above copyright notice and this permission notice shall be included in |
| 14 | Software. | 14 | * all copies or substantial portions of the Software. |
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Nicolai Haehnle | ||
| 25 | * Jerome Glisse | ||
| 26 | */ | ||
| 27 | #ifndef _R300_REG_H_ | ||
| 28 | #define _R300_REG_H_ | ||
| 15 | 29 | ||
| 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 20 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 21 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 22 | USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | 30 | ||
| 24 | **************************************************************************/ | ||
| 25 | 31 | ||
| 26 | #ifndef _R300_REG_H | ||
| 27 | #define _R300_REG_H | ||
| 28 | 32 | ||
| 29 | #define R300_MC_INIT_MISC_LAT_TIMER 0x180 | 33 | #define R300_MC_INIT_MISC_LAT_TIMER 0x180 |
| 30 | # define R300_MC_MISC__MC_CPR_INIT_LAT_SHIFT 0 | 34 | # define R300_MC_MISC__MC_CPR_INIT_LAT_SHIFT 0 |
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c new file mode 100644 index 000000000000..dea497a979f2 --- /dev/null +++ b/drivers/gpu/drm/radeon/r420.c | |||
| @@ -0,0 +1,223 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include <linux/seq_file.h> | ||
| 29 | #include "drmP.h" | ||
| 30 | #include "radeon_reg.h" | ||
| 31 | #include "radeon.h" | ||
| 32 | |||
| 33 | /* r420,r423,rv410 depends on : */ | ||
| 34 | void r100_pci_gart_disable(struct radeon_device *rdev); | ||
| 35 | void r100_hdp_reset(struct radeon_device *rdev); | ||
| 36 | void r100_mc_setup(struct radeon_device *rdev); | ||
| 37 | int r100_gui_wait_for_idle(struct radeon_device *rdev); | ||
| 38 | void r100_mc_disable_clients(struct radeon_device *rdev); | ||
| 39 | void r300_vram_info(struct radeon_device *rdev); | ||
| 40 | int r300_mc_wait_for_idle(struct radeon_device *rdev); | ||
| 41 | int rv370_pcie_gart_enable(struct radeon_device *rdev); | ||
| 42 | void rv370_pcie_gart_disable(struct radeon_device *rdev); | ||
| 43 | |||
| 44 | /* This files gather functions specifics to : | ||
| 45 | * r420,r423,rv410 | ||
| 46 | * | ||
| 47 | * Some of these functions might be used by newer ASICs. | ||
| 48 | */ | ||
| 49 | void r420_gpu_init(struct radeon_device *rdev); | ||
| 50 | int r420_debugfs_pipes_info_init(struct radeon_device *rdev); | ||
| 51 | |||
| 52 | |||
| 53 | /* | ||
| 54 | * MC | ||
| 55 | */ | ||
| 56 | int r420_mc_init(struct radeon_device *rdev) | ||
| 57 | { | ||
| 58 | int r; | ||
| 59 | |||
| 60 | if (r100_debugfs_rbbm_init(rdev)) { | ||
| 61 | DRM_ERROR("Failed to register debugfs file for RBBM !\n"); | ||
| 62 | } | ||
| 63 | if (r420_debugfs_pipes_info_init(rdev)) { | ||
| 64 | DRM_ERROR("Failed to register debugfs file for pipes !\n"); | ||
| 65 | } | ||
| 66 | |||
| 67 | r420_gpu_init(rdev); | ||
| 68 | r100_pci_gart_disable(rdev); | ||
| 69 | if (rdev->flags & RADEON_IS_PCIE) { | ||
| 70 | rv370_pcie_gart_disable(rdev); | ||
| 71 | } | ||
| 72 | |||
| 73 | /* Setup GPU memory space */ | ||
| 74 | rdev->mc.vram_location = 0xFFFFFFFFUL; | ||
| 75 | rdev->mc.gtt_location = 0xFFFFFFFFUL; | ||
| 76 | if (rdev->flags & RADEON_IS_AGP) { | ||
| 77 | r = radeon_agp_init(rdev); | ||
| 78 | if (r) { | ||
| 79 | printk(KERN_WARNING "[drm] Disabling AGP\n"); | ||
| 80 | rdev->flags &= ~RADEON_IS_AGP; | ||
| 81 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; | ||
| 82 | } else { | ||
| 83 | rdev->mc.gtt_location = rdev->mc.agp_base; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | r = radeon_mc_setup(rdev); | ||
| 87 | if (r) { | ||
| 88 | return r; | ||
| 89 | } | ||
| 90 | |||
| 91 | /* Program GPU memory space */ | ||
| 92 | r100_mc_disable_clients(rdev); | ||
| 93 | if (r300_mc_wait_for_idle(rdev)) { | ||
| 94 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 95 | "programming pipes. Bad things might happen.\n"); | ||
| 96 | } | ||
| 97 | r100_mc_setup(rdev); | ||
| 98 | return 0; | ||
| 99 | } | ||
| 100 | |||
| 101 | void r420_mc_fini(struct radeon_device *rdev) | ||
| 102 | { | ||
| 103 | rv370_pcie_gart_disable(rdev); | ||
| 104 | radeon_gart_table_vram_free(rdev); | ||
| 105 | radeon_gart_fini(rdev); | ||
| 106 | } | ||
| 107 | |||
| 108 | |||
| 109 | /* | ||
| 110 | * Global GPU functions | ||
| 111 | */ | ||
| 112 | void r420_errata(struct radeon_device *rdev) | ||
| 113 | { | ||
| 114 | rdev->pll_errata = 0; | ||
| 115 | } | ||
| 116 | |||
| 117 | void r420_pipes_init(struct radeon_device *rdev) | ||
| 118 | { | ||
| 119 | unsigned tmp; | ||
| 120 | unsigned gb_pipe_select; | ||
| 121 | unsigned num_pipes; | ||
| 122 | |||
| 123 | /* GA_ENHANCE workaround TCL deadlock issue */ | ||
| 124 | WREG32(0x4274, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)); | ||
| 125 | /* get max number of pipes */ | ||
| 126 | gb_pipe_select = RREG32(0x402C); | ||
| 127 | num_pipes = ((gb_pipe_select >> 12) & 3) + 1; | ||
| 128 | rdev->num_gb_pipes = num_pipes; | ||
| 129 | tmp = 0; | ||
| 130 | switch (num_pipes) { | ||
| 131 | default: | ||
| 132 | /* force to 1 pipe */ | ||
| 133 | num_pipes = 1; | ||
| 134 | case 1: | ||
| 135 | tmp = (0 << 1); | ||
| 136 | break; | ||
| 137 | case 2: | ||
| 138 | tmp = (3 << 1); | ||
| 139 | break; | ||
| 140 | case 3: | ||
| 141 | tmp = (6 << 1); | ||
| 142 | break; | ||
| 143 | case 4: | ||
| 144 | tmp = (7 << 1); | ||
| 145 | break; | ||
| 146 | } | ||
| 147 | WREG32(0x42C8, (1 << num_pipes) - 1); | ||
| 148 | /* Sub pixel 1/12 so we can have 4K rendering according to doc */ | ||
| 149 | tmp |= (1 << 4) | (1 << 0); | ||
| 150 | WREG32(0x4018, tmp); | ||
| 151 | if (r100_gui_wait_for_idle(rdev)) { | ||
| 152 | printk(KERN_WARNING "Failed to wait GUI idle while " | ||
| 153 | "programming pipes. Bad things might happen.\n"); | ||
| 154 | } | ||
| 155 | |||
| 156 | tmp = RREG32(0x170C); | ||
| 157 | WREG32(0x170C, tmp | (1 << 31)); | ||
| 158 | |||
| 159 | WREG32(R300_RB2D_DSTCACHE_MODE, | ||
| 160 | RREG32(R300_RB2D_DSTCACHE_MODE) | | ||
| 161 | R300_DC_AUTOFLUSH_ENABLE | | ||
| 162 | R300_DC_DC_DISABLE_IGNORE_PE); | ||
| 163 | |||
| 164 | if (r100_gui_wait_for_idle(rdev)) { | ||
| 165 | printk(KERN_WARNING "Failed to wait GUI idle while " | ||
| 166 | "programming pipes. Bad things might happen.\n"); | ||
| 167 | } | ||
| 168 | DRM_INFO("radeon: %d pipes initialized.\n", rdev->num_gb_pipes); | ||
| 169 | } | ||
| 170 | |||
| 171 | void r420_gpu_init(struct radeon_device *rdev) | ||
| 172 | { | ||
| 173 | r100_hdp_reset(rdev); | ||
| 174 | r420_pipes_init(rdev); | ||
| 175 | if (r300_mc_wait_for_idle(rdev)) { | ||
| 176 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 177 | "programming pipes. Bad things might happen.\n"); | ||
| 178 | } | ||
| 179 | } | ||
| 180 | |||
| 181 | |||
| 182 | /* | ||
| 183 | * r420,r423,rv410 VRAM info | ||
| 184 | */ | ||
| 185 | void r420_vram_info(struct radeon_device *rdev) | ||
| 186 | { | ||
| 187 | r300_vram_info(rdev); | ||
| 188 | } | ||
| 189 | |||
| 190 | |||
| 191 | /* | ||
| 192 | * Debugfs info | ||
| 193 | */ | ||
| 194 | #if defined(CONFIG_DEBUG_FS) | ||
| 195 | static int r420_debugfs_pipes_info(struct seq_file *m, void *data) | ||
| 196 | { | ||
| 197 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
| 198 | struct drm_device *dev = node->minor->dev; | ||
| 199 | struct radeon_device *rdev = dev->dev_private; | ||
| 200 | uint32_t tmp; | ||
| 201 | |||
| 202 | tmp = RREG32(R400_GB_PIPE_SELECT); | ||
| 203 | seq_printf(m, "GB_PIPE_SELECT 0x%08x\n", tmp); | ||
| 204 | tmp = RREG32(R300_GB_TILE_CONFIG); | ||
| 205 | seq_printf(m, "GB_TILE_CONFIG 0x%08x\n", tmp); | ||
| 206 | tmp = RREG32(R300_DST_PIPE_CONFIG); | ||
| 207 | seq_printf(m, "DST_PIPE_CONFIG 0x%08x\n", tmp); | ||
| 208 | return 0; | ||
| 209 | } | ||
| 210 | |||
| 211 | static struct drm_info_list r420_pipes_info_list[] = { | ||
| 212 | {"r420_pipes_info", r420_debugfs_pipes_info, 0, NULL}, | ||
| 213 | }; | ||
| 214 | #endif | ||
| 215 | |||
| 216 | int r420_debugfs_pipes_info_init(struct radeon_device *rdev) | ||
| 217 | { | ||
| 218 | #if defined(CONFIG_DEBUG_FS) | ||
| 219 | return radeon_debugfs_add_files(rdev, r420_pipes_info_list, 1); | ||
| 220 | #else | ||
| 221 | return 0; | ||
| 222 | #endif | ||
| 223 | } | ||
diff --git a/drivers/gpu/drm/radeon/r500_reg.h b/drivers/gpu/drm/radeon/r500_reg.h new file mode 100644 index 000000000000..9070a1c2ce23 --- /dev/null +++ b/drivers/gpu/drm/radeon/r500_reg.h | |||
| @@ -0,0 +1,749 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #ifndef __R500_REG_H__ | ||
| 29 | #define __R500_REG_H__ | ||
| 30 | |||
| 31 | /* pipe config regs */ | ||
| 32 | #define R300_GA_POLY_MODE 0x4288 | ||
| 33 | # define R300_FRONT_PTYPE_POINT (0 << 4) | ||
| 34 | # define R300_FRONT_PTYPE_LINE (1 << 4) | ||
| 35 | # define R300_FRONT_PTYPE_TRIANGE (2 << 4) | ||
| 36 | # define R300_BACK_PTYPE_POINT (0 << 7) | ||
| 37 | # define R300_BACK_PTYPE_LINE (1 << 7) | ||
| 38 | # define R300_BACK_PTYPE_TRIANGE (2 << 7) | ||
| 39 | #define R300_GA_ROUND_MODE 0x428c | ||
| 40 | # define R300_GEOMETRY_ROUND_TRUNC (0 << 0) | ||
| 41 | # define R300_GEOMETRY_ROUND_NEAREST (1 << 0) | ||
| 42 | # define R300_COLOR_ROUND_TRUNC (0 << 2) | ||
| 43 | # define R300_COLOR_ROUND_NEAREST (1 << 2) | ||
| 44 | #define R300_GB_MSPOS0 0x4010 | ||
| 45 | # define R300_MS_X0_SHIFT 0 | ||
| 46 | # define R300_MS_Y0_SHIFT 4 | ||
| 47 | # define R300_MS_X1_SHIFT 8 | ||
| 48 | # define R300_MS_Y1_SHIFT 12 | ||
| 49 | # define R300_MS_X2_SHIFT 16 | ||
| 50 | # define R300_MS_Y2_SHIFT 20 | ||
| 51 | # define R300_MSBD0_Y_SHIFT 24 | ||
| 52 | # define R300_MSBD0_X_SHIFT 28 | ||
| 53 | #define R300_GB_MSPOS1 0x4014 | ||
| 54 | # define R300_MS_X3_SHIFT 0 | ||
| 55 | # define R300_MS_Y3_SHIFT 4 | ||
| 56 | # define R300_MS_X4_SHIFT 8 | ||
| 57 | # define R300_MS_Y4_SHIFT 12 | ||
| 58 | # define R300_MS_X5_SHIFT 16 | ||
| 59 | # define R300_MS_Y5_SHIFT 20 | ||
| 60 | # define R300_MSBD1_SHIFT 24 | ||
| 61 | |||
| 62 | #define R300_GA_ENHANCE 0x4274 | ||
| 63 | # define R300_GA_DEADLOCK_CNTL (1 << 0) | ||
| 64 | # define R300_GA_FASTSYNC_CNTL (1 << 1) | ||
| 65 | #define R300_RB3D_DSTCACHE_CTLSTAT 0x4e4c | ||
| 66 | # define R300_RB3D_DC_FLUSH (2 << 0) | ||
| 67 | # define R300_RB3D_DC_FREE (2 << 2) | ||
| 68 | # define R300_RB3D_DC_FINISH (1 << 4) | ||
| 69 | #define R300_RB3D_ZCACHE_CTLSTAT 0x4f18 | ||
| 70 | # define R300_ZC_FLUSH (1 << 0) | ||
| 71 | # define R300_ZC_FREE (1 << 1) | ||
| 72 | # define R300_ZC_FLUSH_ALL 0x3 | ||
| 73 | #define R400_GB_PIPE_SELECT 0x402c | ||
| 74 | #define R500_DYN_SCLK_PWMEM_PIPE 0x000d /* PLL */ | ||
| 75 | #define R500_SU_REG_DEST 0x42c8 | ||
| 76 | #define R300_GB_TILE_CONFIG 0x4018 | ||
| 77 | # define R300_ENABLE_TILING (1 << 0) | ||
| 78 | # define R300_PIPE_COUNT_RV350 (0 << 1) | ||
| 79 | # define R300_PIPE_COUNT_R300 (3 << 1) | ||
| 80 | # define R300_PIPE_COUNT_R420_3P (6 << 1) | ||
| 81 | # define R300_PIPE_COUNT_R420 (7 << 1) | ||
| 82 | # define R300_TILE_SIZE_8 (0 << 4) | ||
| 83 | # define R300_TILE_SIZE_16 (1 << 4) | ||
| 84 | # define R300_TILE_SIZE_32 (2 << 4) | ||
| 85 | # define R300_SUBPIXEL_1_12 (0 << 16) | ||
| 86 | # define R300_SUBPIXEL_1_16 (1 << 16) | ||
| 87 | #define R300_DST_PIPE_CONFIG 0x170c | ||
| 88 | # define R300_PIPE_AUTO_CONFIG (1 << 31) | ||
| 89 | #define R300_RB2D_DSTCACHE_MODE 0x3428 | ||
| 90 | # define R300_DC_AUTOFLUSH_ENABLE (1 << 8) | ||
| 91 | # define R300_DC_DC_DISABLE_IGNORE_PE (1 << 17) | ||
| 92 | |||
| 93 | #define RADEON_CP_STAT 0x7C0 | ||
| 94 | #define RADEON_RBBM_CMDFIFO_ADDR 0xE70 | ||
| 95 | #define RADEON_RBBM_CMDFIFO_DATA 0xE74 | ||
| 96 | #define RADEON_ISYNC_CNTL 0x1724 | ||
| 97 | # define RADEON_ISYNC_ANY2D_IDLE3D (1 << 0) | ||
| 98 | # define RADEON_ISYNC_ANY3D_IDLE2D (1 << 1) | ||
| 99 | # define RADEON_ISYNC_TRIG2D_IDLE3D (1 << 2) | ||
| 100 | # define RADEON_ISYNC_TRIG3D_IDLE2D (1 << 3) | ||
| 101 | # define RADEON_ISYNC_WAIT_IDLEGUI (1 << 4) | ||
| 102 | # define RADEON_ISYNC_CPSCRATCH_IDLEGUI (1 << 5) | ||
| 103 | |||
| 104 | #define RS480_NB_MC_INDEX 0x168 | ||
| 105 | # define RS480_NB_MC_IND_WR_EN (1 << 8) | ||
| 106 | #define RS480_NB_MC_DATA 0x16c | ||
| 107 | |||
| 108 | /* | ||
| 109 | * RS690 | ||
| 110 | */ | ||
| 111 | #define RS690_MCCFG_FB_LOCATION 0x100 | ||
| 112 | #define RS690_MC_FB_START_MASK 0x0000FFFF | ||
| 113 | #define RS690_MC_FB_START_SHIFT 0 | ||
| 114 | #define RS690_MC_FB_TOP_MASK 0xFFFF0000 | ||
| 115 | #define RS690_MC_FB_TOP_SHIFT 16 | ||
| 116 | #define RS690_MCCFG_AGP_LOCATION 0x101 | ||
| 117 | #define RS690_MC_AGP_START_MASK 0x0000FFFF | ||
| 118 | #define RS690_MC_AGP_START_SHIFT 0 | ||
| 119 | #define RS690_MC_AGP_TOP_MASK 0xFFFF0000 | ||
| 120 | #define RS690_MC_AGP_TOP_SHIFT 16 | ||
| 121 | #define RS690_MCCFG_AGP_BASE 0x102 | ||
| 122 | #define RS690_MCCFG_AGP_BASE_2 0x103 | ||
| 123 | #define RS690_MC_INIT_MISC_LAT_TIMER 0x104 | ||
| 124 | #define RS690_HDP_FB_LOCATION 0x0134 | ||
| 125 | #define RS690_MC_INDEX 0x78 | ||
| 126 | # define RS690_MC_INDEX_MASK 0x1ff | ||
| 127 | # define RS690_MC_INDEX_WR_EN (1 << 9) | ||
| 128 | # define RS690_MC_INDEX_WR_ACK 0x7f | ||
| 129 | #define RS690_MC_DATA 0x7c | ||
| 130 | #define RS690_MC_STATUS 0x90 | ||
| 131 | #define RS690_MC_STATUS_IDLE (1 << 0) | ||
| 132 | #define RS480_AGP_BASE_2 0x0164 | ||
| 133 | #define RS480_MC_MISC_CNTL 0x18 | ||
| 134 | # define RS480_DISABLE_GTW (1 << 1) | ||
| 135 | # define RS480_GART_INDEX_REG_EN (1 << 12) | ||
| 136 | # define RS690_BLOCK_GFX_D3_EN (1 << 14) | ||
| 137 | #define RS480_GART_FEATURE_ID 0x2b | ||
| 138 | # define RS480_HANG_EN (1 << 11) | ||
| 139 | # define RS480_TLB_ENABLE (1 << 18) | ||
| 140 | # define RS480_P2P_ENABLE (1 << 19) | ||
| 141 | # define RS480_GTW_LAC_EN (1 << 25) | ||
| 142 | # define RS480_2LEVEL_GART (0 << 30) | ||
| 143 | # define RS480_1LEVEL_GART (1 << 30) | ||
| 144 | # define RS480_PDC_EN (1 << 31) | ||
| 145 | #define RS480_GART_BASE 0x2c | ||
| 146 | #define RS480_GART_CACHE_CNTRL 0x2e | ||
| 147 | # define RS480_GART_CACHE_INVALIDATE (1 << 0) /* wait for it to clear */ | ||
| 148 | #define RS480_AGP_ADDRESS_SPACE_SIZE 0x38 | ||
| 149 | # define RS480_GART_EN (1 << 0) | ||
| 150 | # define RS480_VA_SIZE_32MB (0 << 1) | ||
| 151 | # define RS480_VA_SIZE_64MB (1 << 1) | ||
| 152 | # define RS480_VA_SIZE_128MB (2 << 1) | ||
| 153 | # define RS480_VA_SIZE_256MB (3 << 1) | ||
| 154 | # define RS480_VA_SIZE_512MB (4 << 1) | ||
| 155 | # define RS480_VA_SIZE_1GB (5 << 1) | ||
| 156 | # define RS480_VA_SIZE_2GB (6 << 1) | ||
| 157 | #define RS480_AGP_MODE_CNTL 0x39 | ||
| 158 | # define RS480_POST_GART_Q_SIZE (1 << 18) | ||
| 159 | # define RS480_NONGART_SNOOP (1 << 19) | ||
| 160 | # define RS480_AGP_RD_BUF_SIZE (1 << 20) | ||
| 161 | # define RS480_REQ_TYPE_SNOOP_SHIFT 22 | ||
| 162 | # define RS480_REQ_TYPE_SNOOP_MASK 0x3 | ||
| 163 | # define RS480_REQ_TYPE_SNOOP_DIS (1 << 24) | ||
| 164 | |||
| 165 | #define RS690_AIC_CTRL_SCRATCH 0x3A | ||
| 166 | # define RS690_DIS_OUT_OF_PCI_GART_ACCESS (1 << 1) | ||
| 167 | |||
| 168 | /* | ||
| 169 | * RS600 | ||
| 170 | */ | ||
| 171 | #define RS600_MC_STATUS 0x0 | ||
| 172 | #define RS600_MC_STATUS_IDLE (1 << 0) | ||
| 173 | #define RS600_MC_INDEX 0x70 | ||
| 174 | # define RS600_MC_ADDR_MASK 0xffff | ||
| 175 | # define RS600_MC_IND_SEQ_RBS_0 (1 << 16) | ||
| 176 | # define RS600_MC_IND_SEQ_RBS_1 (1 << 17) | ||
| 177 | # define RS600_MC_IND_SEQ_RBS_2 (1 << 18) | ||
| 178 | # define RS600_MC_IND_SEQ_RBS_3 (1 << 19) | ||
| 179 | # define RS600_MC_IND_AIC_RBS (1 << 20) | ||
| 180 | # define RS600_MC_IND_CITF_ARB0 (1 << 21) | ||
| 181 | # define RS600_MC_IND_CITF_ARB1 (1 << 22) | ||
| 182 | # define RS600_MC_IND_WR_EN (1 << 23) | ||
| 183 | #define RS600_MC_DATA 0x74 | ||
| 184 | #define RS600_MC_STATUS 0x0 | ||
| 185 | # define RS600_MC_IDLE (1 << 1) | ||
| 186 | #define RS600_MC_FB_LOCATION 0x4 | ||
| 187 | #define RS600_MC_FB_START_MASK 0x0000FFFF | ||
| 188 | #define RS600_MC_FB_START_SHIFT 0 | ||
| 189 | #define RS600_MC_FB_TOP_MASK 0xFFFF0000 | ||
| 190 | #define RS600_MC_FB_TOP_SHIFT 16 | ||
| 191 | #define RS600_MC_AGP_LOCATION 0x5 | ||
| 192 | #define RS600_MC_AGP_START_MASK 0x0000FFFF | ||
| 193 | #define RS600_MC_AGP_START_SHIFT 0 | ||
| 194 | #define RS600_MC_AGP_TOP_MASK 0xFFFF0000 | ||
| 195 | #define RS600_MC_AGP_TOP_SHIFT 16 | ||
| 196 | #define RS600_MC_AGP_BASE 0x6 | ||
| 197 | #define RS600_MC_AGP_BASE_2 0x7 | ||
| 198 | #define RS600_MC_CNTL1 0x9 | ||
| 199 | # define RS600_ENABLE_PAGE_TABLES (1 << 26) | ||
| 200 | #define RS600_MC_PT0_CNTL 0x100 | ||
| 201 | # define RS600_ENABLE_PT (1 << 0) | ||
| 202 | # define RS600_EFFECTIVE_L2_CACHE_SIZE(x) ((x) << 15) | ||
| 203 | # define RS600_EFFECTIVE_L2_QUEUE_SIZE(x) ((x) << 21) | ||
| 204 | # define RS600_INVALIDATE_ALL_L1_TLBS (1 << 28) | ||
| 205 | # define RS600_INVALIDATE_L2_CACHE (1 << 29) | ||
| 206 | #define RS600_MC_PT0_CONTEXT0_CNTL 0x102 | ||
| 207 | # define RS600_ENABLE_PAGE_TABLE (1 << 0) | ||
| 208 | # define RS600_PAGE_TABLE_TYPE_FLAT (0 << 1) | ||
| 209 | #define RS600_MC_PT0_SYSTEM_APERTURE_LOW_ADDR 0x112 | ||
| 210 | #define RS600_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR 0x114 | ||
| 211 | #define RS600_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR 0x11c | ||
| 212 | #define RS600_MC_PT0_CONTEXT0_FLAT_BASE_ADDR 0x12c | ||
| 213 | #define RS600_MC_PT0_CONTEXT0_FLAT_START_ADDR 0x13c | ||
| 214 | #define RS600_MC_PT0_CONTEXT0_FLAT_END_ADDR 0x14c | ||
| 215 | #define RS600_MC_PT0_CLIENT0_CNTL 0x16c | ||
| 216 | # define RS600_ENABLE_TRANSLATION_MODE_OVERRIDE (1 << 0) | ||
| 217 | # define RS600_TRANSLATION_MODE_OVERRIDE (1 << 1) | ||
| 218 | # define RS600_SYSTEM_ACCESS_MODE_MASK (3 << 8) | ||
| 219 | # define RS600_SYSTEM_ACCESS_MODE_PA_ONLY (0 << 8) | ||
| 220 | # define RS600_SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 8) | ||
| 221 | # define RS600_SYSTEM_ACCESS_MODE_IN_SYS (2 << 8) | ||
| 222 | # define RS600_SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 8) | ||
| 223 | # define RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASSTHROUGH (0 << 10) | ||
| 224 | # define RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_DEFAULT_PAGE (1 << 10) | ||
| 225 | # define RS600_EFFECTIVE_L1_CACHE_SIZE(x) ((x) << 11) | ||
| 226 | # define RS600_ENABLE_FRAGMENT_PROCESSING (1 << 14) | ||
| 227 | # define RS600_EFFECTIVE_L1_QUEUE_SIZE(x) ((x) << 15) | ||
| 228 | # define RS600_INVALIDATE_L1_TLB (1 << 20) | ||
| 229 | /* rs600/rs690/rs740 */ | ||
| 230 | # define RS600_BUS_MASTER_DIS (1 << 14) | ||
| 231 | # define RS600_MSI_REARM (1 << 20) | ||
| 232 | /* see RS400_MSI_REARM in AIC_CNTL for rs480 */ | ||
| 233 | |||
| 234 | |||
| 235 | |||
| 236 | #define RV515_MC_FB_LOCATION 0x01 | ||
| 237 | #define RV515_MC_FB_START_MASK 0x0000FFFF | ||
| 238 | #define RV515_MC_FB_START_SHIFT 0 | ||
| 239 | #define RV515_MC_FB_TOP_MASK 0xFFFF0000 | ||
| 240 | #define RV515_MC_FB_TOP_SHIFT 16 | ||
| 241 | #define RV515_MC_AGP_LOCATION 0x02 | ||
| 242 | #define RV515_MC_AGP_START_MASK 0x0000FFFF | ||
| 243 | #define RV515_MC_AGP_START_SHIFT 0 | ||
| 244 | #define RV515_MC_AGP_TOP_MASK 0xFFFF0000 | ||
| 245 | #define RV515_MC_AGP_TOP_SHIFT 16 | ||
| 246 | #define RV515_MC_AGP_BASE 0x03 | ||
| 247 | #define RV515_MC_AGP_BASE_2 0x04 | ||
| 248 | |||
| 249 | #define R520_MC_FB_LOCATION 0x04 | ||
| 250 | #define R520_MC_FB_START_MASK 0x0000FFFF | ||
| 251 | #define R520_MC_FB_START_SHIFT 0 | ||
| 252 | #define R520_MC_FB_TOP_MASK 0xFFFF0000 | ||
| 253 | #define R520_MC_FB_TOP_SHIFT 16 | ||
| 254 | #define R520_MC_AGP_LOCATION 0x05 | ||
| 255 | #define R520_MC_AGP_START_MASK 0x0000FFFF | ||
| 256 | #define R520_MC_AGP_START_SHIFT 0 | ||
| 257 | #define R520_MC_AGP_TOP_MASK 0xFFFF0000 | ||
| 258 | #define R520_MC_AGP_TOP_SHIFT 16 | ||
| 259 | #define R520_MC_AGP_BASE 0x06 | ||
| 260 | #define R520_MC_AGP_BASE_2 0x07 | ||
| 261 | |||
| 262 | |||
| 263 | #define AVIVO_MC_INDEX 0x0070 | ||
| 264 | #define R520_MC_STATUS 0x00 | ||
| 265 | #define R520_MC_STATUS_IDLE (1<<1) | ||
| 266 | #define RV515_MC_STATUS 0x08 | ||
| 267 | #define RV515_MC_STATUS_IDLE (1<<4) | ||
| 268 | #define RV515_MC_INIT_MISC_LAT_TIMER 0x09 | ||
| 269 | #define AVIVO_MC_DATA 0x0074 | ||
| 270 | |||
| 271 | #define R520_MC_IND_INDEX 0x70 | ||
| 272 | #define R520_MC_IND_WR_EN (1 << 24) | ||
| 273 | #define R520_MC_IND_DATA 0x74 | ||
| 274 | |||
| 275 | #define RV515_MC_CNTL 0x5 | ||
| 276 | # define RV515_MEM_NUM_CHANNELS_MASK 0x3 | ||
| 277 | #define R520_MC_CNTL0 0x8 | ||
| 278 | # define R520_MEM_NUM_CHANNELS_MASK (0x3 << 24) | ||
| 279 | # define R520_MEM_NUM_CHANNELS_SHIFT 24 | ||
| 280 | # define R520_MC_CHANNEL_SIZE (1 << 23) | ||
| 281 | |||
| 282 | #define AVIVO_CP_DYN_CNTL 0x000f /* PLL */ | ||
| 283 | # define AVIVO_CP_FORCEON (1 << 0) | ||
| 284 | #define AVIVO_E2_DYN_CNTL 0x0011 /* PLL */ | ||
| 285 | # define AVIVO_E2_FORCEON (1 << 0) | ||
| 286 | #define AVIVO_IDCT_DYN_CNTL 0x0013 /* PLL */ | ||
| 287 | # define AVIVO_IDCT_FORCEON (1 << 0) | ||
| 288 | |||
| 289 | #define AVIVO_HDP_FB_LOCATION 0x134 | ||
| 290 | |||
| 291 | #define AVIVO_VGA_RENDER_CONTROL 0x0300 | ||
| 292 | # define AVIVO_VGA_VSTATUS_CNTL_MASK (3 << 16) | ||
| 293 | #define AVIVO_D1VGA_CONTROL 0x0330 | ||
| 294 | # define AVIVO_DVGA_CONTROL_MODE_ENABLE (1<<0) | ||
| 295 | # define AVIVO_DVGA_CONTROL_TIMING_SELECT (1<<8) | ||
| 296 | # define AVIVO_DVGA_CONTROL_SYNC_POLARITY_SELECT (1<<9) | ||
| 297 | # define AVIVO_DVGA_CONTROL_OVERSCAN_TIMING_SELECT (1<<10) | ||
| 298 | # define AVIVO_DVGA_CONTROL_OVERSCAN_COLOR_EN (1<<16) | ||
| 299 | # define AVIVO_DVGA_CONTROL_ROTATE (1<<24) | ||
| 300 | #define AVIVO_D2VGA_CONTROL 0x0338 | ||
| 301 | |||
| 302 | #define AVIVO_EXT1_PPLL_REF_DIV_SRC 0x400 | ||
| 303 | #define AVIVO_EXT1_PPLL_REF_DIV 0x404 | ||
| 304 | #define AVIVO_EXT1_PPLL_UPDATE_LOCK 0x408 | ||
| 305 | #define AVIVO_EXT1_PPLL_UPDATE_CNTL 0x40c | ||
| 306 | |||
| 307 | #define AVIVO_EXT2_PPLL_REF_DIV_SRC 0x410 | ||
| 308 | #define AVIVO_EXT2_PPLL_REF_DIV 0x414 | ||
| 309 | #define AVIVO_EXT2_PPLL_UPDATE_LOCK 0x418 | ||
| 310 | #define AVIVO_EXT2_PPLL_UPDATE_CNTL 0x41c | ||
| 311 | |||
| 312 | #define AVIVO_EXT1_PPLL_FB_DIV 0x430 | ||
| 313 | #define AVIVO_EXT2_PPLL_FB_DIV 0x434 | ||
| 314 | |||
| 315 | #define AVIVO_EXT1_PPLL_POST_DIV_SRC 0x438 | ||
| 316 | #define AVIVO_EXT1_PPLL_POST_DIV 0x43c | ||
| 317 | |||
| 318 | #define AVIVO_EXT2_PPLL_POST_DIV_SRC 0x440 | ||
| 319 | #define AVIVO_EXT2_PPLL_POST_DIV 0x444 | ||
| 320 | |||
| 321 | #define AVIVO_EXT1_PPLL_CNTL 0x448 | ||
| 322 | #define AVIVO_EXT2_PPLL_CNTL 0x44c | ||
| 323 | |||
| 324 | #define AVIVO_P1PLL_CNTL 0x450 | ||
| 325 | #define AVIVO_P2PLL_CNTL 0x454 | ||
| 326 | #define AVIVO_P1PLL_INT_SS_CNTL 0x458 | ||
| 327 | #define AVIVO_P2PLL_INT_SS_CNTL 0x45c | ||
| 328 | #define AVIVO_P1PLL_TMDSA_CNTL 0x460 | ||
| 329 | #define AVIVO_P2PLL_LVTMA_CNTL 0x464 | ||
| 330 | |||
| 331 | #define AVIVO_PCLK_CRTC1_CNTL 0x480 | ||
| 332 | #define AVIVO_PCLK_CRTC2_CNTL 0x484 | ||
| 333 | |||
| 334 | #define AVIVO_D1CRTC_H_TOTAL 0x6000 | ||
| 335 | #define AVIVO_D1CRTC_H_BLANK_START_END 0x6004 | ||
| 336 | #define AVIVO_D1CRTC_H_SYNC_A 0x6008 | ||
| 337 | #define AVIVO_D1CRTC_H_SYNC_A_CNTL 0x600c | ||
| 338 | #define AVIVO_D1CRTC_H_SYNC_B 0x6010 | ||
| 339 | #define AVIVO_D1CRTC_H_SYNC_B_CNTL 0x6014 | ||
| 340 | |||
| 341 | #define AVIVO_D1CRTC_V_TOTAL 0x6020 | ||
| 342 | #define AVIVO_D1CRTC_V_BLANK_START_END 0x6024 | ||
| 343 | #define AVIVO_D1CRTC_V_SYNC_A 0x6028 | ||
| 344 | #define AVIVO_D1CRTC_V_SYNC_A_CNTL 0x602c | ||
| 345 | #define AVIVO_D1CRTC_V_SYNC_B 0x6030 | ||
| 346 | #define AVIVO_D1CRTC_V_SYNC_B_CNTL 0x6034 | ||
| 347 | |||
| 348 | #define AVIVO_D1CRTC_CONTROL 0x6080 | ||
| 349 | # define AVIVO_CRTC_EN (1 << 0) | ||
| 350 | #define AVIVO_D1CRTC_BLANK_CONTROL 0x6084 | ||
| 351 | #define AVIVO_D1CRTC_INTERLACE_CONTROL 0x6088 | ||
| 352 | #define AVIVO_D1CRTC_INTERLACE_STATUS 0x608c | ||
| 353 | #define AVIVO_D1CRTC_STEREO_CONTROL 0x60c4 | ||
| 354 | |||
| 355 | /* master controls */ | ||
| 356 | #define AVIVO_DC_CRTC_MASTER_EN 0x60f8 | ||
| 357 | #define AVIVO_DC_CRTC_TV_CONTROL 0x60fc | ||
| 358 | |||
| 359 | #define AVIVO_D1GRPH_ENABLE 0x6100 | ||
| 360 | #define AVIVO_D1GRPH_CONTROL 0x6104 | ||
| 361 | # define AVIVO_D1GRPH_CONTROL_DEPTH_8BPP (0 << 0) | ||
| 362 | # define AVIVO_D1GRPH_CONTROL_DEPTH_16BPP (1 << 0) | ||
| 363 | # define AVIVO_D1GRPH_CONTROL_DEPTH_32BPP (2 << 0) | ||
| 364 | # define AVIVO_D1GRPH_CONTROL_DEPTH_64BPP (3 << 0) | ||
| 365 | |||
| 366 | # define AVIVO_D1GRPH_CONTROL_8BPP_INDEXED (0 << 8) | ||
| 367 | |||
| 368 | # define AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555 (0 << 8) | ||
| 369 | # define AVIVO_D1GRPH_CONTROL_16BPP_RGB565 (1 << 8) | ||
| 370 | # define AVIVO_D1GRPH_CONTROL_16BPP_ARGB4444 (2 << 8) | ||
| 371 | # define AVIVO_D1GRPH_CONTROL_16BPP_AI88 (3 << 8) | ||
| 372 | # define AVIVO_D1GRPH_CONTROL_16BPP_MONO16 (4 << 8) | ||
| 373 | |||
| 374 | # define AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888 (0 << 8) | ||
| 375 | # define AVIVO_D1GRPH_CONTROL_32BPP_ARGB2101010 (1 << 8) | ||
| 376 | # define AVIVO_D1GRPH_CONTROL_32BPP_DIGITAL (2 << 8) | ||
| 377 | # define AVIVO_D1GRPH_CONTROL_32BPP_8B_ARGB2101010 (3 << 8) | ||
| 378 | |||
| 379 | |||
| 380 | # define AVIVO_D1GRPH_CONTROL_64BPP_ARGB16161616 (0 << 8) | ||
| 381 | |||
| 382 | # define AVIVO_D1GRPH_SWAP_RB (1 << 16) | ||
| 383 | # define AVIVO_D1GRPH_TILED (1 << 20) | ||
| 384 | # define AVIVO_D1GRPH_MACRO_ADDRESS_MODE (1 << 21) | ||
| 385 | |||
| 386 | #define AVIVO_D1GRPH_LUT_SEL 0x6108 | ||
| 387 | #define AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS 0x6110 | ||
| 388 | #define AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS 0x6118 | ||
| 389 | #define AVIVO_D1GRPH_PITCH 0x6120 | ||
| 390 | #define AVIVO_D1GRPH_SURFACE_OFFSET_X 0x6124 | ||
| 391 | #define AVIVO_D1GRPH_SURFACE_OFFSET_Y 0x6128 | ||
| 392 | #define AVIVO_D1GRPH_X_START 0x612c | ||
| 393 | #define AVIVO_D1GRPH_Y_START 0x6130 | ||
| 394 | #define AVIVO_D1GRPH_X_END 0x6134 | ||
| 395 | #define AVIVO_D1GRPH_Y_END 0x6138 | ||
| 396 | #define AVIVO_D1GRPH_UPDATE 0x6144 | ||
| 397 | # define AVIVO_D1GRPH_UPDATE_LOCK (1 << 16) | ||
| 398 | #define AVIVO_D1GRPH_FLIP_CONTROL 0x6148 | ||
| 399 | |||
| 400 | #define AVIVO_D1CUR_CONTROL 0x6400 | ||
| 401 | # define AVIVO_D1CURSOR_EN (1 << 0) | ||
| 402 | # define AVIVO_D1CURSOR_MODE_SHIFT 8 | ||
| 403 | # define AVIVO_D1CURSOR_MODE_MASK (3 << 8) | ||
| 404 | # define AVIVO_D1CURSOR_MODE_24BPP 2 | ||
| 405 | #define AVIVO_D1CUR_SURFACE_ADDRESS 0x6408 | ||
| 406 | #define AVIVO_D1CUR_SIZE 0x6410 | ||
| 407 | #define AVIVO_D1CUR_POSITION 0x6414 | ||
| 408 | #define AVIVO_D1CUR_HOT_SPOT 0x6418 | ||
| 409 | #define AVIVO_D1CUR_UPDATE 0x6424 | ||
| 410 | # define AVIVO_D1CURSOR_UPDATE_LOCK (1 << 16) | ||
| 411 | |||
| 412 | #define AVIVO_DC_LUT_RW_SELECT 0x6480 | ||
| 413 | #define AVIVO_DC_LUT_RW_MODE 0x6484 | ||
| 414 | #define AVIVO_DC_LUT_RW_INDEX 0x6488 | ||
| 415 | #define AVIVO_DC_LUT_SEQ_COLOR 0x648c | ||
| 416 | #define AVIVO_DC_LUT_PWL_DATA 0x6490 | ||
| 417 | #define AVIVO_DC_LUT_30_COLOR 0x6494 | ||
| 418 | #define AVIVO_DC_LUT_READ_PIPE_SELECT 0x6498 | ||
| 419 | #define AVIVO_DC_LUT_WRITE_EN_MASK 0x649c | ||
| 420 | #define AVIVO_DC_LUT_AUTOFILL 0x64a0 | ||
| 421 | |||
| 422 | #define AVIVO_DC_LUTA_CONTROL 0x64c0 | ||
| 423 | #define AVIVO_DC_LUTA_BLACK_OFFSET_BLUE 0x64c4 | ||
| 424 | #define AVIVO_DC_LUTA_BLACK_OFFSET_GREEN 0x64c8 | ||
| 425 | #define AVIVO_DC_LUTA_BLACK_OFFSET_RED 0x64cc | ||
| 426 | #define AVIVO_DC_LUTA_WHITE_OFFSET_BLUE 0x64d0 | ||
| 427 | #define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN 0x64d4 | ||
| 428 | #define AVIVO_DC_LUTA_WHITE_OFFSET_RED 0x64d8 | ||
| 429 | |||
| 430 | #define AVIVO_DC_LB_MEMORY_SPLIT 0x6520 | ||
| 431 | # define AVIVO_DC_LB_MEMORY_SPLIT_MASK 0x3 | ||
| 432 | # define AVIVO_DC_LB_MEMORY_SPLIT_SHIFT 0 | ||
| 433 | # define AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF 0 | ||
| 434 | # define AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q 1 | ||
| 435 | # define AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY 2 | ||
| 436 | # define AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q 3 | ||
| 437 | # define AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE (1 << 2) | ||
| 438 | # define AVIVO_DC_LB_DISP1_END_ADR_SHIFT 4 | ||
| 439 | # define AVIVO_DC_LB_DISP1_END_ADR_MASK 0x7ff | ||
| 440 | |||
| 441 | #define R500_DxMODE_INT_MASK 0x6540 | ||
| 442 | #define R500_D1MODE_INT_MASK (1<<0) | ||
| 443 | #define R500_D2MODE_INT_MASK (1<<8) | ||
| 444 | |||
| 445 | #define AVIVO_D1MODE_DATA_FORMAT 0x6528 | ||
| 446 | # define AVIVO_D1MODE_INTERLEAVE_EN (1 << 0) | ||
| 447 | #define AVIVO_D1MODE_DESKTOP_HEIGHT 0x652C | ||
| 448 | #define AVIVO_D1MODE_VIEWPORT_START 0x6580 | ||
| 449 | #define AVIVO_D1MODE_VIEWPORT_SIZE 0x6584 | ||
| 450 | #define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6588 | ||
| 451 | #define AVIVO_D1MODE_EXT_OVERSCAN_TOP_BOTTOM 0x658c | ||
| 452 | |||
| 453 | #define AVIVO_D1SCL_SCALER_ENABLE 0x6590 | ||
| 454 | #define AVIVO_D1SCL_SCALER_TAP_CONTROL 0x6594 | ||
| 455 | #define AVIVO_D1SCL_UPDATE 0x65cc | ||
| 456 | # define AVIVO_D1SCL_UPDATE_LOCK (1 << 16) | ||
| 457 | |||
| 458 | /* second crtc */ | ||
| 459 | #define AVIVO_D2CRTC_H_TOTAL 0x6800 | ||
| 460 | #define AVIVO_D2CRTC_H_BLANK_START_END 0x6804 | ||
| 461 | #define AVIVO_D2CRTC_H_SYNC_A 0x6808 | ||
| 462 | #define AVIVO_D2CRTC_H_SYNC_A_CNTL 0x680c | ||
| 463 | #define AVIVO_D2CRTC_H_SYNC_B 0x6810 | ||
| 464 | #define AVIVO_D2CRTC_H_SYNC_B_CNTL 0x6814 | ||
| 465 | |||
| 466 | #define AVIVO_D2CRTC_V_TOTAL 0x6820 | ||
| 467 | #define AVIVO_D2CRTC_V_BLANK_START_END 0x6824 | ||
| 468 | #define AVIVO_D2CRTC_V_SYNC_A 0x6828 | ||
| 469 | #define AVIVO_D2CRTC_V_SYNC_A_CNTL 0x682c | ||
| 470 | #define AVIVO_D2CRTC_V_SYNC_B 0x6830 | ||
| 471 | #define AVIVO_D2CRTC_V_SYNC_B_CNTL 0x6834 | ||
| 472 | |||
| 473 | #define AVIVO_D2CRTC_CONTROL 0x6880 | ||
| 474 | #define AVIVO_D2CRTC_BLANK_CONTROL 0x6884 | ||
| 475 | #define AVIVO_D2CRTC_INTERLACE_CONTROL 0x6888 | ||
| 476 | #define AVIVO_D2CRTC_INTERLACE_STATUS 0x688c | ||
| 477 | #define AVIVO_D2CRTC_STEREO_CONTROL 0x68c4 | ||
| 478 | |||
| 479 | #define AVIVO_D2GRPH_ENABLE 0x6900 | ||
| 480 | #define AVIVO_D2GRPH_CONTROL 0x6904 | ||
| 481 | #define AVIVO_D2GRPH_LUT_SEL 0x6908 | ||
| 482 | #define AVIVO_D2GRPH_PRIMARY_SURFACE_ADDRESS 0x6910 | ||
| 483 | #define AVIVO_D2GRPH_SECONDARY_SURFACE_ADDRESS 0x6918 | ||
| 484 | #define AVIVO_D2GRPH_PITCH 0x6920 | ||
| 485 | #define AVIVO_D2GRPH_SURFACE_OFFSET_X 0x6924 | ||
| 486 | #define AVIVO_D2GRPH_SURFACE_OFFSET_Y 0x6928 | ||
| 487 | #define AVIVO_D2GRPH_X_START 0x692c | ||
| 488 | #define AVIVO_D2GRPH_Y_START 0x6930 | ||
| 489 | #define AVIVO_D2GRPH_X_END 0x6934 | ||
| 490 | #define AVIVO_D2GRPH_Y_END 0x6938 | ||
| 491 | #define AVIVO_D2GRPH_UPDATE 0x6944 | ||
| 492 | #define AVIVO_D2GRPH_FLIP_CONTROL 0x6948 | ||
| 493 | |||
| 494 | #define AVIVO_D2CUR_CONTROL 0x6c00 | ||
| 495 | #define AVIVO_D2CUR_SURFACE_ADDRESS 0x6c08 | ||
| 496 | #define AVIVO_D2CUR_SIZE 0x6c10 | ||
| 497 | #define AVIVO_D2CUR_POSITION 0x6c14 | ||
| 498 | |||
| 499 | #define AVIVO_D2MODE_VIEWPORT_START 0x6d80 | ||
| 500 | #define AVIVO_D2MODE_VIEWPORT_SIZE 0x6d84 | ||
| 501 | #define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6d88 | ||
| 502 | #define AVIVO_D2MODE_EXT_OVERSCAN_TOP_BOTTOM 0x6d8c | ||
| 503 | |||
| 504 | #define AVIVO_D2SCL_SCALER_ENABLE 0x6d90 | ||
| 505 | #define AVIVO_D2SCL_SCALER_TAP_CONTROL 0x6d94 | ||
| 506 | |||
| 507 | #define AVIVO_DDIA_BIT_DEPTH_CONTROL 0x7214 | ||
| 508 | |||
| 509 | #define AVIVO_DACA_ENABLE 0x7800 | ||
| 510 | # define AVIVO_DAC_ENABLE (1 << 0) | ||
| 511 | #define AVIVO_DACA_SOURCE_SELECT 0x7804 | ||
| 512 | # define AVIVO_DAC_SOURCE_CRTC1 (0 << 0) | ||
| 513 | # define AVIVO_DAC_SOURCE_CRTC2 (1 << 0) | ||
| 514 | # define AVIVO_DAC_SOURCE_TV (2 << 0) | ||
| 515 | |||
| 516 | #define AVIVO_DACA_FORCE_OUTPUT_CNTL 0x783c | ||
| 517 | # define AVIVO_DACA_FORCE_OUTPUT_CNTL_FORCE_DATA_EN (1 << 0) | ||
| 518 | # define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_SEL_SHIFT (8) | ||
| 519 | # define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_SEL_BLUE (1 << 0) | ||
| 520 | # define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_SEL_GREEN (1 << 1) | ||
| 521 | # define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_SEL_RED (1 << 2) | ||
| 522 | # define AVIVO_DACA_FORCE_OUTPUT_CNTL_DATA_ON_BLANKB_ONLY (1 << 24) | ||
| 523 | #define AVIVO_DACA_POWERDOWN 0x7850 | ||
| 524 | # define AVIVO_DACA_POWERDOWN_POWERDOWN (1 << 0) | ||
| 525 | # define AVIVO_DACA_POWERDOWN_BLUE (1 << 8) | ||
| 526 | # define AVIVO_DACA_POWERDOWN_GREEN (1 << 16) | ||
| 527 | # define AVIVO_DACA_POWERDOWN_RED (1 << 24) | ||
| 528 | |||
| 529 | #define AVIVO_DACB_ENABLE 0x7a00 | ||
| 530 | #define AVIVO_DACB_SOURCE_SELECT 0x7a04 | ||
| 531 | #define AVIVO_DACB_FORCE_OUTPUT_CNTL 0x7a3c | ||
| 532 | # define AVIVO_DACB_FORCE_OUTPUT_CNTL_FORCE_DATA_EN (1 << 0) | ||
| 533 | # define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_SEL_SHIFT (8) | ||
| 534 | # define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_SEL_BLUE (1 << 0) | ||
| 535 | # define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_SEL_GREEN (1 << 1) | ||
| 536 | # define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_SEL_RED (1 << 2) | ||
| 537 | # define AVIVO_DACB_FORCE_OUTPUT_CNTL_DATA_ON_BLANKB_ONLY (1 << 24) | ||
| 538 | #define AVIVO_DACB_POWERDOWN 0x7a50 | ||
| 539 | # define AVIVO_DACB_POWERDOWN_POWERDOWN (1 << 0) | ||
| 540 | # define AVIVO_DACB_POWERDOWN_BLUE (1 << 8) | ||
| 541 | # define AVIVO_DACB_POWERDOWN_GREEN (1 << 16) | ||
| 542 | # define AVIVO_DACB_POWERDOWN_RED | ||
| 543 | |||
| 544 | #define AVIVO_TMDSA_CNTL 0x7880 | ||
| 545 | # define AVIVO_TMDSA_CNTL_ENABLE (1 << 0) | ||
| 546 | # define AVIVO_TMDSA_CNTL_HPD_MASK (1 << 4) | ||
| 547 | # define AVIVO_TMDSA_CNTL_HPD_SELECT (1 << 8) | ||
| 548 | # define AVIVO_TMDSA_CNTL_SYNC_PHASE (1 << 12) | ||
| 549 | # define AVIVO_TMDSA_CNTL_PIXEL_ENCODING (1 << 16) | ||
| 550 | # define AVIVO_TMDSA_CNTL_DUAL_LINK_ENABLE (1 << 24) | ||
| 551 | # define AVIVO_TMDSA_CNTL_SWAP (1 << 28) | ||
| 552 | #define AVIVO_TMDSA_SOURCE_SELECT 0x7884 | ||
| 553 | /* 78a8 appears to be some kind of (reasonably tolerant) clock? | ||
| 554 | * 78d0 definitely hits the transmitter, definitely clock. */ | ||
| 555 | /* MYSTERY1 This appears to control dithering? */ | ||
| 556 | #define AVIVO_TMDSA_BIT_DEPTH_CONTROL 0x7894 | ||
| 557 | # define AVIVO_TMDS_BIT_DEPTH_CONTROL_TRUNCATE_EN (1 << 0) | ||
| 558 | # define AVIVO_TMDS_BIT_DEPTH_CONTROL_TRUNCATE_DEPTH (1 << 4) | ||
| 559 | # define AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN (1 << 8) | ||
| 560 | # define AVIVO_TMDS_BIT_DEPTH_CONTROL_SPATIAL_DITHER_DEPTH (1 << 12) | ||
| 561 | # define AVIVO_TMDS_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_EN (1 << 16) | ||
| 562 | # define AVIVO_TMDS_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_DEPTH (1 << 20) | ||
| 563 | # define AVIVO_TMDS_BIT_DEPTH_CONTROL_TEMPORAL_LEVEL (1 << 24) | ||
| 564 | # define AVIVO_TMDS_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_RESET (1 << 26) | ||
| 565 | #define AVIVO_TMDSA_DCBALANCER_CONTROL 0x78d0 | ||
| 566 | # define AVIVO_TMDSA_DCBALANCER_CONTROL_EN (1 << 0) | ||
| 567 | # define AVIVO_TMDSA_DCBALANCER_CONTROL_TEST_EN (1 << 8) | ||
| 568 | # define AVIVO_TMDSA_DCBALANCER_CONTROL_TEST_IN_SHIFT (16) | ||
| 569 | # define AVIVO_TMDSA_DCBALANCER_CONTROL_FORCE (1 << 24) | ||
| 570 | #define AVIVO_TMDSA_DATA_SYNCHRONIZATION 0x78d8 | ||
| 571 | # define AVIVO_TMDSA_DATA_SYNCHRONIZATION_DSYNSEL (1 << 0) | ||
| 572 | # define AVIVO_TMDSA_DATA_SYNCHRONIZATION_PFREQCHG (1 << 8) | ||
| 573 | #define AVIVO_TMDSA_CLOCK_ENABLE 0x7900 | ||
| 574 | #define AVIVO_TMDSA_TRANSMITTER_ENABLE 0x7904 | ||
| 575 | # define AVIVO_TMDSA_TRANSMITTER_ENABLE_TX0_ENABLE (1 << 0) | ||
| 576 | # define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKC0EN (1 << 1) | ||
| 577 | # define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD00EN (1 << 2) | ||
| 578 | # define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD01EN (1 << 3) | ||
| 579 | # define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD02EN (1 << 4) | ||
| 580 | # define AVIVO_TMDSA_TRANSMITTER_ENABLE_TX1_ENABLE (1 << 8) | ||
| 581 | # define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD10EN (1 << 10) | ||
| 582 | # define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD11EN (1 << 11) | ||
| 583 | # define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKD12EN (1 << 12) | ||
| 584 | # define AVIVO_TMDSA_TRANSMITTER_ENABLE_TX_ENABLE_HPD_MASK (1 << 16) | ||
| 585 | # define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKCEN_HPD_MASK (1 << 17) | ||
| 586 | # define AVIVO_TMDSA_TRANSMITTER_ENABLE_LNKDEN_HPD_MASK (1 << 18) | ||
| 587 | |||
| 588 | #define AVIVO_TMDSA_TRANSMITTER_CONTROL 0x7910 | ||
| 589 | # define AVIVO_TMDSA_TRANSMITTER_CONTROL_PLL_ENABLE (1 << 0) | ||
| 590 | # define AVIVO_TMDSA_TRANSMITTER_CONTROL_PLL_RESET (1 << 1) | ||
| 591 | # define AVIVO_TMDSA_TRANSMITTER_CONTROL_PLL_HPD_MASK_SHIFT (2) | ||
| 592 | # define AVIVO_TMDSA_TRANSMITTER_CONTROL_IDSCKSEL (1 << 4) | ||
| 593 | # define AVIVO_TMDSA_TRANSMITTER_CONTROL_BGSLEEP (1 << 5) | ||
| 594 | # define AVIVO_TMDSA_TRANSMITTER_CONTROL_PLL_PWRUP_SEQ_EN (1 << 6) | ||
| 595 | # define AVIVO_TMDSA_TRANSMITTER_CONTROL_TMCLK (1 << 8) | ||
| 596 | # define AVIVO_TMDSA_TRANSMITTER_CONTROL_TMCLK_FROM_PADS (1 << 13) | ||
| 597 | # define AVIVO_TMDSA_TRANSMITTER_CONTROL_TDCLK (1 << 14) | ||
| 598 | # define AVIVO_TMDSA_TRANSMITTER_CONTROL_TDCLK_FROM_PADS (1 << 15) | ||
| 599 | # define AVIVO_TMDSA_TRANSMITTER_CONTROL_CLK_PATTERN_SHIFT (16) | ||
| 600 | # define AVIVO_TMDSA_TRANSMITTER_CONTROL_BYPASS_PLL (1 << 28) | ||
| 601 | # define AVIVO_TMDSA_TRANSMITTER_CONTROL_USE_CLK_DATA (1 << 29) | ||
| 602 | # define AVIVO_TMDSA_TRANSMITTER_CONTROL_INPUT_TEST_CLK_SEL (1 << 31) | ||
| 603 | |||
| 604 | #define AVIVO_LVTMA_CNTL 0x7a80 | ||
| 605 | # define AVIVO_LVTMA_CNTL_ENABLE (1 << 0) | ||
| 606 | # define AVIVO_LVTMA_CNTL_HPD_MASK (1 << 4) | ||
| 607 | # define AVIVO_LVTMA_CNTL_HPD_SELECT (1 << 8) | ||
| 608 | # define AVIVO_LVTMA_CNTL_SYNC_PHASE (1 << 12) | ||
| 609 | # define AVIVO_LVTMA_CNTL_PIXEL_ENCODING (1 << 16) | ||
| 610 | # define AVIVO_LVTMA_CNTL_DUAL_LINK_ENABLE (1 << 24) | ||
| 611 | # define AVIVO_LVTMA_CNTL_SWAP (1 << 28) | ||
| 612 | #define AVIVO_LVTMA_SOURCE_SELECT 0x7a84 | ||
| 613 | #define AVIVO_LVTMA_COLOR_FORMAT 0x7a88 | ||
| 614 | #define AVIVO_LVTMA_BIT_DEPTH_CONTROL 0x7a94 | ||
| 615 | # define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN (1 << 0) | ||
| 616 | # define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_DEPTH (1 << 4) | ||
| 617 | # define AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN (1 << 8) | ||
| 618 | # define AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_DEPTH (1 << 12) | ||
| 619 | # define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_EN (1 << 16) | ||
| 620 | # define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_DEPTH (1 << 20) | ||
| 621 | # define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TEMPORAL_LEVEL (1 << 24) | ||
| 622 | # define AVIVO_LVTMA_BIT_DEPTH_CONTROL_TEMPORAL_DITHER_RESET (1 << 26) | ||
| 623 | |||
| 624 | |||
| 625 | |||
| 626 | #define AVIVO_LVTMA_DCBALANCER_CONTROL 0x7ad0 | ||
| 627 | # define AVIVO_LVTMA_DCBALANCER_CONTROL_EN (1 << 0) | ||
| 628 | # define AVIVO_LVTMA_DCBALANCER_CONTROL_TEST_EN (1 << 8) | ||
| 629 | # define AVIVO_LVTMA_DCBALANCER_CONTROL_TEST_IN_SHIFT (16) | ||
| 630 | # define AVIVO_LVTMA_DCBALANCER_CONTROL_FORCE (1 << 24) | ||
| 631 | |||
| 632 | #define AVIVO_LVTMA_DATA_SYNCHRONIZATION 0x78d8 | ||
| 633 | # define AVIVO_LVTMA_DATA_SYNCHRONIZATION_DSYNSEL (1 << 0) | ||
| 634 | # define AVIVO_LVTMA_DATA_SYNCHRONIZATION_PFREQCHG (1 << 8) | ||
| 635 | #define R500_LVTMA_CLOCK_ENABLE 0x7b00 | ||
| 636 | #define R600_LVTMA_CLOCK_ENABLE 0x7b04 | ||
| 637 | |||
| 638 | #define R500_LVTMA_TRANSMITTER_ENABLE 0x7b04 | ||
| 639 | #define R600_LVTMA_TRANSMITTER_ENABLE 0x7b08 | ||
| 640 | # define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKC0EN (1 << 1) | ||
| 641 | # define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD00EN (1 << 2) | ||
| 642 | # define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD01EN (1 << 3) | ||
| 643 | # define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD02EN (1 << 4) | ||
| 644 | # define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD03EN (1 << 5) | ||
| 645 | # define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKC1EN (1 << 9) | ||
| 646 | # define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD10EN (1 << 10) | ||
| 647 | # define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD11EN (1 << 11) | ||
| 648 | # define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKD12EN (1 << 12) | ||
| 649 | # define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKCEN_HPD_MASK (1 << 17) | ||
| 650 | # define AVIVO_LVTMA_TRANSMITTER_ENABLE_LNKDEN_HPD_MASK (1 << 18) | ||
| 651 | |||
| 652 | #define R500_LVTMA_TRANSMITTER_CONTROL 0x7b10 | ||
| 653 | #define R600_LVTMA_TRANSMITTER_CONTROL 0x7b14 | ||
| 654 | # define AVIVO_LVTMA_TRANSMITTER_CONTROL_PLL_ENABLE (1 << 0) | ||
| 655 | # define AVIVO_LVTMA_TRANSMITTER_CONTROL_PLL_RESET (1 << 1) | ||
| 656 | # define AVIVO_LVTMA_TRANSMITTER_CONTROL_PLL_HPD_MASK_SHIFT (2) | ||
| 657 | # define AVIVO_LVTMA_TRANSMITTER_CONTROL_IDSCKSEL (1 << 4) | ||
| 658 | # define AVIVO_LVTMA_TRANSMITTER_CONTROL_BGSLEEP (1 << 5) | ||
| 659 | # define AVIVO_LVTMA_TRANSMITTER_CONTROL_PLL_PWRUP_SEQ_EN (1 << 6) | ||
| 660 | # define AVIVO_LVTMA_TRANSMITTER_CONTROL_TMCLK (1 << 8) | ||
| 661 | # define AVIVO_LVTMA_TRANSMITTER_CONTROL_TMCLK_FROM_PADS (1 << 13) | ||
| 662 | # define AVIVO_LVTMA_TRANSMITTER_CONTROL_TDCLK (1 << 14) | ||
| 663 | # define AVIVO_LVTMA_TRANSMITTER_CONTROL_TDCLK_FROM_PADS (1 << 15) | ||
| 664 | # define AVIVO_LVTMA_TRANSMITTER_CONTROL_CLK_PATTERN_SHIFT (16) | ||
| 665 | # define AVIVO_LVTMA_TRANSMITTER_CONTROL_BYPASS_PLL (1 << 28) | ||
| 666 | # define AVIVO_LVTMA_TRANSMITTER_CONTROL_USE_CLK_DATA (1 << 29) | ||
| 667 | # define AVIVO_LVTMA_TRANSMITTER_CONTROL_INPUT_TEST_CLK_SEL (1 << 31) | ||
| 668 | |||
| 669 | #define R500_LVTMA_PWRSEQ_CNTL 0x7af0 | ||
| 670 | #define R600_LVTMA_PWRSEQ_CNTL 0x7af4 | ||
| 671 | # define AVIVO_LVTMA_PWRSEQ_EN (1 << 0) | ||
| 672 | # define AVIVO_LVTMA_PWRSEQ_PLL_ENABLE_MASK (1 << 2) | ||
| 673 | # define AVIVO_LVTMA_PWRSEQ_PLL_RESET_MASK (1 << 3) | ||
| 674 | # define AVIVO_LVTMA_PWRSEQ_TARGET_STATE (1 << 4) | ||
| 675 | # define AVIVO_LVTMA_SYNCEN (1 << 8) | ||
| 676 | # define AVIVO_LVTMA_SYNCEN_OVRD (1 << 9) | ||
| 677 | # define AVIVO_LVTMA_SYNCEN_POL (1 << 10) | ||
| 678 | # define AVIVO_LVTMA_DIGON (1 << 16) | ||
| 679 | # define AVIVO_LVTMA_DIGON_OVRD (1 << 17) | ||
| 680 | # define AVIVO_LVTMA_DIGON_POL (1 << 18) | ||
| 681 | # define AVIVO_LVTMA_BLON (1 << 24) | ||
| 682 | # define AVIVO_LVTMA_BLON_OVRD (1 << 25) | ||
| 683 | # define AVIVO_LVTMA_BLON_POL (1 << 26) | ||
| 684 | |||
| 685 | #define R500_LVTMA_PWRSEQ_STATE 0x7af4 | ||
| 686 | #define R600_LVTMA_PWRSEQ_STATE 0x7af8 | ||
| 687 | # define AVIVO_LVTMA_PWRSEQ_STATE_TARGET_STATE_R (1 << 0) | ||
| 688 | # define AVIVO_LVTMA_PWRSEQ_STATE_DIGON (1 << 1) | ||
| 689 | # define AVIVO_LVTMA_PWRSEQ_STATE_SYNCEN (1 << 2) | ||
| 690 | # define AVIVO_LVTMA_PWRSEQ_STATE_BLON (1 << 3) | ||
| 691 | # define AVIVO_LVTMA_PWRSEQ_STATE_DONE (1 << 4) | ||
| 692 | # define AVIVO_LVTMA_PWRSEQ_STATE_STATUS_SHIFT (8) | ||
| 693 | |||
| 694 | #define AVIVO_LVDS_BACKLIGHT_CNTL 0x7af8 | ||
| 695 | # define AVIVO_LVDS_BACKLIGHT_CNTL_EN (1 << 0) | ||
| 696 | # define AVIVO_LVDS_BACKLIGHT_LEVEL_MASK 0x0000ff00 | ||
| 697 | # define AVIVO_LVDS_BACKLIGHT_LEVEL_SHIFT 8 | ||
| 698 | |||
| 699 | #define AVIVO_DVOA_BIT_DEPTH_CONTROL 0x7988 | ||
| 700 | |||
| 701 | #define AVIVO_GPIO_0 0x7e30 | ||
| 702 | #define AVIVO_GPIO_1 0x7e40 | ||
| 703 | #define AVIVO_GPIO_2 0x7e50 | ||
| 704 | #define AVIVO_GPIO_3 0x7e60 | ||
| 705 | |||
| 706 | #define AVIVO_DC_GPIO_HPD_Y 0x7e9c | ||
| 707 | |||
| 708 | #define AVIVO_I2C_STATUS 0x7d30 | ||
| 709 | # define AVIVO_I2C_STATUS_DONE (1 << 0) | ||
| 710 | # define AVIVO_I2C_STATUS_NACK (1 << 1) | ||
| 711 | # define AVIVO_I2C_STATUS_HALT (1 << 2) | ||
| 712 | # define AVIVO_I2C_STATUS_GO (1 << 3) | ||
| 713 | # define AVIVO_I2C_STATUS_MASK 0x7 | ||
| 714 | /* If radeon_mm_i2c is to be believed, this is HALT, NACK, and maybe | ||
| 715 | * DONE? */ | ||
| 716 | # define AVIVO_I2C_STATUS_CMD_RESET 0x7 | ||
| 717 | # define AVIVO_I2C_STATUS_CMD_WAIT (1 << 3) | ||
| 718 | #define AVIVO_I2C_STOP 0x7d34 | ||
| 719 | #define AVIVO_I2C_START_CNTL 0x7d38 | ||
| 720 | # define AVIVO_I2C_START (1 << 8) | ||
| 721 | # define AVIVO_I2C_CONNECTOR0 (0 << 16) | ||
| 722 | # define AVIVO_I2C_CONNECTOR1 (1 << 16) | ||
| 723 | #define R520_I2C_START (1<<0) | ||
| 724 | #define R520_I2C_STOP (1<<1) | ||
| 725 | #define R520_I2C_RX (1<<2) | ||
| 726 | #define R520_I2C_EN (1<<8) | ||
| 727 | #define R520_I2C_DDC1 (0<<16) | ||
| 728 | #define R520_I2C_DDC2 (1<<16) | ||
| 729 | #define R520_I2C_DDC3 (2<<16) | ||
| 730 | #define R520_I2C_DDC_MASK (3<<16) | ||
| 731 | #define AVIVO_I2C_CONTROL2 0x7d3c | ||
| 732 | # define AVIVO_I2C_7D3C_SIZE_SHIFT 8 | ||
| 733 | # define AVIVO_I2C_7D3C_SIZE_MASK (0xf << 8) | ||
| 734 | #define AVIVO_I2C_CONTROL3 0x7d40 | ||
| 735 | /* Reading is done 4 bytes at a time: read the bottom 8 bits from | ||
| 736 | * 7d44, four times in a row. | ||
| 737 | * Writing is a little more complex. First write DATA with | ||
| 738 | * 0xnnnnnnzz, then 0xnnnnnnyy, where nnnnnn is some non-deterministic | ||
| 739 | * magic number, zz is, I think, the slave address, and yy is the byte | ||
| 740 | * you want to write. */ | ||
| 741 | #define AVIVO_I2C_DATA 0x7d44 | ||
| 742 | #define R520_I2C_ADDR_COUNT_MASK (0x7) | ||
| 743 | #define R520_I2C_DATA_COUNT_SHIFT (8) | ||
| 744 | #define R520_I2C_DATA_COUNT_MASK (0xF00) | ||
| 745 | #define AVIVO_I2C_CNTL 0x7d50 | ||
| 746 | # define AVIVO_I2C_EN (1 << 0) | ||
| 747 | # define AVIVO_I2C_RESET (1 << 8) | ||
| 748 | |||
| 749 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c new file mode 100644 index 000000000000..570a244bd88b --- /dev/null +++ b/drivers/gpu/drm/radeon/r520.c | |||
| @@ -0,0 +1,234 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include "drmP.h" | ||
| 29 | #include "radeon_reg.h" | ||
| 30 | #include "radeon.h" | ||
| 31 | |||
| 32 | /* r520,rv530,rv560,rv570,r580 depends on : */ | ||
| 33 | void r100_hdp_reset(struct radeon_device *rdev); | ||
| 34 | int rv370_pcie_gart_enable(struct radeon_device *rdev); | ||
| 35 | void rv370_pcie_gart_disable(struct radeon_device *rdev); | ||
| 36 | void r420_pipes_init(struct radeon_device *rdev); | ||
| 37 | void rs600_mc_disable_clients(struct radeon_device *rdev); | ||
| 38 | void rs600_disable_vga(struct radeon_device *rdev); | ||
| 39 | int rv515_debugfs_pipes_info_init(struct radeon_device *rdev); | ||
| 40 | int rv515_debugfs_ga_info_init(struct radeon_device *rdev); | ||
| 41 | |||
| 42 | /* This files gather functions specifics to: | ||
| 43 | * r520,rv530,rv560,rv570,r580 | ||
| 44 | * | ||
| 45 | * Some of these functions might be used by newer ASICs. | ||
| 46 | */ | ||
| 47 | void r520_gpu_init(struct radeon_device *rdev); | ||
| 48 | int r520_mc_wait_for_idle(struct radeon_device *rdev); | ||
| 49 | |||
| 50 | |||
| 51 | /* | ||
| 52 | * MC | ||
| 53 | */ | ||
| 54 | int r520_mc_init(struct radeon_device *rdev) | ||
| 55 | { | ||
| 56 | uint32_t tmp; | ||
| 57 | int r; | ||
| 58 | |||
| 59 | if (r100_debugfs_rbbm_init(rdev)) { | ||
| 60 | DRM_ERROR("Failed to register debugfs file for RBBM !\n"); | ||
| 61 | } | ||
| 62 | if (rv515_debugfs_pipes_info_init(rdev)) { | ||
| 63 | DRM_ERROR("Failed to register debugfs file for pipes !\n"); | ||
| 64 | } | ||
| 65 | if (rv515_debugfs_ga_info_init(rdev)) { | ||
| 66 | DRM_ERROR("Failed to register debugfs file for pipes !\n"); | ||
| 67 | } | ||
| 68 | |||
| 69 | r520_gpu_init(rdev); | ||
| 70 | rv370_pcie_gart_disable(rdev); | ||
| 71 | |||
| 72 | /* Setup GPU memory space */ | ||
| 73 | rdev->mc.vram_location = 0xFFFFFFFFUL; | ||
| 74 | rdev->mc.gtt_location = 0xFFFFFFFFUL; | ||
| 75 | if (rdev->flags & RADEON_IS_AGP) { | ||
| 76 | r = radeon_agp_init(rdev); | ||
| 77 | if (r) { | ||
| 78 | printk(KERN_WARNING "[drm] Disabling AGP\n"); | ||
| 79 | rdev->flags &= ~RADEON_IS_AGP; | ||
| 80 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; | ||
| 81 | } else { | ||
| 82 | rdev->mc.gtt_location = rdev->mc.agp_base; | ||
| 83 | } | ||
| 84 | } | ||
| 85 | r = radeon_mc_setup(rdev); | ||
| 86 | if (r) { | ||
| 87 | return r; | ||
| 88 | } | ||
| 89 | |||
| 90 | /* Program GPU memory space */ | ||
| 91 | rs600_mc_disable_clients(rdev); | ||
| 92 | if (r520_mc_wait_for_idle(rdev)) { | ||
| 93 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 94 | "programming pipes. Bad things might happen.\n"); | ||
| 95 | } | ||
| 96 | /* Write VRAM size in case we are limiting it */ | ||
| 97 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); | ||
| 98 | tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; | ||
| 99 | tmp = REG_SET(R520_MC_FB_TOP, tmp >> 16); | ||
| 100 | tmp |= REG_SET(R520_MC_FB_START, rdev->mc.vram_location >> 16); | ||
| 101 | WREG32_MC(R520_MC_FB_LOCATION, tmp); | ||
| 102 | WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16); | ||
| 103 | WREG32(0x310, rdev->mc.vram_location); | ||
| 104 | if (rdev->flags & RADEON_IS_AGP) { | ||
| 105 | tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; | ||
| 106 | tmp = REG_SET(R520_MC_AGP_TOP, tmp >> 16); | ||
| 107 | tmp |= REG_SET(R520_MC_AGP_START, rdev->mc.gtt_location >> 16); | ||
| 108 | WREG32_MC(R520_MC_AGP_LOCATION, tmp); | ||
| 109 | WREG32_MC(R520_MC_AGP_BASE, rdev->mc.agp_base); | ||
| 110 | WREG32_MC(R520_MC_AGP_BASE_2, 0); | ||
| 111 | } else { | ||
| 112 | WREG32_MC(R520_MC_AGP_LOCATION, 0x0FFFFFFF); | ||
| 113 | WREG32_MC(R520_MC_AGP_BASE, 0); | ||
| 114 | WREG32_MC(R520_MC_AGP_BASE_2, 0); | ||
| 115 | } | ||
| 116 | return 0; | ||
| 117 | } | ||
| 118 | |||
| 119 | void r520_mc_fini(struct radeon_device *rdev) | ||
| 120 | { | ||
| 121 | rv370_pcie_gart_disable(rdev); | ||
| 122 | radeon_gart_table_vram_free(rdev); | ||
| 123 | radeon_gart_fini(rdev); | ||
| 124 | } | ||
| 125 | |||
| 126 | |||
| 127 | /* | ||
| 128 | * Global GPU functions | ||
| 129 | */ | ||
| 130 | void r520_errata(struct radeon_device *rdev) | ||
| 131 | { | ||
| 132 | rdev->pll_errata = 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | int r520_mc_wait_for_idle(struct radeon_device *rdev) | ||
| 136 | { | ||
| 137 | unsigned i; | ||
| 138 | uint32_t tmp; | ||
| 139 | |||
| 140 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 141 | /* read MC_STATUS */ | ||
| 142 | tmp = RREG32_MC(R520_MC_STATUS); | ||
| 143 | if (tmp & R520_MC_STATUS_IDLE) { | ||
| 144 | return 0; | ||
| 145 | } | ||
| 146 | DRM_UDELAY(1); | ||
| 147 | } | ||
| 148 | return -1; | ||
| 149 | } | ||
| 150 | |||
| 151 | void r520_gpu_init(struct radeon_device *rdev) | ||
| 152 | { | ||
| 153 | unsigned pipe_select_current, gb_pipe_select, tmp; | ||
| 154 | |||
| 155 | r100_hdp_reset(rdev); | ||
| 156 | rs600_disable_vga(rdev); | ||
| 157 | /* | ||
| 158 | * DST_PIPE_CONFIG 0x170C | ||
| 159 | * GB_TILE_CONFIG 0x4018 | ||
| 160 | * GB_FIFO_SIZE 0x4024 | ||
| 161 | * GB_PIPE_SELECT 0x402C | ||
| 162 | * GB_PIPE_SELECT2 0x4124 | ||
| 163 | * Z_PIPE_SHIFT 0 | ||
| 164 | * Z_PIPE_MASK 0x000000003 | ||
| 165 | * GB_FIFO_SIZE2 0x4128 | ||
| 166 | * SC_SFIFO_SIZE_SHIFT 0 | ||
| 167 | * SC_SFIFO_SIZE_MASK 0x000000003 | ||
| 168 | * SC_MFIFO_SIZE_SHIFT 2 | ||
| 169 | * SC_MFIFO_SIZE_MASK 0x00000000C | ||
| 170 | * FG_SFIFO_SIZE_SHIFT 4 | ||
| 171 | * FG_SFIFO_SIZE_MASK 0x000000030 | ||
| 172 | * ZB_MFIFO_SIZE_SHIFT 6 | ||
| 173 | * ZB_MFIFO_SIZE_MASK 0x0000000C0 | ||
| 174 | * GA_ENHANCE 0x4274 | ||
| 175 | * SU_REG_DEST 0x42C8 | ||
| 176 | */ | ||
| 177 | /* workaround for RV530 */ | ||
| 178 | if (rdev->family == CHIP_RV530) { | ||
| 179 | WREG32(0x4124, 1); | ||
| 180 | WREG32(0x4128, 0xFF); | ||
| 181 | } | ||
| 182 | r420_pipes_init(rdev); | ||
| 183 | gb_pipe_select = RREG32(0x402C); | ||
| 184 | tmp = RREG32(0x170C); | ||
| 185 | pipe_select_current = (tmp >> 2) & 3; | ||
| 186 | tmp = (1 << pipe_select_current) | | ||
| 187 | (((gb_pipe_select >> 8) & 0xF) << 4); | ||
| 188 | WREG32_PLL(0x000D, tmp); | ||
| 189 | if (r520_mc_wait_for_idle(rdev)) { | ||
| 190 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 191 | "programming pipes. Bad things might happen.\n"); | ||
| 192 | } | ||
| 193 | } | ||
| 194 | |||
| 195 | |||
| 196 | /* | ||
| 197 | * VRAM info | ||
| 198 | */ | ||
| 199 | static void r520_vram_get_type(struct radeon_device *rdev) | ||
| 200 | { | ||
| 201 | uint32_t tmp; | ||
| 202 | |||
| 203 | rdev->mc.vram_width = 128; | ||
| 204 | rdev->mc.vram_is_ddr = true; | ||
| 205 | tmp = RREG32_MC(R520_MC_CNTL0); | ||
| 206 | switch ((tmp & R520_MEM_NUM_CHANNELS_MASK) >> R520_MEM_NUM_CHANNELS_SHIFT) { | ||
| 207 | case 0: | ||
| 208 | rdev->mc.vram_width = 32; | ||
| 209 | break; | ||
| 210 | case 1: | ||
| 211 | rdev->mc.vram_width = 64; | ||
| 212 | break; | ||
| 213 | case 2: | ||
| 214 | rdev->mc.vram_width = 128; | ||
| 215 | break; | ||
| 216 | case 3: | ||
| 217 | rdev->mc.vram_width = 256; | ||
| 218 | break; | ||
| 219 | default: | ||
| 220 | rdev->mc.vram_width = 128; | ||
| 221 | break; | ||
| 222 | } | ||
| 223 | if (tmp & R520_MC_CHANNEL_SIZE) | ||
| 224 | rdev->mc.vram_width *= 2; | ||
| 225 | } | ||
| 226 | |||
| 227 | void r520_vram_info(struct radeon_device *rdev) | ||
| 228 | { | ||
| 229 | r520_vram_get_type(rdev); | ||
| 230 | rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); | ||
| 231 | |||
| 232 | rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); | ||
| 233 | rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); | ||
| 234 | } | ||
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c new file mode 100644 index 000000000000..c45559fc97fd --- /dev/null +++ b/drivers/gpu/drm/radeon/r600.c | |||
| @@ -0,0 +1,169 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include "drmP.h" | ||
| 29 | #include "radeon_reg.h" | ||
| 30 | #include "radeon.h" | ||
| 31 | |||
| 32 | /* r600,rv610,rv630,rv620,rv635,rv670 depends on : */ | ||
| 33 | void rs600_mc_disable_clients(struct radeon_device *rdev); | ||
| 34 | |||
| 35 | /* This files gather functions specifics to: | ||
| 36 | * r600,rv610,rv630,rv620,rv635,rv670 | ||
| 37 | * | ||
| 38 | * Some of these functions might be used by newer ASICs. | ||
| 39 | */ | ||
| 40 | int r600_mc_wait_for_idle(struct radeon_device *rdev); | ||
| 41 | void r600_gpu_init(struct radeon_device *rdev); | ||
| 42 | |||
| 43 | |||
| 44 | /* | ||
| 45 | * MC | ||
| 46 | */ | ||
| 47 | int r600_mc_init(struct radeon_device *rdev) | ||
| 48 | { | ||
| 49 | uint32_t tmp; | ||
| 50 | |||
| 51 | r600_gpu_init(rdev); | ||
| 52 | |||
| 53 | /* setup the gart before changing location so we can ask to | ||
| 54 | * discard unmapped mc request | ||
| 55 | */ | ||
| 56 | /* FIXME: disable out of gart access */ | ||
| 57 | tmp = rdev->mc.gtt_location / 4096; | ||
| 58 | tmp = REG_SET(R600_LOGICAL_PAGE_NUMBER, tmp); | ||
| 59 | WREG32(R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR, tmp); | ||
| 60 | tmp = (rdev->mc.gtt_location + rdev->mc.gtt_size) / 4096; | ||
| 61 | tmp = REG_SET(R600_LOGICAL_PAGE_NUMBER, tmp); | ||
| 62 | WREG32(R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, tmp); | ||
| 63 | |||
| 64 | rs600_mc_disable_clients(rdev); | ||
| 65 | if (r600_mc_wait_for_idle(rdev)) { | ||
| 66 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 67 | "programming pipes. Bad things might happen.\n"); | ||
| 68 | } | ||
| 69 | |||
| 70 | tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; | ||
| 71 | tmp = REG_SET(R600_MC_FB_TOP, tmp >> 24); | ||
| 72 | tmp |= REG_SET(R600_MC_FB_BASE, rdev->mc.vram_location >> 24); | ||
| 73 | WREG32(R600_MC_VM_FB_LOCATION, tmp); | ||
| 74 | tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; | ||
| 75 | tmp = REG_SET(R600_MC_AGP_TOP, tmp >> 22); | ||
| 76 | WREG32(R600_MC_VM_AGP_TOP, tmp); | ||
| 77 | tmp = REG_SET(R600_MC_AGP_BOT, rdev->mc.gtt_location >> 22); | ||
| 78 | WREG32(R600_MC_VM_AGP_BOT, tmp); | ||
| 79 | return 0; | ||
| 80 | } | ||
| 81 | |||
| 82 | void r600_mc_fini(struct radeon_device *rdev) | ||
| 83 | { | ||
| 84 | /* FIXME: implement */ | ||
| 85 | } | ||
| 86 | |||
| 87 | |||
| 88 | /* | ||
| 89 | * Global GPU functions | ||
| 90 | */ | ||
| 91 | void r600_errata(struct radeon_device *rdev) | ||
| 92 | { | ||
| 93 | rdev->pll_errata = 0; | ||
| 94 | } | ||
| 95 | |||
| 96 | int r600_mc_wait_for_idle(struct radeon_device *rdev) | ||
| 97 | { | ||
| 98 | /* FIXME: implement */ | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | void r600_gpu_init(struct radeon_device *rdev) | ||
| 103 | { | ||
| 104 | /* FIXME: implement */ | ||
| 105 | } | ||
| 106 | |||
| 107 | |||
| 108 | /* | ||
| 109 | * VRAM info | ||
| 110 | */ | ||
| 111 | void r600_vram_get_type(struct radeon_device *rdev) | ||
| 112 | { | ||
| 113 | uint32_t tmp; | ||
| 114 | int chansize; | ||
| 115 | |||
| 116 | rdev->mc.vram_width = 128; | ||
| 117 | rdev->mc.vram_is_ddr = true; | ||
| 118 | |||
| 119 | tmp = RREG32(R600_RAMCFG); | ||
| 120 | if (tmp & R600_CHANSIZE_OVERRIDE) { | ||
| 121 | chansize = 16; | ||
| 122 | } else if (tmp & R600_CHANSIZE) { | ||
| 123 | chansize = 64; | ||
| 124 | } else { | ||
| 125 | chansize = 32; | ||
| 126 | } | ||
| 127 | if (rdev->family == CHIP_R600) { | ||
| 128 | rdev->mc.vram_width = 8 * chansize; | ||
| 129 | } else if (rdev->family == CHIP_RV670) { | ||
| 130 | rdev->mc.vram_width = 4 * chansize; | ||
| 131 | } else if ((rdev->family == CHIP_RV610) || | ||
| 132 | (rdev->family == CHIP_RV620)) { | ||
| 133 | rdev->mc.vram_width = chansize; | ||
| 134 | } else if ((rdev->family == CHIP_RV630) || | ||
| 135 | (rdev->family == CHIP_RV635)) { | ||
| 136 | rdev->mc.vram_width = 2 * chansize; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | |||
| 140 | void r600_vram_info(struct radeon_device *rdev) | ||
| 141 | { | ||
| 142 | r600_vram_get_type(rdev); | ||
| 143 | rdev->mc.vram_size = RREG32(R600_CONFIG_MEMSIZE); | ||
| 144 | |||
| 145 | /* Could aper size report 0 ? */ | ||
| 146 | rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); | ||
| 147 | rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); | ||
| 148 | } | ||
| 149 | |||
| 150 | /* | ||
| 151 | * Indirect registers accessor | ||
| 152 | */ | ||
| 153 | uint32_t r600_pciep_rreg(struct radeon_device *rdev, uint32_t reg) | ||
| 154 | { | ||
| 155 | uint32_t r; | ||
| 156 | |||
| 157 | WREG32(R600_PCIE_PORT_INDEX, ((reg) & 0xff)); | ||
| 158 | (void)RREG32(R600_PCIE_PORT_INDEX); | ||
| 159 | r = RREG32(R600_PCIE_PORT_DATA); | ||
| 160 | return r; | ||
| 161 | } | ||
| 162 | |||
| 163 | void r600_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | ||
| 164 | { | ||
| 165 | WREG32(R600_PCIE_PORT_INDEX, ((reg) & 0xff)); | ||
| 166 | (void)RREG32(R600_PCIE_PORT_INDEX); | ||
| 167 | WREG32(R600_PCIE_PORT_DATA, (v)); | ||
| 168 | (void)RREG32(R600_PCIE_PORT_DATA); | ||
| 169 | } | ||
diff --git a/drivers/gpu/drm/radeon/r600_reg.h b/drivers/gpu/drm/radeon/r600_reg.h new file mode 100644 index 000000000000..e2d1f5f33f7e --- /dev/null +++ b/drivers/gpu/drm/radeon/r600_reg.h | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #ifndef __R600_REG_H__ | ||
| 29 | #define __R600_REG_H__ | ||
| 30 | |||
| 31 | #define R600_PCIE_PORT_INDEX 0x0038 | ||
| 32 | #define R600_PCIE_PORT_DATA 0x003c | ||
| 33 | |||
| 34 | #define R600_MC_VM_FB_LOCATION 0x2180 | ||
| 35 | #define R600_MC_FB_BASE_MASK 0x0000FFFF | ||
| 36 | #define R600_MC_FB_BASE_SHIFT 0 | ||
| 37 | #define R600_MC_FB_TOP_MASK 0xFFFF0000 | ||
| 38 | #define R600_MC_FB_TOP_SHIFT 16 | ||
| 39 | #define R600_MC_VM_AGP_TOP 0x2184 | ||
| 40 | #define R600_MC_AGP_TOP_MASK 0x0003FFFF | ||
| 41 | #define R600_MC_AGP_TOP_SHIFT 0 | ||
| 42 | #define R600_MC_VM_AGP_BOT 0x2188 | ||
| 43 | #define R600_MC_AGP_BOT_MASK 0x0003FFFF | ||
| 44 | #define R600_MC_AGP_BOT_SHIFT 0 | ||
| 45 | #define R600_MC_VM_AGP_BASE 0x218c | ||
| 46 | #define R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2190 | ||
| 47 | #define R600_LOGICAL_PAGE_NUMBER_MASK 0x000FFFFF | ||
| 48 | #define R600_LOGICAL_PAGE_NUMBER_SHIFT 0 | ||
| 49 | #define R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2194 | ||
| 50 | #define R600_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x2198 | ||
| 51 | |||
| 52 | #define R700_MC_VM_FB_LOCATION 0x2024 | ||
| 53 | #define R700_MC_FB_BASE_MASK 0x0000FFFF | ||
| 54 | #define R700_MC_FB_BASE_SHIFT 0 | ||
| 55 | #define R700_MC_FB_TOP_MASK 0xFFFF0000 | ||
| 56 | #define R700_MC_FB_TOP_SHIFT 16 | ||
| 57 | #define R700_MC_VM_AGP_TOP 0x2028 | ||
| 58 | #define R700_MC_AGP_TOP_MASK 0x0003FFFF | ||
| 59 | #define R700_MC_AGP_TOP_SHIFT 0 | ||
| 60 | #define R700_MC_VM_AGP_BOT 0x202c | ||
| 61 | #define R700_MC_AGP_BOT_MASK 0x0003FFFF | ||
| 62 | #define R700_MC_AGP_BOT_SHIFT 0 | ||
| 63 | #define R700_MC_VM_AGP_BASE 0x2030 | ||
| 64 | #define R700_MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 | ||
| 65 | #define R700_LOGICAL_PAGE_NUMBER_MASK 0x000FFFFF | ||
| 66 | #define R700_LOGICAL_PAGE_NUMBER_SHIFT 0 | ||
| 67 | #define R700_MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 | ||
| 68 | #define R700_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203c | ||
| 69 | |||
| 70 | #define R600_RAMCFG 0x2408 | ||
| 71 | # define R600_CHANSIZE (1 << 7) | ||
| 72 | # define R600_CHANSIZE_OVERRIDE (1 << 10) | ||
| 73 | |||
| 74 | |||
| 75 | #define R600_GENERAL_PWRMGT 0x618 | ||
| 76 | # define R600_OPEN_DRAIN_PADS (1 << 11) | ||
| 77 | |||
| 78 | #define R600_LOWER_GPIO_ENABLE 0x710 | ||
| 79 | #define R600_CTXSW_VID_LOWER_GPIO_CNTL 0x718 | ||
| 80 | #define R600_HIGH_VID_LOWER_GPIO_CNTL 0x71c | ||
| 81 | #define R600_MEDIUM_VID_LOWER_GPIO_CNTL 0x720 | ||
| 82 | #define R600_LOW_VID_LOWER_GPIO_CNTL 0x724 | ||
| 83 | |||
| 84 | |||
| 85 | |||
| 86 | #define R600_HDP_NONSURFACE_BASE 0x2c04 | ||
| 87 | |||
| 88 | #define R600_BUS_CNTL 0x5420 | ||
| 89 | #define R600_CONFIG_CNTL 0x5424 | ||
| 90 | #define R600_CONFIG_MEMSIZE 0x5428 | ||
| 91 | #define R600_CONFIG_F0_BASE 0x542C | ||
| 92 | #define R600_CONFIG_APER_SIZE 0x5430 | ||
| 93 | |||
| 94 | #define R600_ROM_CNTL 0x1600 | ||
| 95 | # define R600_SCK_OVERWRITE (1 << 1) | ||
| 96 | # define R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT 28 | ||
| 97 | # define R600_SCK_PRESCALE_CRYSTAL_CLK_MASK (0xf << 28) | ||
| 98 | |||
| 99 | #define R600_CG_SPLL_FUNC_CNTL 0x600 | ||
| 100 | # define R600_SPLL_BYPASS_EN (1 << 3) | ||
| 101 | #define R600_CG_SPLL_STATUS 0x60c | ||
| 102 | # define R600_SPLL_CHG_STATUS (1 << 1) | ||
| 103 | |||
| 104 | #define R600_BIOS_0_SCRATCH 0x1724 | ||
| 105 | #define R600_BIOS_1_SCRATCH 0x1728 | ||
| 106 | #define R600_BIOS_2_SCRATCH 0x172c | ||
| 107 | #define R600_BIOS_3_SCRATCH 0x1730 | ||
| 108 | #define R600_BIOS_4_SCRATCH 0x1734 | ||
| 109 | #define R600_BIOS_5_SCRATCH 0x1738 | ||
| 110 | #define R600_BIOS_6_SCRATCH 0x173c | ||
| 111 | #define R600_BIOS_7_SCRATCH 0x1740 | ||
| 112 | |||
| 113 | |||
| 114 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h new file mode 100644 index 000000000000..c3f24cc56009 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -0,0 +1,793 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #ifndef __RADEON_H__ | ||
| 29 | #define __RADEON_H__ | ||
| 30 | |||
| 31 | #include "radeon_object.h" | ||
| 32 | |||
| 33 | /* TODO: Here are things that needs to be done : | ||
| 34 | * - surface allocator & initializer : (bit like scratch reg) should | ||
| 35 | * initialize HDP_ stuff on RS600, R600, R700 hw, well anythings | ||
| 36 | * related to surface | ||
| 37 | * - WB : write back stuff (do it bit like scratch reg things) | ||
| 38 | * - Vblank : look at Jesse's rework and what we should do | ||
| 39 | * - r600/r700: gart & cp | ||
| 40 | * - cs : clean cs ioctl use bitmap & things like that. | ||
| 41 | * - power management stuff | ||
| 42 | * - Barrier in gart code | ||
| 43 | * - Unmappabled vram ? | ||
| 44 | * - TESTING, TESTING, TESTING | ||
| 45 | */ | ||
| 46 | |||
| 47 | #include <asm/atomic.h> | ||
| 48 | #include <linux/wait.h> | ||
| 49 | #include <linux/list.h> | ||
| 50 | #include <linux/kref.h> | ||
| 51 | |||
| 52 | #include "radeon_mode.h" | ||
| 53 | #include "radeon_reg.h" | ||
| 54 | |||
| 55 | |||
| 56 | /* | ||
| 57 | * Modules parameters. | ||
| 58 | */ | ||
| 59 | extern int radeon_no_wb; | ||
| 60 | extern int radeon_modeset; | ||
| 61 | extern int radeon_dynclks; | ||
| 62 | extern int radeon_r4xx_atom; | ||
| 63 | extern int radeon_agpmode; | ||
| 64 | extern int radeon_vram_limit; | ||
| 65 | extern int radeon_gart_size; | ||
| 66 | extern int radeon_benchmarking; | ||
| 67 | extern int radeon_connector_table; | ||
| 68 | |||
| 69 | /* | ||
| 70 | * Copy from radeon_drv.h so we don't have to include both and have conflicting | ||
| 71 | * symbol; | ||
| 72 | */ | ||
| 73 | #define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ | ||
| 74 | #define RADEON_IB_POOL_SIZE 16 | ||
| 75 | #define RADEON_DEBUGFS_MAX_NUM_FILES 32 | ||
| 76 | #define RADEONFB_CONN_LIMIT 4 | ||
| 77 | |||
| 78 | enum radeon_family { | ||
| 79 | CHIP_R100, | ||
| 80 | CHIP_RV100, | ||
| 81 | CHIP_RS100, | ||
| 82 | CHIP_RV200, | ||
| 83 | CHIP_RS200, | ||
| 84 | CHIP_R200, | ||
| 85 | CHIP_RV250, | ||
| 86 | CHIP_RS300, | ||
| 87 | CHIP_RV280, | ||
| 88 | CHIP_R300, | ||
| 89 | CHIP_R350, | ||
| 90 | CHIP_RV350, | ||
| 91 | CHIP_RV380, | ||
| 92 | CHIP_R420, | ||
| 93 | CHIP_R423, | ||
| 94 | CHIP_RV410, | ||
| 95 | CHIP_RS400, | ||
| 96 | CHIP_RS480, | ||
| 97 | CHIP_RS600, | ||
| 98 | CHIP_RS690, | ||
| 99 | CHIP_RS740, | ||
| 100 | CHIP_RV515, | ||
| 101 | CHIP_R520, | ||
| 102 | CHIP_RV530, | ||
| 103 | CHIP_RV560, | ||
| 104 | CHIP_RV570, | ||
| 105 | CHIP_R580, | ||
| 106 | CHIP_R600, | ||
| 107 | CHIP_RV610, | ||
| 108 | CHIP_RV630, | ||
| 109 | CHIP_RV620, | ||
| 110 | CHIP_RV635, | ||
| 111 | CHIP_RV670, | ||
| 112 | CHIP_RS780, | ||
| 113 | CHIP_RV770, | ||
| 114 | CHIP_RV730, | ||
| 115 | CHIP_RV710, | ||
| 116 | CHIP_LAST, | ||
| 117 | }; | ||
| 118 | |||
| 119 | enum radeon_chip_flags { | ||
| 120 | RADEON_FAMILY_MASK = 0x0000ffffUL, | ||
| 121 | RADEON_FLAGS_MASK = 0xffff0000UL, | ||
| 122 | RADEON_IS_MOBILITY = 0x00010000UL, | ||
| 123 | RADEON_IS_IGP = 0x00020000UL, | ||
| 124 | RADEON_SINGLE_CRTC = 0x00040000UL, | ||
| 125 | RADEON_IS_AGP = 0x00080000UL, | ||
| 126 | RADEON_HAS_HIERZ = 0x00100000UL, | ||
| 127 | RADEON_IS_PCIE = 0x00200000UL, | ||
| 128 | RADEON_NEW_MEMMAP = 0x00400000UL, | ||
| 129 | RADEON_IS_PCI = 0x00800000UL, | ||
| 130 | RADEON_IS_IGPGART = 0x01000000UL, | ||
| 131 | }; | ||
| 132 | |||
| 133 | |||
| 134 | /* | ||
| 135 | * Errata workarounds. | ||
| 136 | */ | ||
| 137 | enum radeon_pll_errata { | ||
| 138 | CHIP_ERRATA_R300_CG = 0x00000001, | ||
| 139 | CHIP_ERRATA_PLL_DUMMYREADS = 0x00000002, | ||
| 140 | CHIP_ERRATA_PLL_DELAY = 0x00000004 | ||
| 141 | }; | ||
| 142 | |||
| 143 | |||
| 144 | struct radeon_device; | ||
| 145 | |||
| 146 | |||
| 147 | /* | ||
| 148 | * BIOS. | ||
| 149 | */ | ||
| 150 | bool radeon_get_bios(struct radeon_device *rdev); | ||
| 151 | |||
| 152 | /* | ||
| 153 | * Clocks | ||
| 154 | */ | ||
| 155 | |||
| 156 | struct radeon_clock { | ||
| 157 | struct radeon_pll p1pll; | ||
| 158 | struct radeon_pll p2pll; | ||
| 159 | struct radeon_pll spll; | ||
| 160 | struct radeon_pll mpll; | ||
| 161 | /* 10 Khz units */ | ||
| 162 | uint32_t default_mclk; | ||
| 163 | uint32_t default_sclk; | ||
| 164 | }; | ||
| 165 | |||
| 166 | /* | ||
| 167 | * Fences. | ||
| 168 | */ | ||
| 169 | struct radeon_fence_driver { | ||
| 170 | uint32_t scratch_reg; | ||
| 171 | atomic_t seq; | ||
| 172 | uint32_t last_seq; | ||
| 173 | unsigned long count_timeout; | ||
| 174 | wait_queue_head_t queue; | ||
| 175 | rwlock_t lock; | ||
| 176 | struct list_head created; | ||
| 177 | struct list_head emited; | ||
| 178 | struct list_head signaled; | ||
| 179 | }; | ||
| 180 | |||
| 181 | struct radeon_fence { | ||
| 182 | struct radeon_device *rdev; | ||
| 183 | struct kref kref; | ||
| 184 | struct list_head list; | ||
| 185 | /* protected by radeon_fence.lock */ | ||
| 186 | uint32_t seq; | ||
| 187 | unsigned long timeout; | ||
| 188 | bool emited; | ||
| 189 | bool signaled; | ||
| 190 | }; | ||
| 191 | |||
| 192 | int radeon_fence_driver_init(struct radeon_device *rdev); | ||
| 193 | void radeon_fence_driver_fini(struct radeon_device *rdev); | ||
| 194 | int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence); | ||
| 195 | int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence); | ||
| 196 | void radeon_fence_process(struct radeon_device *rdev); | ||
| 197 | bool radeon_fence_signaled(struct radeon_fence *fence); | ||
| 198 | int radeon_fence_wait(struct radeon_fence *fence, bool interruptible); | ||
| 199 | int radeon_fence_wait_next(struct radeon_device *rdev); | ||
| 200 | int radeon_fence_wait_last(struct radeon_device *rdev); | ||
| 201 | struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); | ||
| 202 | void radeon_fence_unref(struct radeon_fence **fence); | ||
| 203 | |||
| 204 | |||
| 205 | /* | ||
| 206 | * Radeon buffer. | ||
| 207 | */ | ||
| 208 | struct radeon_object; | ||
| 209 | |||
| 210 | struct radeon_object_list { | ||
| 211 | struct list_head list; | ||
| 212 | struct radeon_object *robj; | ||
| 213 | uint64_t gpu_offset; | ||
| 214 | unsigned rdomain; | ||
| 215 | unsigned wdomain; | ||
| 216 | }; | ||
| 217 | |||
| 218 | int radeon_object_init(struct radeon_device *rdev); | ||
| 219 | void radeon_object_fini(struct radeon_device *rdev); | ||
| 220 | int radeon_object_create(struct radeon_device *rdev, | ||
| 221 | struct drm_gem_object *gobj, | ||
| 222 | unsigned long size, | ||
| 223 | bool kernel, | ||
| 224 | uint32_t domain, | ||
| 225 | bool interruptible, | ||
| 226 | struct radeon_object **robj_ptr); | ||
| 227 | int radeon_object_kmap(struct radeon_object *robj, void **ptr); | ||
| 228 | void radeon_object_kunmap(struct radeon_object *robj); | ||
| 229 | void radeon_object_unref(struct radeon_object **robj); | ||
| 230 | int radeon_object_pin(struct radeon_object *robj, uint32_t domain, | ||
| 231 | uint64_t *gpu_addr); | ||
| 232 | void radeon_object_unpin(struct radeon_object *robj); | ||
| 233 | int radeon_object_wait(struct radeon_object *robj); | ||
| 234 | int radeon_object_evict_vram(struct radeon_device *rdev); | ||
| 235 | int radeon_object_mmap(struct radeon_object *robj, uint64_t *offset); | ||
| 236 | void radeon_object_force_delete(struct radeon_device *rdev); | ||
| 237 | void radeon_object_list_add_object(struct radeon_object_list *lobj, | ||
| 238 | struct list_head *head); | ||
| 239 | int radeon_object_list_validate(struct list_head *head, void *fence); | ||
| 240 | void radeon_object_list_unvalidate(struct list_head *head); | ||
| 241 | void radeon_object_list_clean(struct list_head *head); | ||
| 242 | int radeon_object_fbdev_mmap(struct radeon_object *robj, | ||
| 243 | struct vm_area_struct *vma); | ||
| 244 | unsigned long radeon_object_size(struct radeon_object *robj); | ||
| 245 | |||
| 246 | |||
| 247 | /* | ||
| 248 | * GEM objects. | ||
| 249 | */ | ||
| 250 | struct radeon_gem { | ||
| 251 | struct list_head objects; | ||
| 252 | }; | ||
| 253 | |||
| 254 | int radeon_gem_init(struct radeon_device *rdev); | ||
| 255 | void radeon_gem_fini(struct radeon_device *rdev); | ||
| 256 | int radeon_gem_object_create(struct radeon_device *rdev, int size, | ||
| 257 | int alignment, int initial_domain, | ||
| 258 | bool discardable, bool kernel, | ||
| 259 | bool interruptible, | ||
| 260 | struct drm_gem_object **obj); | ||
| 261 | int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain, | ||
| 262 | uint64_t *gpu_addr); | ||
| 263 | void radeon_gem_object_unpin(struct drm_gem_object *obj); | ||
| 264 | |||
| 265 | |||
| 266 | /* | ||
| 267 | * GART structures, functions & helpers | ||
| 268 | */ | ||
| 269 | struct radeon_mc; | ||
| 270 | |||
| 271 | struct radeon_gart_table_ram { | ||
| 272 | volatile uint32_t *ptr; | ||
| 273 | }; | ||
| 274 | |||
| 275 | struct radeon_gart_table_vram { | ||
| 276 | struct radeon_object *robj; | ||
| 277 | volatile uint32_t *ptr; | ||
| 278 | }; | ||
| 279 | |||
| 280 | union radeon_gart_table { | ||
| 281 | struct radeon_gart_table_ram ram; | ||
| 282 | struct radeon_gart_table_vram vram; | ||
| 283 | }; | ||
| 284 | |||
| 285 | struct radeon_gart { | ||
| 286 | dma_addr_t table_addr; | ||
| 287 | unsigned num_gpu_pages; | ||
| 288 | unsigned num_cpu_pages; | ||
| 289 | unsigned table_size; | ||
| 290 | union radeon_gart_table table; | ||
| 291 | struct page **pages; | ||
| 292 | dma_addr_t *pages_addr; | ||
| 293 | bool ready; | ||
| 294 | }; | ||
| 295 | |||
| 296 | int radeon_gart_table_ram_alloc(struct radeon_device *rdev); | ||
| 297 | void radeon_gart_table_ram_free(struct radeon_device *rdev); | ||
| 298 | int radeon_gart_table_vram_alloc(struct radeon_device *rdev); | ||
| 299 | void radeon_gart_table_vram_free(struct radeon_device *rdev); | ||
| 300 | int radeon_gart_init(struct radeon_device *rdev); | ||
| 301 | void radeon_gart_fini(struct radeon_device *rdev); | ||
| 302 | void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, | ||
| 303 | int pages); | ||
| 304 | int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, | ||
| 305 | int pages, struct page **pagelist); | ||
| 306 | |||
| 307 | |||
| 308 | /* | ||
| 309 | * GPU MC structures, functions & helpers | ||
| 310 | */ | ||
| 311 | struct radeon_mc { | ||
| 312 | resource_size_t aper_size; | ||
| 313 | resource_size_t aper_base; | ||
| 314 | resource_size_t agp_base; | ||
| 315 | unsigned gtt_location; | ||
| 316 | unsigned gtt_size; | ||
| 317 | unsigned vram_location; | ||
| 318 | unsigned vram_size; | ||
| 319 | unsigned vram_width; | ||
| 320 | int vram_mtrr; | ||
| 321 | bool vram_is_ddr; | ||
| 322 | }; | ||
| 323 | |||
| 324 | int radeon_mc_setup(struct radeon_device *rdev); | ||
| 325 | |||
| 326 | |||
| 327 | /* | ||
| 328 | * GPU scratch registers structures, functions & helpers | ||
| 329 | */ | ||
| 330 | struct radeon_scratch { | ||
| 331 | unsigned num_reg; | ||
| 332 | bool free[32]; | ||
| 333 | uint32_t reg[32]; | ||
| 334 | }; | ||
| 335 | |||
| 336 | int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg); | ||
| 337 | void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg); | ||
| 338 | |||
| 339 | |||
| 340 | /* | ||
| 341 | * IRQS. | ||
| 342 | */ | ||
| 343 | struct radeon_irq { | ||
| 344 | bool installed; | ||
| 345 | bool sw_int; | ||
| 346 | /* FIXME: use a define max crtc rather than hardcode it */ | ||
| 347 | bool crtc_vblank_int[2]; | ||
| 348 | }; | ||
| 349 | |||
| 350 | int radeon_irq_kms_init(struct radeon_device *rdev); | ||
| 351 | void radeon_irq_kms_fini(struct radeon_device *rdev); | ||
| 352 | |||
| 353 | |||
| 354 | /* | ||
| 355 | * CP & ring. | ||
| 356 | */ | ||
| 357 | struct radeon_ib { | ||
| 358 | struct list_head list; | ||
| 359 | unsigned long idx; | ||
| 360 | uint64_t gpu_addr; | ||
| 361 | struct radeon_fence *fence; | ||
| 362 | volatile uint32_t *ptr; | ||
| 363 | uint32_t length_dw; | ||
| 364 | }; | ||
| 365 | |||
| 366 | struct radeon_ib_pool { | ||
| 367 | struct mutex mutex; | ||
| 368 | struct radeon_object *robj; | ||
| 369 | struct list_head scheduled_ibs; | ||
| 370 | struct radeon_ib ibs[RADEON_IB_POOL_SIZE]; | ||
| 371 | bool ready; | ||
| 372 | DECLARE_BITMAP(alloc_bm, RADEON_IB_POOL_SIZE); | ||
| 373 | }; | ||
| 374 | |||
| 375 | struct radeon_cp { | ||
| 376 | struct radeon_object *ring_obj; | ||
| 377 | volatile uint32_t *ring; | ||
| 378 | unsigned rptr; | ||
| 379 | unsigned wptr; | ||
| 380 | unsigned wptr_old; | ||
| 381 | unsigned ring_size; | ||
| 382 | unsigned ring_free_dw; | ||
| 383 | int count_dw; | ||
| 384 | uint64_t gpu_addr; | ||
| 385 | uint32_t align_mask; | ||
| 386 | uint32_t ptr_mask; | ||
| 387 | struct mutex mutex; | ||
| 388 | bool ready; | ||
| 389 | }; | ||
| 390 | |||
| 391 | int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib); | ||
| 392 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib); | ||
| 393 | int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib); | ||
| 394 | int radeon_ib_pool_init(struct radeon_device *rdev); | ||
| 395 | void radeon_ib_pool_fini(struct radeon_device *rdev); | ||
| 396 | int radeon_ib_test(struct radeon_device *rdev); | ||
| 397 | /* Ring access between begin & end cannot sleep */ | ||
| 398 | void radeon_ring_free_size(struct radeon_device *rdev); | ||
| 399 | int radeon_ring_lock(struct radeon_device *rdev, unsigned ndw); | ||
| 400 | void radeon_ring_unlock_commit(struct radeon_device *rdev); | ||
| 401 | void radeon_ring_unlock_undo(struct radeon_device *rdev); | ||
| 402 | int radeon_ring_test(struct radeon_device *rdev); | ||
| 403 | int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size); | ||
| 404 | void radeon_ring_fini(struct radeon_device *rdev); | ||
| 405 | |||
| 406 | |||
| 407 | /* | ||
| 408 | * CS. | ||
| 409 | */ | ||
| 410 | struct radeon_cs_reloc { | ||
| 411 | struct drm_gem_object *gobj; | ||
| 412 | struct radeon_object *robj; | ||
| 413 | struct radeon_object_list lobj; | ||
| 414 | uint32_t handle; | ||
| 415 | uint32_t flags; | ||
| 416 | }; | ||
| 417 | |||
| 418 | struct radeon_cs_chunk { | ||
| 419 | uint32_t chunk_id; | ||
| 420 | uint32_t length_dw; | ||
| 421 | uint32_t *kdata; | ||
| 422 | }; | ||
| 423 | |||
| 424 | struct radeon_cs_parser { | ||
| 425 | struct radeon_device *rdev; | ||
| 426 | struct drm_file *filp; | ||
| 427 | /* chunks */ | ||
| 428 | unsigned nchunks; | ||
| 429 | struct radeon_cs_chunk *chunks; | ||
| 430 | uint64_t *chunks_array; | ||
| 431 | /* IB */ | ||
| 432 | unsigned idx; | ||
| 433 | /* relocations */ | ||
| 434 | unsigned nrelocs; | ||
| 435 | struct radeon_cs_reloc *relocs; | ||
| 436 | struct radeon_cs_reloc **relocs_ptr; | ||
| 437 | struct list_head validated; | ||
| 438 | /* indices of various chunks */ | ||
| 439 | int chunk_ib_idx; | ||
| 440 | int chunk_relocs_idx; | ||
| 441 | struct radeon_ib *ib; | ||
| 442 | void *track; | ||
| 443 | }; | ||
| 444 | |||
| 445 | struct radeon_cs_packet { | ||
| 446 | unsigned idx; | ||
| 447 | unsigned type; | ||
| 448 | unsigned reg; | ||
| 449 | unsigned opcode; | ||
| 450 | int count; | ||
| 451 | unsigned one_reg_wr; | ||
| 452 | }; | ||
| 453 | |||
| 454 | typedef int (*radeon_packet0_check_t)(struct radeon_cs_parser *p, | ||
| 455 | struct radeon_cs_packet *pkt, | ||
| 456 | unsigned idx, unsigned reg); | ||
| 457 | typedef int (*radeon_packet3_check_t)(struct radeon_cs_parser *p, | ||
| 458 | struct radeon_cs_packet *pkt); | ||
| 459 | |||
| 460 | |||
| 461 | /* | ||
| 462 | * AGP | ||
| 463 | */ | ||
| 464 | int radeon_agp_init(struct radeon_device *rdev); | ||
| 465 | void radeon_agp_fini(struct radeon_device *rdev); | ||
| 466 | |||
| 467 | |||
| 468 | /* | ||
| 469 | * Writeback | ||
| 470 | */ | ||
| 471 | struct radeon_wb { | ||
| 472 | struct radeon_object *wb_obj; | ||
| 473 | volatile uint32_t *wb; | ||
| 474 | uint64_t gpu_addr; | ||
| 475 | }; | ||
| 476 | |||
| 477 | |||
| 478 | /* | ||
| 479 | * Benchmarking | ||
| 480 | */ | ||
| 481 | void radeon_benchmark(struct radeon_device *rdev); | ||
| 482 | |||
| 483 | |||
| 484 | /* | ||
| 485 | * Debugfs | ||
| 486 | */ | ||
| 487 | int radeon_debugfs_add_files(struct radeon_device *rdev, | ||
| 488 | struct drm_info_list *files, | ||
| 489 | unsigned nfiles); | ||
| 490 | int radeon_debugfs_fence_init(struct radeon_device *rdev); | ||
| 491 | int r100_debugfs_rbbm_init(struct radeon_device *rdev); | ||
| 492 | int r100_debugfs_cp_init(struct radeon_device *rdev); | ||
| 493 | |||
| 494 | |||
| 495 | /* | ||
| 496 | * ASIC specific functions. | ||
| 497 | */ | ||
| 498 | struct radeon_asic { | ||
| 499 | void (*errata)(struct radeon_device *rdev); | ||
| 500 | void (*vram_info)(struct radeon_device *rdev); | ||
| 501 | int (*gpu_reset)(struct radeon_device *rdev); | ||
| 502 | int (*mc_init)(struct radeon_device *rdev); | ||
| 503 | void (*mc_fini)(struct radeon_device *rdev); | ||
| 504 | int (*wb_init)(struct radeon_device *rdev); | ||
| 505 | void (*wb_fini)(struct radeon_device *rdev); | ||
| 506 | int (*gart_enable)(struct radeon_device *rdev); | ||
| 507 | void (*gart_disable)(struct radeon_device *rdev); | ||
| 508 | void (*gart_tlb_flush)(struct radeon_device *rdev); | ||
| 509 | int (*gart_set_page)(struct radeon_device *rdev, int i, uint64_t addr); | ||
| 510 | int (*cp_init)(struct radeon_device *rdev, unsigned ring_size); | ||
| 511 | void (*cp_fini)(struct radeon_device *rdev); | ||
| 512 | void (*cp_disable)(struct radeon_device *rdev); | ||
| 513 | void (*ring_start)(struct radeon_device *rdev); | ||
| 514 | int (*irq_set)(struct radeon_device *rdev); | ||
| 515 | int (*irq_process)(struct radeon_device *rdev); | ||
| 516 | void (*fence_ring_emit)(struct radeon_device *rdev, struct radeon_fence *fence); | ||
| 517 | int (*cs_parse)(struct radeon_cs_parser *p); | ||
| 518 | int (*copy_blit)(struct radeon_device *rdev, | ||
| 519 | uint64_t src_offset, | ||
| 520 | uint64_t dst_offset, | ||
| 521 | unsigned num_pages, | ||
| 522 | struct radeon_fence *fence); | ||
| 523 | int (*copy_dma)(struct radeon_device *rdev, | ||
| 524 | uint64_t src_offset, | ||
| 525 | uint64_t dst_offset, | ||
| 526 | unsigned num_pages, | ||
| 527 | struct radeon_fence *fence); | ||
| 528 | int (*copy)(struct radeon_device *rdev, | ||
| 529 | uint64_t src_offset, | ||
| 530 | uint64_t dst_offset, | ||
| 531 | unsigned num_pages, | ||
| 532 | struct radeon_fence *fence); | ||
| 533 | void (*set_engine_clock)(struct radeon_device *rdev, uint32_t eng_clock); | ||
| 534 | void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock); | ||
| 535 | void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes); | ||
| 536 | void (*set_clock_gating)(struct radeon_device *rdev, int enable); | ||
| 537 | }; | ||
| 538 | |||
| 539 | |||
| 540 | /* | ||
| 541 | * IOCTL. | ||
| 542 | */ | ||
| 543 | int radeon_gem_info_ioctl(struct drm_device *dev, void *data, | ||
| 544 | struct drm_file *filp); | ||
| 545 | int radeon_gem_create_ioctl(struct drm_device *dev, void *data, | ||
| 546 | struct drm_file *filp); | ||
| 547 | int radeon_gem_pin_ioctl(struct drm_device *dev, void *data, | ||
| 548 | struct drm_file *file_priv); | ||
| 549 | int radeon_gem_unpin_ioctl(struct drm_device *dev, void *data, | ||
| 550 | struct drm_file *file_priv); | ||
| 551 | int radeon_gem_pwrite_ioctl(struct drm_device *dev, void *data, | ||
| 552 | struct drm_file *file_priv); | ||
| 553 | int radeon_gem_pread_ioctl(struct drm_device *dev, void *data, | ||
| 554 | struct drm_file *file_priv); | ||
| 555 | int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, | ||
| 556 | struct drm_file *filp); | ||
| 557 | int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, | ||
| 558 | struct drm_file *filp); | ||
| 559 | int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, | ||
| 560 | struct drm_file *filp); | ||
| 561 | int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, | ||
| 562 | struct drm_file *filp); | ||
| 563 | int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); | ||
| 564 | |||
| 565 | |||
| 566 | /* | ||
| 567 | * Core structure, functions and helpers. | ||
| 568 | */ | ||
| 569 | typedef uint32_t (*radeon_rreg_t)(struct radeon_device*, uint32_t); | ||
| 570 | typedef void (*radeon_wreg_t)(struct radeon_device*, uint32_t, uint32_t); | ||
| 571 | |||
| 572 | struct radeon_device { | ||
| 573 | struct drm_device *ddev; | ||
| 574 | struct pci_dev *pdev; | ||
| 575 | /* ASIC */ | ||
| 576 | enum radeon_family family; | ||
| 577 | unsigned long flags; | ||
| 578 | int usec_timeout; | ||
| 579 | enum radeon_pll_errata pll_errata; | ||
| 580 | int num_gb_pipes; | ||
| 581 | int disp_priority; | ||
| 582 | /* BIOS */ | ||
| 583 | uint8_t *bios; | ||
| 584 | bool is_atom_bios; | ||
| 585 | uint16_t bios_header_start; | ||
| 586 | struct radeon_object *stollen_vga_memory; | ||
| 587 | struct fb_info *fbdev_info; | ||
| 588 | struct radeon_object *fbdev_robj; | ||
| 589 | struct radeon_framebuffer *fbdev_rfb; | ||
| 590 | /* Register mmio */ | ||
| 591 | unsigned long rmmio_base; | ||
| 592 | unsigned long rmmio_size; | ||
| 593 | void *rmmio; | ||
| 594 | radeon_rreg_t mm_rreg; | ||
| 595 | radeon_wreg_t mm_wreg; | ||
| 596 | radeon_rreg_t mc_rreg; | ||
| 597 | radeon_wreg_t mc_wreg; | ||
| 598 | radeon_rreg_t pll_rreg; | ||
| 599 | radeon_wreg_t pll_wreg; | ||
| 600 | radeon_rreg_t pcie_rreg; | ||
| 601 | radeon_wreg_t pcie_wreg; | ||
| 602 | radeon_rreg_t pciep_rreg; | ||
| 603 | radeon_wreg_t pciep_wreg; | ||
| 604 | struct radeon_clock clock; | ||
| 605 | struct radeon_mc mc; | ||
| 606 | struct radeon_gart gart; | ||
| 607 | struct radeon_mode_info mode_info; | ||
| 608 | struct radeon_scratch scratch; | ||
| 609 | struct radeon_mman mman; | ||
| 610 | struct radeon_fence_driver fence_drv; | ||
| 611 | struct radeon_cp cp; | ||
| 612 | struct radeon_ib_pool ib_pool; | ||
| 613 | struct radeon_irq irq; | ||
| 614 | struct radeon_asic *asic; | ||
| 615 | struct radeon_gem gem; | ||
| 616 | struct mutex cs_mutex; | ||
| 617 | struct radeon_wb wb; | ||
| 618 | bool gpu_lockup; | ||
| 619 | bool shutdown; | ||
| 620 | bool suspend; | ||
| 621 | }; | ||
| 622 | |||
| 623 | int radeon_device_init(struct radeon_device *rdev, | ||
| 624 | struct drm_device *ddev, | ||
| 625 | struct pci_dev *pdev, | ||
| 626 | uint32_t flags); | ||
| 627 | void radeon_device_fini(struct radeon_device *rdev); | ||
| 628 | int radeon_gpu_wait_for_idle(struct radeon_device *rdev); | ||
| 629 | |||
| 630 | |||
| 631 | /* | ||
| 632 | * Registers read & write functions. | ||
| 633 | */ | ||
| 634 | #define RREG8(reg) readb(((void __iomem *)rdev->rmmio) + (reg)) | ||
| 635 | #define WREG8(reg, v) writeb(v, ((void __iomem *)rdev->rmmio) + (reg)) | ||
| 636 | #define RREG32(reg) rdev->mm_rreg(rdev, (reg)) | ||
| 637 | #define WREG32(reg, v) rdev->mm_wreg(rdev, (reg), (v)) | ||
| 638 | #define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) | ||
| 639 | #define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) | ||
| 640 | #define RREG32_PLL(reg) rdev->pll_rreg(rdev, (reg)) | ||
| 641 | #define WREG32_PLL(reg, v) rdev->pll_wreg(rdev, (reg), (v)) | ||
| 642 | #define RREG32_MC(reg) rdev->mc_rreg(rdev, (reg)) | ||
| 643 | #define WREG32_MC(reg, v) rdev->mc_wreg(rdev, (reg), (v)) | ||
| 644 | #define RREG32_PCIE(reg) rdev->pcie_rreg(rdev, (reg)) | ||
| 645 | #define WREG32_PCIE(reg, v) rdev->pcie_wreg(rdev, (reg), (v)) | ||
| 646 | #define WREG32_P(reg, val, mask) \ | ||
| 647 | do { \ | ||
| 648 | uint32_t tmp_ = RREG32(reg); \ | ||
| 649 | tmp_ &= (mask); \ | ||
| 650 | tmp_ |= ((val) & ~(mask)); \ | ||
| 651 | WREG32(reg, tmp_); \ | ||
| 652 | } while (0) | ||
| 653 | #define WREG32_PLL_P(reg, val, mask) \ | ||
| 654 | do { \ | ||
| 655 | uint32_t tmp_ = RREG32_PLL(reg); \ | ||
| 656 | tmp_ &= (mask); \ | ||
| 657 | tmp_ |= ((val) & ~(mask)); \ | ||
| 658 | WREG32_PLL(reg, tmp_); \ | ||
| 659 | } while (0) | ||
| 660 | |||
| 661 | void r100_pll_errata_after_index(struct radeon_device *rdev); | ||
| 662 | |||
| 663 | |||
| 664 | /* | ||
| 665 | * ASICs helpers. | ||
| 666 | */ | ||
| 667 | #define ASIC_IS_RV100(rdev) ((rdev->family == CHIP_RV100) || \ | ||
| 668 | (rdev->family == CHIP_RV200) || \ | ||
| 669 | (rdev->family == CHIP_RS100) || \ | ||
| 670 | (rdev->family == CHIP_RS200) || \ | ||
| 671 | (rdev->family == CHIP_RV250) || \ | ||
| 672 | (rdev->family == CHIP_RV280) || \ | ||
| 673 | (rdev->family == CHIP_RS300)) | ||
| 674 | #define ASIC_IS_R300(rdev) ((rdev->family == CHIP_R300) || \ | ||
| 675 | (rdev->family == CHIP_RV350) || \ | ||
| 676 | (rdev->family == CHIP_R350) || \ | ||
| 677 | (rdev->family == CHIP_RV380) || \ | ||
| 678 | (rdev->family == CHIP_R420) || \ | ||
| 679 | (rdev->family == CHIP_R423) || \ | ||
| 680 | (rdev->family == CHIP_RV410) || \ | ||
| 681 | (rdev->family == CHIP_RS400) || \ | ||
| 682 | (rdev->family == CHIP_RS480)) | ||
| 683 | #define ASIC_IS_AVIVO(rdev) ((rdev->family >= CHIP_RS600)) | ||
| 684 | #define ASIC_IS_DCE3(rdev) ((rdev->family >= CHIP_RV620)) | ||
| 685 | #define ASIC_IS_DCE32(rdev) ((rdev->family >= CHIP_RV730)) | ||
| 686 | |||
| 687 | |||
| 688 | /* | ||
| 689 | * BIOS helpers. | ||
| 690 | */ | ||
| 691 | #define RBIOS8(i) (rdev->bios[i]) | ||
| 692 | #define RBIOS16(i) (RBIOS8(i) | (RBIOS8((i)+1) << 8)) | ||
| 693 | #define RBIOS32(i) ((RBIOS16(i)) | (RBIOS16((i)+2) << 16)) | ||
| 694 | |||
| 695 | int radeon_combios_init(struct radeon_device *rdev); | ||
| 696 | void radeon_combios_fini(struct radeon_device *rdev); | ||
| 697 | int radeon_atombios_init(struct radeon_device *rdev); | ||
| 698 | void radeon_atombios_fini(struct radeon_device *rdev); | ||
| 699 | |||
| 700 | |||
| 701 | /* | ||
| 702 | * RING helpers. | ||
| 703 | */ | ||
| 704 | #define CP_PACKET0 0x00000000 | ||
| 705 | #define PACKET0_BASE_INDEX_SHIFT 0 | ||
| 706 | #define PACKET0_BASE_INDEX_MASK (0x1ffff << 0) | ||
| 707 | #define PACKET0_COUNT_SHIFT 16 | ||
| 708 | #define PACKET0_COUNT_MASK (0x3fff << 16) | ||
| 709 | #define CP_PACKET1 0x40000000 | ||
| 710 | #define CP_PACKET2 0x80000000 | ||
| 711 | #define PACKET2_PAD_SHIFT 0 | ||
| 712 | #define PACKET2_PAD_MASK (0x3fffffff << 0) | ||
| 713 | #define CP_PACKET3 0xC0000000 | ||
| 714 | #define PACKET3_IT_OPCODE_SHIFT 8 | ||
| 715 | #define PACKET3_IT_OPCODE_MASK (0xff << 8) | ||
| 716 | #define PACKET3_COUNT_SHIFT 16 | ||
| 717 | #define PACKET3_COUNT_MASK (0x3fff << 16) | ||
| 718 | /* PACKET3 op code */ | ||
| 719 | #define PACKET3_NOP 0x10 | ||
| 720 | #define PACKET3_3D_DRAW_VBUF 0x28 | ||
| 721 | #define PACKET3_3D_DRAW_IMMD 0x29 | ||
| 722 | #define PACKET3_3D_DRAW_INDX 0x2A | ||
| 723 | #define PACKET3_3D_LOAD_VBPNTR 0x2F | ||
| 724 | #define PACKET3_INDX_BUFFER 0x33 | ||
| 725 | #define PACKET3_3D_DRAW_VBUF_2 0x34 | ||
| 726 | #define PACKET3_3D_DRAW_IMMD_2 0x35 | ||
| 727 | #define PACKET3_3D_DRAW_INDX_2 0x36 | ||
| 728 | #define PACKET3_BITBLT_MULTI 0x9B | ||
| 729 | |||
| 730 | #define PACKET0(reg, n) (CP_PACKET0 | \ | ||
| 731 | REG_SET(PACKET0_BASE_INDEX, (reg) >> 2) | \ | ||
| 732 | REG_SET(PACKET0_COUNT, (n))) | ||
| 733 | #define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v))) | ||
| 734 | #define PACKET3(op, n) (CP_PACKET3 | \ | ||
| 735 | REG_SET(PACKET3_IT_OPCODE, (op)) | \ | ||
| 736 | REG_SET(PACKET3_COUNT, (n))) | ||
| 737 | |||
| 738 | #define PACKET_TYPE0 0 | ||
| 739 | #define PACKET_TYPE1 1 | ||
| 740 | #define PACKET_TYPE2 2 | ||
| 741 | #define PACKET_TYPE3 3 | ||
| 742 | |||
| 743 | #define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) | ||
| 744 | #define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) | ||
| 745 | #define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2) | ||
| 746 | #define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1) | ||
| 747 | #define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) | ||
| 748 | |||
| 749 | static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) | ||
| 750 | { | ||
| 751 | #if DRM_DEBUG_CODE | ||
| 752 | if (rdev->cp.count_dw <= 0) { | ||
| 753 | DRM_ERROR("radeon: writting more dword to ring than expected !\n"); | ||
| 754 | } | ||
| 755 | #endif | ||
| 756 | rdev->cp.ring[rdev->cp.wptr++] = v; | ||
| 757 | rdev->cp.wptr &= rdev->cp.ptr_mask; | ||
| 758 | rdev->cp.count_dw--; | ||
| 759 | rdev->cp.ring_free_dw--; | ||
| 760 | } | ||
| 761 | |||
| 762 | |||
| 763 | /* | ||
| 764 | * ASICs macro. | ||
| 765 | */ | ||
| 766 | #define radeon_cs_parse(p) rdev->asic->cs_parse((p)) | ||
| 767 | #define radeon_errata(rdev) (rdev)->asic->errata((rdev)) | ||
| 768 | #define radeon_vram_info(rdev) (rdev)->asic->vram_info((rdev)) | ||
| 769 | #define radeon_gpu_reset(rdev) (rdev)->asic->gpu_reset((rdev)) | ||
| 770 | #define radeon_mc_init(rdev) (rdev)->asic->mc_init((rdev)) | ||
| 771 | #define radeon_mc_fini(rdev) (rdev)->asic->mc_fini((rdev)) | ||
| 772 | #define radeon_wb_init(rdev) (rdev)->asic->wb_init((rdev)) | ||
| 773 | #define radeon_wb_fini(rdev) (rdev)->asic->wb_fini((rdev)) | ||
| 774 | #define radeon_gart_enable(rdev) (rdev)->asic->gart_enable((rdev)) | ||
| 775 | #define radeon_gart_disable(rdev) (rdev)->asic->gart_disable((rdev)) | ||
| 776 | #define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart_tlb_flush((rdev)) | ||
| 777 | #define radeon_gart_set_page(rdev, i, p) (rdev)->asic->gart_set_page((rdev), (i), (p)) | ||
| 778 | #define radeon_cp_init(rdev,rsize) (rdev)->asic->cp_init((rdev), (rsize)) | ||
| 779 | #define radeon_cp_fini(rdev) (rdev)->asic->cp_fini((rdev)) | ||
| 780 | #define radeon_cp_disable(rdev) (rdev)->asic->cp_disable((rdev)) | ||
| 781 | #define radeon_ring_start(rdev) (rdev)->asic->ring_start((rdev)) | ||
| 782 | #define radeon_irq_set(rdev) (rdev)->asic->irq_set((rdev)) | ||
| 783 | #define radeon_irq_process(rdev) (rdev)->asic->irq_process((rdev)) | ||
| 784 | #define radeon_fence_ring_emit(rdev, fence) (rdev)->asic->fence_ring_emit((rdev), (fence)) | ||
| 785 | #define radeon_copy_blit(rdev, s, d, np, f) (rdev)->asic->copy_blit((rdev), (s), (d), (np), (f)) | ||
| 786 | #define radeon_copy_dma(rdev, s, d, np, f) (rdev)->asic->copy_dma((rdev), (s), (d), (np), (f)) | ||
| 787 | #define radeon_copy(rdev, s, d, np, f) (rdev)->asic->copy((rdev), (s), (d), (np), (f)) | ||
| 788 | #define radeon_set_engine_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e)) | ||
| 789 | #define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e)) | ||
| 790 | #define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l)) | ||
| 791 | #define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e)) | ||
| 792 | |||
| 793 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c new file mode 100644 index 000000000000..23ea9955ac59 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_agp.c | |||
| @@ -0,0 +1,249 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Red Hat Inc. | ||
| 3 | * Copyright 2009 Jerome Glisse. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * copy of this software and associated documentation files (the "Software"), | ||
| 7 | * to deal in the Software without restriction, including without limitation | ||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 10 | * Software is furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 21 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Dave Airlie | ||
| 25 | * Jerome Glisse <glisse@freedesktop.org> | ||
| 26 | */ | ||
| 27 | #include "drmP.h" | ||
| 28 | #include "drm.h" | ||
| 29 | #include "radeon.h" | ||
| 30 | #include "radeon_drm.h" | ||
| 31 | |||
| 32 | #if __OS_HAS_AGP | ||
| 33 | |||
| 34 | struct radeon_agpmode_quirk { | ||
| 35 | u32 hostbridge_vendor; | ||
| 36 | u32 hostbridge_device; | ||
| 37 | u32 chip_vendor; | ||
| 38 | u32 chip_device; | ||
| 39 | u32 subsys_vendor; | ||
| 40 | u32 subsys_device; | ||
| 41 | u32 default_mode; | ||
| 42 | }; | ||
| 43 | |||
| 44 | static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = { | ||
| 45 | /* Intel E7505 Memory Controller Hub / RV350 AR [Radeon 9600XT] Needs AGPMode 4 (deb #515326) */ | ||
| 46 | { PCI_VENDOR_ID_INTEL, 0x2550, PCI_VENDOR_ID_ATI, 0x4152, 0x1458, 0x4038, 4}, | ||
| 47 | /* Intel 82865G/PE/P DRAM Controller/Host-Hub / Mobility 9800 Needs AGPMode 4 (deb #462590) */ | ||
| 48 | { PCI_VENDOR_ID_INTEL, 0x2570, PCI_VENDOR_ID_ATI, 0x4a4e, PCI_VENDOR_ID_DELL, 0x5106, 4}, | ||
| 49 | /* Intel 82865G/PE/P DRAM Controller/Host-Hub / RV280 [Radeon 9200 SE] Needs AGPMode 4 (lp #300304) */ | ||
| 50 | { PCI_VENDOR_ID_INTEL, 0x2570, PCI_VENDOR_ID_ATI, 0x5964, | ||
| 51 | 0x148c, 0x2073, 4}, | ||
| 52 | /* Intel 82855PM Processor to I/O Controller / Mobility M6 LY Needs AGPMode 1 (deb #467235) */ | ||
| 53 | { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c59, | ||
| 54 | PCI_VENDOR_ID_IBM, 0x052f, 1}, | ||
| 55 | /* Intel 82855PM host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (lp #195051) */ | ||
| 56 | { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4e50, | ||
| 57 | PCI_VENDOR_ID_IBM, 0x0550, 1}, | ||
| 58 | /* Intel 82855PM host bridge / Mobility M7 needs AGPMode 1 */ | ||
| 59 | { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c57, | ||
| 60 | PCI_VENDOR_ID_IBM, 0x0530, 1}, | ||
| 61 | /* Intel 82855PM host bridge / FireGL Mobility T2 RV350 Needs AGPMode 2 (fdo #20647) */ | ||
| 62 | { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4e54, | ||
| 63 | PCI_VENDOR_ID_IBM, 0x054f, 2}, | ||
| 64 | /* Intel 82855PM host bridge / Mobility M9+ / VaioPCG-V505DX Needs AGPMode 2 (fdo #17928) */ | ||
| 65 | { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x5c61, | ||
| 66 | PCI_VENDOR_ID_SONY, 0x816b, 2}, | ||
| 67 | /* Intel 82855PM Processor to I/O Controller / Mobility M9+ Needs AGPMode 8 (phoronix forum) */ | ||
| 68 | { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x5c61, | ||
| 69 | PCI_VENDOR_ID_SONY, 0x8195, 8}, | ||
| 70 | /* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/ | ||
| 71 | { PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59, | ||
| 72 | PCI_VENDOR_ID_DELL, 0x00e3, 2}, | ||
| 73 | /* Intel 82852/82855 host bridge / Mobility FireGL 9000 R250 Needs AGPMode 1 (lp #296617) */ | ||
| 74 | { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66, | ||
| 75 | PCI_VENDOR_ID_DELL, 0x0149, 1}, | ||
| 76 | /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */ | ||
| 77 | { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, | ||
| 78 | 0x1025, 0x0061, 1}, | ||
| 79 | /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (lp #203007) */ | ||
| 80 | { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, | ||
| 81 | 0x1025, 0x0064, 1}, | ||
| 82 | /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (lp #141551) */ | ||
| 83 | { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, | ||
| 84 | PCI_VENDOR_ID_ASUSTEK, 0x1942, 1}, | ||
| 85 | /* Intel 82852/82855 host bridge / Mobility 9600/9700 Needs AGPMode 1 (deb #510208) */ | ||
| 86 | { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, | ||
| 87 | 0x10cf, 0x127f, 1}, | ||
| 88 | /* ASRock K7VT4A+ AGP 8x / ATI Radeon 9250 AGP Needs AGPMode 4 (lp #133192) */ | ||
| 89 | { 0x1849, 0x3189, PCI_VENDOR_ID_ATI, 0x5960, | ||
| 90 | 0x1787, 0x5960, 4}, | ||
| 91 | /* VIA K8M800 Host Bridge / RV280 [Radeon 9200 PRO] Needs AGPMode 4 (fdo #12544) */ | ||
| 92 | { PCI_VENDOR_ID_VIA, 0x0204, PCI_VENDOR_ID_ATI, 0x5960, | ||
| 93 | 0x17af, 0x2020, 4}, | ||
| 94 | /* VIA KT880 Host Bridge / RV350 [Radeon 9550] Needs AGPMode 4 (fdo #19981) */ | ||
| 95 | { PCI_VENDOR_ID_VIA, 0x0269, PCI_VENDOR_ID_ATI, 0x4153, | ||
| 96 | PCI_VENDOR_ID_ASUSTEK, 0x003c, 4}, | ||
| 97 | /* VIA VT8363 Host Bridge / R200 QL [Radeon 8500] Needs AGPMode 2 (lp #141551) */ | ||
| 98 | { PCI_VENDOR_ID_VIA, 0x0305, PCI_VENDOR_ID_ATI, 0x514c, | ||
| 99 | PCI_VENDOR_ID_ATI, 0x013a, 2}, | ||
| 100 | /* VIA VT82C693A Host Bridge / RV280 [Radeon 9200 PRO] Needs AGPMode 2 (deb #515512) */ | ||
| 101 | { PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_ATI, 0x5960, | ||
| 102 | PCI_VENDOR_ID_ASUSTEK, 0x004c, 2}, | ||
| 103 | /* VIA VT82C693A Host Bridge / RV280 [Radeon 9200 PRO] Needs AGPMode 2 */ | ||
| 104 | { PCI_VENDOR_ID_VIA, 0x0691, PCI_VENDOR_ID_ATI, 0x5960, | ||
| 105 | PCI_VENDOR_ID_ASUSTEK, 0x0054, 2}, | ||
| 106 | /* VIA VT8377 Host Bridge / R200 QM [Radeon 9100] Needs AGPMode 4 (deb #461144) */ | ||
| 107 | { PCI_VENDOR_ID_VIA, 0x3189, PCI_VENDOR_ID_ATI, 0x514d, | ||
| 108 | 0x174b, 0x7149, 4}, | ||
| 109 | /* VIA VT8377 Host Bridge / RV280 [Radeon 9200 PRO] Needs AGPMode 4 (lp #312693) */ | ||
| 110 | { PCI_VENDOR_ID_VIA, 0x3189, PCI_VENDOR_ID_ATI, 0x5960, | ||
| 111 | 0x1462, 0x0380, 4}, | ||
| 112 | /* VIA VT8377 Host Bridge / RV280 Needs AGPMode 4 (ati ML) */ | ||
| 113 | { PCI_VENDOR_ID_VIA, 0x3189, PCI_VENDOR_ID_ATI, 0x5964, | ||
| 114 | 0x148c, 0x2073, 4}, | ||
| 115 | /* ATI Host Bridge / RV280 [M9+] Needs AGPMode 1 (phoronix forum) */ | ||
| 116 | { PCI_VENDOR_ID_ATI, 0xcbb2, PCI_VENDOR_ID_ATI, 0x5c61, | ||
| 117 | PCI_VENDOR_ID_SONY, 0x8175, 1}, | ||
| 118 | /* HP Host Bridge / R300 [FireGL X1] Needs AGPMode 2 (fdo #7770) */ | ||
| 119 | { PCI_VENDOR_ID_HP, 0x122e, PCI_VENDOR_ID_ATI, 0x4e47, | ||
| 120 | PCI_VENDOR_ID_ATI, 0x0152, 2}, | ||
| 121 | { 0, 0, 0, 0, 0, 0, 0 }, | ||
| 122 | }; | ||
| 123 | #endif | ||
| 124 | |||
| 125 | int radeon_agp_init(struct radeon_device *rdev) | ||
| 126 | { | ||
| 127 | #if __OS_HAS_AGP | ||
| 128 | struct radeon_agpmode_quirk *p = radeon_agpmode_quirk_list; | ||
| 129 | struct drm_agp_mode mode; | ||
| 130 | struct drm_agp_info info; | ||
| 131 | uint32_t agp_status; | ||
| 132 | int default_mode; | ||
| 133 | bool is_v3; | ||
| 134 | int ret; | ||
| 135 | |||
| 136 | /* Acquire AGP. */ | ||
| 137 | if (!rdev->ddev->agp->acquired) { | ||
| 138 | ret = drm_agp_acquire(rdev->ddev); | ||
| 139 | if (ret) { | ||
| 140 | DRM_ERROR("Unable to acquire AGP: %d\n", ret); | ||
| 141 | return ret; | ||
| 142 | } | ||
| 143 | } | ||
| 144 | |||
| 145 | ret = drm_agp_info(rdev->ddev, &info); | ||
| 146 | if (ret) { | ||
| 147 | DRM_ERROR("Unable to get AGP info: %d\n", ret); | ||
| 148 | return ret; | ||
| 149 | } | ||
| 150 | mode.mode = info.mode; | ||
| 151 | agp_status = (RREG32(RADEON_AGP_STATUS) | RADEON_AGPv3_MODE) & mode.mode; | ||
| 152 | is_v3 = !!(agp_status & RADEON_AGPv3_MODE); | ||
| 153 | |||
| 154 | if (is_v3) { | ||
| 155 | default_mode = (agp_status & RADEON_AGPv3_8X_MODE) ? 8 : 4; | ||
| 156 | } else { | ||
| 157 | if (agp_status & RADEON_AGP_4X_MODE) { | ||
| 158 | default_mode = 4; | ||
| 159 | } else if (agp_status & RADEON_AGP_2X_MODE) { | ||
| 160 | default_mode = 2; | ||
| 161 | } else { | ||
| 162 | default_mode = 1; | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | /* Apply AGPMode Quirks */ | ||
| 167 | while (p && p->chip_device != 0) { | ||
| 168 | if (info.id_vendor == p->hostbridge_vendor && | ||
| 169 | info.id_device == p->hostbridge_device && | ||
| 170 | rdev->pdev->vendor == p->chip_vendor && | ||
| 171 | rdev->pdev->device == p->chip_device && | ||
| 172 | rdev->pdev->subsystem_vendor == p->subsys_vendor && | ||
| 173 | rdev->pdev->subsystem_device == p->subsys_device) { | ||
| 174 | default_mode = p->default_mode; | ||
| 175 | } | ||
| 176 | ++p; | ||
| 177 | } | ||
| 178 | |||
| 179 | if (radeon_agpmode > 0) { | ||
| 180 | if ((radeon_agpmode < (is_v3 ? 4 : 1)) || | ||
| 181 | (radeon_agpmode > (is_v3 ? 8 : 4)) || | ||
| 182 | (radeon_agpmode & (radeon_agpmode - 1))) { | ||
| 183 | DRM_ERROR("Illegal AGP Mode: %d (valid %s), leaving at %d\n", | ||
| 184 | radeon_agpmode, is_v3 ? "4, 8" : "1, 2, 4", | ||
| 185 | default_mode); | ||
| 186 | radeon_agpmode = default_mode; | ||
| 187 | } else { | ||
| 188 | DRM_INFO("AGP mode requested: %d\n", radeon_agpmode); | ||
| 189 | } | ||
| 190 | } else { | ||
| 191 | radeon_agpmode = default_mode; | ||
| 192 | } | ||
| 193 | |||
| 194 | mode.mode &= ~RADEON_AGP_MODE_MASK; | ||
| 195 | if (is_v3) { | ||
| 196 | switch (radeon_agpmode) { | ||
| 197 | case 8: | ||
| 198 | mode.mode |= RADEON_AGPv3_8X_MODE; | ||
| 199 | break; | ||
| 200 | case 4: | ||
| 201 | default: | ||
| 202 | mode.mode |= RADEON_AGPv3_4X_MODE; | ||
| 203 | break; | ||
| 204 | } | ||
| 205 | } else { | ||
| 206 | switch (radeon_agpmode) { | ||
| 207 | case 4: | ||
| 208 | mode.mode |= RADEON_AGP_4X_MODE; | ||
| 209 | break; | ||
| 210 | case 2: | ||
| 211 | mode.mode |= RADEON_AGP_2X_MODE; | ||
| 212 | break; | ||
| 213 | case 1: | ||
| 214 | default: | ||
| 215 | mode.mode |= RADEON_AGP_1X_MODE; | ||
| 216 | break; | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | mode.mode &= ~RADEON_AGP_FW_MODE; /* disable fw */ | ||
| 221 | ret = drm_agp_enable(rdev->ddev, mode); | ||
| 222 | if (ret) { | ||
| 223 | DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode); | ||
| 224 | return ret; | ||
| 225 | } | ||
| 226 | |||
| 227 | rdev->mc.agp_base = rdev->ddev->agp->agp_info.aper_base; | ||
| 228 | rdev->mc.gtt_size = rdev->ddev->agp->agp_info.aper_size << 20; | ||
| 229 | |||
| 230 | /* workaround some hw issues */ | ||
| 231 | if (rdev->family < CHIP_R200) { | ||
| 232 | WREG32(RADEON_AGP_CNTL, RREG32(RADEON_AGP_CNTL) | 0x000e0000); | ||
| 233 | } | ||
| 234 | return 0; | ||
| 235 | #else | ||
| 236 | return 0; | ||
| 237 | #endif | ||
| 238 | } | ||
| 239 | |||
| 240 | void radeon_agp_fini(struct radeon_device *rdev) | ||
| 241 | { | ||
| 242 | #if __OS_HAS_AGP | ||
| 243 | if (rdev->flags & RADEON_IS_AGP) { | ||
| 244 | if (rdev->ddev->agp && rdev->ddev->agp->acquired) { | ||
| 245 | drm_agp_release(rdev->ddev); | ||
| 246 | } | ||
| 247 | } | ||
| 248 | #endif | ||
| 249 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h new file mode 100644 index 000000000000..e57d8a784e9f --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
| @@ -0,0 +1,405 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #ifndef __RADEON_ASIC_H__ | ||
| 29 | #define __RADEON_ASIC_H__ | ||
| 30 | |||
| 31 | /* | ||
| 32 | * common functions | ||
| 33 | */ | ||
| 34 | void radeon_legacy_set_engine_clock(struct radeon_device *rdev, uint32_t eng_clock); | ||
| 35 | void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable); | ||
| 36 | |||
| 37 | void radeon_atom_set_engine_clock(struct radeon_device *rdev, uint32_t eng_clock); | ||
| 38 | void radeon_atom_set_memory_clock(struct radeon_device *rdev, uint32_t mem_clock); | ||
| 39 | void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable); | ||
| 40 | |||
| 41 | /* | ||
| 42 | * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 | ||
| 43 | */ | ||
| 44 | uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg); | ||
| 45 | void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | ||
| 46 | void r100_errata(struct radeon_device *rdev); | ||
| 47 | void r100_vram_info(struct radeon_device *rdev); | ||
| 48 | int r100_gpu_reset(struct radeon_device *rdev); | ||
| 49 | int r100_mc_init(struct radeon_device *rdev); | ||
| 50 | void r100_mc_fini(struct radeon_device *rdev); | ||
| 51 | int r100_wb_init(struct radeon_device *rdev); | ||
| 52 | void r100_wb_fini(struct radeon_device *rdev); | ||
| 53 | int r100_gart_enable(struct radeon_device *rdev); | ||
| 54 | void r100_pci_gart_disable(struct radeon_device *rdev); | ||
| 55 | void r100_pci_gart_tlb_flush(struct radeon_device *rdev); | ||
| 56 | int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); | ||
| 57 | int r100_cp_init(struct radeon_device *rdev, unsigned ring_size); | ||
| 58 | void r100_cp_fini(struct radeon_device *rdev); | ||
| 59 | void r100_cp_disable(struct radeon_device *rdev); | ||
| 60 | void r100_ring_start(struct radeon_device *rdev); | ||
| 61 | int r100_irq_set(struct radeon_device *rdev); | ||
| 62 | int r100_irq_process(struct radeon_device *rdev); | ||
| 63 | void r100_fence_ring_emit(struct radeon_device *rdev, | ||
| 64 | struct radeon_fence *fence); | ||
| 65 | int r100_cs_parse(struct radeon_cs_parser *p); | ||
| 66 | void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | ||
| 67 | uint32_t r100_pll_rreg(struct radeon_device *rdev, uint32_t reg); | ||
| 68 | int r100_copy_blit(struct radeon_device *rdev, | ||
| 69 | uint64_t src_offset, | ||
| 70 | uint64_t dst_offset, | ||
| 71 | unsigned num_pages, | ||
| 72 | struct radeon_fence *fence); | ||
| 73 | |||
| 74 | static struct radeon_asic r100_asic = { | ||
| 75 | .errata = &r100_errata, | ||
| 76 | .vram_info = &r100_vram_info, | ||
| 77 | .gpu_reset = &r100_gpu_reset, | ||
| 78 | .mc_init = &r100_mc_init, | ||
| 79 | .mc_fini = &r100_mc_fini, | ||
| 80 | .wb_init = &r100_wb_init, | ||
| 81 | .wb_fini = &r100_wb_fini, | ||
| 82 | .gart_enable = &r100_gart_enable, | ||
| 83 | .gart_disable = &r100_pci_gart_disable, | ||
| 84 | .gart_tlb_flush = &r100_pci_gart_tlb_flush, | ||
| 85 | .gart_set_page = &r100_pci_gart_set_page, | ||
| 86 | .cp_init = &r100_cp_init, | ||
| 87 | .cp_fini = &r100_cp_fini, | ||
| 88 | .cp_disable = &r100_cp_disable, | ||
| 89 | .ring_start = &r100_ring_start, | ||
| 90 | .irq_set = &r100_irq_set, | ||
| 91 | .irq_process = &r100_irq_process, | ||
| 92 | .fence_ring_emit = &r100_fence_ring_emit, | ||
| 93 | .cs_parse = &r100_cs_parse, | ||
| 94 | .copy_blit = &r100_copy_blit, | ||
| 95 | .copy_dma = NULL, | ||
| 96 | .copy = &r100_copy_blit, | ||
| 97 | .set_engine_clock = &radeon_legacy_set_engine_clock, | ||
| 98 | .set_memory_clock = NULL, | ||
| 99 | .set_pcie_lanes = NULL, | ||
| 100 | .set_clock_gating = &radeon_legacy_set_clock_gating, | ||
| 101 | }; | ||
| 102 | |||
| 103 | |||
| 104 | /* | ||
| 105 | * r300,r350,rv350,rv380 | ||
| 106 | */ | ||
| 107 | void r300_errata(struct radeon_device *rdev); | ||
| 108 | void r300_vram_info(struct radeon_device *rdev); | ||
| 109 | int r300_gpu_reset(struct radeon_device *rdev); | ||
| 110 | int r300_mc_init(struct radeon_device *rdev); | ||
| 111 | void r300_mc_fini(struct radeon_device *rdev); | ||
| 112 | void r300_ring_start(struct radeon_device *rdev); | ||
| 113 | void r300_fence_ring_emit(struct radeon_device *rdev, | ||
| 114 | struct radeon_fence *fence); | ||
| 115 | int r300_cs_parse(struct radeon_cs_parser *p); | ||
| 116 | int r300_gart_enable(struct radeon_device *rdev); | ||
| 117 | void rv370_pcie_gart_disable(struct radeon_device *rdev); | ||
| 118 | void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev); | ||
| 119 | int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); | ||
| 120 | uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg); | ||
| 121 | void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | ||
| 122 | void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes); | ||
| 123 | int r300_copy_dma(struct radeon_device *rdev, | ||
| 124 | uint64_t src_offset, | ||
| 125 | uint64_t dst_offset, | ||
| 126 | unsigned num_pages, | ||
| 127 | struct radeon_fence *fence); | ||
| 128 | static struct radeon_asic r300_asic = { | ||
| 129 | .errata = &r300_errata, | ||
| 130 | .vram_info = &r300_vram_info, | ||
| 131 | .gpu_reset = &r300_gpu_reset, | ||
| 132 | .mc_init = &r300_mc_init, | ||
| 133 | .mc_fini = &r300_mc_fini, | ||
| 134 | .wb_init = &r100_wb_init, | ||
| 135 | .wb_fini = &r100_wb_fini, | ||
| 136 | .gart_enable = &r300_gart_enable, | ||
| 137 | .gart_disable = &r100_pci_gart_disable, | ||
| 138 | .gart_tlb_flush = &r100_pci_gart_tlb_flush, | ||
| 139 | .gart_set_page = &r100_pci_gart_set_page, | ||
| 140 | .cp_init = &r100_cp_init, | ||
| 141 | .cp_fini = &r100_cp_fini, | ||
| 142 | .cp_disable = &r100_cp_disable, | ||
| 143 | .ring_start = &r300_ring_start, | ||
| 144 | .irq_set = &r100_irq_set, | ||
| 145 | .irq_process = &r100_irq_process, | ||
| 146 | .fence_ring_emit = &r300_fence_ring_emit, | ||
| 147 | .cs_parse = &r300_cs_parse, | ||
| 148 | .copy_blit = &r100_copy_blit, | ||
| 149 | .copy_dma = &r300_copy_dma, | ||
| 150 | .copy = &r100_copy_blit, | ||
| 151 | .set_engine_clock = &radeon_legacy_set_engine_clock, | ||
| 152 | .set_memory_clock = NULL, | ||
| 153 | .set_pcie_lanes = &rv370_set_pcie_lanes, | ||
| 154 | .set_clock_gating = &radeon_legacy_set_clock_gating, | ||
| 155 | }; | ||
| 156 | |||
| 157 | /* | ||
| 158 | * r420,r423,rv410 | ||
| 159 | */ | ||
| 160 | void r420_errata(struct radeon_device *rdev); | ||
| 161 | void r420_vram_info(struct radeon_device *rdev); | ||
| 162 | int r420_mc_init(struct radeon_device *rdev); | ||
| 163 | void r420_mc_fini(struct radeon_device *rdev); | ||
| 164 | static struct radeon_asic r420_asic = { | ||
| 165 | .errata = &r420_errata, | ||
| 166 | .vram_info = &r420_vram_info, | ||
| 167 | .gpu_reset = &r300_gpu_reset, | ||
| 168 | .mc_init = &r420_mc_init, | ||
| 169 | .mc_fini = &r420_mc_fini, | ||
| 170 | .wb_init = &r100_wb_init, | ||
| 171 | .wb_fini = &r100_wb_fini, | ||
| 172 | .gart_enable = &r300_gart_enable, | ||
| 173 | .gart_disable = &rv370_pcie_gart_disable, | ||
| 174 | .gart_tlb_flush = &rv370_pcie_gart_tlb_flush, | ||
| 175 | .gart_set_page = &rv370_pcie_gart_set_page, | ||
| 176 | .cp_init = &r100_cp_init, | ||
| 177 | .cp_fini = &r100_cp_fini, | ||
| 178 | .cp_disable = &r100_cp_disable, | ||
| 179 | .ring_start = &r300_ring_start, | ||
| 180 | .irq_set = &r100_irq_set, | ||
| 181 | .irq_process = &r100_irq_process, | ||
| 182 | .fence_ring_emit = &r300_fence_ring_emit, | ||
| 183 | .cs_parse = &r300_cs_parse, | ||
| 184 | .copy_blit = &r100_copy_blit, | ||
| 185 | .copy_dma = &r300_copy_dma, | ||
| 186 | .copy = &r100_copy_blit, | ||
| 187 | .set_engine_clock = &radeon_atom_set_engine_clock, | ||
| 188 | .set_memory_clock = &radeon_atom_set_memory_clock, | ||
| 189 | .set_pcie_lanes = &rv370_set_pcie_lanes, | ||
| 190 | .set_clock_gating = &radeon_atom_set_clock_gating, | ||
| 191 | }; | ||
| 192 | |||
| 193 | |||
| 194 | /* | ||
| 195 | * rs400,rs480 | ||
| 196 | */ | ||
| 197 | void rs400_errata(struct radeon_device *rdev); | ||
| 198 | void rs400_vram_info(struct radeon_device *rdev); | ||
| 199 | int rs400_mc_init(struct radeon_device *rdev); | ||
| 200 | void rs400_mc_fini(struct radeon_device *rdev); | ||
| 201 | int rs400_gart_enable(struct radeon_device *rdev); | ||
| 202 | void rs400_gart_disable(struct radeon_device *rdev); | ||
| 203 | void rs400_gart_tlb_flush(struct radeon_device *rdev); | ||
| 204 | int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); | ||
| 205 | uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg); | ||
| 206 | void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | ||
| 207 | static struct radeon_asic rs400_asic = { | ||
| 208 | .errata = &rs400_errata, | ||
| 209 | .vram_info = &rs400_vram_info, | ||
| 210 | .gpu_reset = &r300_gpu_reset, | ||
| 211 | .mc_init = &rs400_mc_init, | ||
| 212 | .mc_fini = &rs400_mc_fini, | ||
| 213 | .wb_init = &r100_wb_init, | ||
| 214 | .wb_fini = &r100_wb_fini, | ||
| 215 | .gart_enable = &rs400_gart_enable, | ||
| 216 | .gart_disable = &rs400_gart_disable, | ||
| 217 | .gart_tlb_flush = &rs400_gart_tlb_flush, | ||
| 218 | .gart_set_page = &rs400_gart_set_page, | ||
| 219 | .cp_init = &r100_cp_init, | ||
| 220 | .cp_fini = &r100_cp_fini, | ||
| 221 | .cp_disable = &r100_cp_disable, | ||
| 222 | .ring_start = &r300_ring_start, | ||
| 223 | .irq_set = &r100_irq_set, | ||
| 224 | .irq_process = &r100_irq_process, | ||
| 225 | .fence_ring_emit = &r300_fence_ring_emit, | ||
| 226 | .cs_parse = &r300_cs_parse, | ||
| 227 | .copy_blit = &r100_copy_blit, | ||
| 228 | .copy_dma = &r300_copy_dma, | ||
| 229 | .copy = &r100_copy_blit, | ||
| 230 | .set_engine_clock = &radeon_legacy_set_engine_clock, | ||
| 231 | .set_memory_clock = NULL, | ||
| 232 | .set_pcie_lanes = NULL, | ||
| 233 | .set_clock_gating = &radeon_legacy_set_clock_gating, | ||
| 234 | }; | ||
| 235 | |||
| 236 | |||
| 237 | /* | ||
| 238 | * rs600. | ||
| 239 | */ | ||
| 240 | void rs600_errata(struct radeon_device *rdev); | ||
| 241 | void rs600_vram_info(struct radeon_device *rdev); | ||
| 242 | int rs600_mc_init(struct radeon_device *rdev); | ||
| 243 | void rs600_mc_fini(struct radeon_device *rdev); | ||
| 244 | int rs600_irq_set(struct radeon_device *rdev); | ||
| 245 | int rs600_gart_enable(struct radeon_device *rdev); | ||
| 246 | void rs600_gart_disable(struct radeon_device *rdev); | ||
| 247 | void rs600_gart_tlb_flush(struct radeon_device *rdev); | ||
| 248 | int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); | ||
| 249 | uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg); | ||
| 250 | void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | ||
| 251 | static struct radeon_asic rs600_asic = { | ||
| 252 | .errata = &rs600_errata, | ||
| 253 | .vram_info = &rs600_vram_info, | ||
| 254 | .gpu_reset = &r300_gpu_reset, | ||
| 255 | .mc_init = &rs600_mc_init, | ||
| 256 | .mc_fini = &rs600_mc_fini, | ||
| 257 | .wb_init = &r100_wb_init, | ||
| 258 | .wb_fini = &r100_wb_fini, | ||
| 259 | .gart_enable = &rs600_gart_enable, | ||
| 260 | .gart_disable = &rs600_gart_disable, | ||
| 261 | .gart_tlb_flush = &rs600_gart_tlb_flush, | ||
| 262 | .gart_set_page = &rs600_gart_set_page, | ||
| 263 | .cp_init = &r100_cp_init, | ||
| 264 | .cp_fini = &r100_cp_fini, | ||
| 265 | .cp_disable = &r100_cp_disable, | ||
| 266 | .ring_start = &r300_ring_start, | ||
| 267 | .irq_set = &rs600_irq_set, | ||
| 268 | .irq_process = &r100_irq_process, | ||
| 269 | .fence_ring_emit = &r300_fence_ring_emit, | ||
| 270 | .cs_parse = &r300_cs_parse, | ||
| 271 | .copy_blit = &r100_copy_blit, | ||
| 272 | .copy_dma = &r300_copy_dma, | ||
| 273 | .copy = &r100_copy_blit, | ||
| 274 | .set_engine_clock = &radeon_atom_set_engine_clock, | ||
| 275 | .set_memory_clock = &radeon_atom_set_memory_clock, | ||
| 276 | .set_pcie_lanes = NULL, | ||
| 277 | .set_clock_gating = &radeon_atom_set_clock_gating, | ||
| 278 | }; | ||
| 279 | |||
| 280 | |||
| 281 | /* | ||
| 282 | * rs690,rs740 | ||
| 283 | */ | ||
| 284 | void rs690_errata(struct radeon_device *rdev); | ||
| 285 | void rs690_vram_info(struct radeon_device *rdev); | ||
| 286 | int rs690_mc_init(struct radeon_device *rdev); | ||
| 287 | void rs690_mc_fini(struct radeon_device *rdev); | ||
| 288 | uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg); | ||
| 289 | void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | ||
| 290 | static struct radeon_asic rs690_asic = { | ||
| 291 | .errata = &rs690_errata, | ||
| 292 | .vram_info = &rs690_vram_info, | ||
| 293 | .gpu_reset = &r300_gpu_reset, | ||
| 294 | .mc_init = &rs690_mc_init, | ||
| 295 | .mc_fini = &rs690_mc_fini, | ||
| 296 | .wb_init = &r100_wb_init, | ||
| 297 | .wb_fini = &r100_wb_fini, | ||
| 298 | .gart_enable = &rs400_gart_enable, | ||
| 299 | .gart_disable = &rs400_gart_disable, | ||
| 300 | .gart_tlb_flush = &rs400_gart_tlb_flush, | ||
| 301 | .gart_set_page = &rs400_gart_set_page, | ||
| 302 | .cp_init = &r100_cp_init, | ||
| 303 | .cp_fini = &r100_cp_fini, | ||
| 304 | .cp_disable = &r100_cp_disable, | ||
| 305 | .ring_start = &r300_ring_start, | ||
| 306 | .irq_set = &rs600_irq_set, | ||
| 307 | .irq_process = &r100_irq_process, | ||
| 308 | .fence_ring_emit = &r300_fence_ring_emit, | ||
| 309 | .cs_parse = &r300_cs_parse, | ||
| 310 | .copy_blit = &r100_copy_blit, | ||
| 311 | .copy_dma = &r300_copy_dma, | ||
| 312 | .copy = &r300_copy_dma, | ||
| 313 | .set_engine_clock = &radeon_atom_set_engine_clock, | ||
| 314 | .set_memory_clock = &radeon_atom_set_memory_clock, | ||
| 315 | .set_pcie_lanes = NULL, | ||
| 316 | .set_clock_gating = &radeon_atom_set_clock_gating, | ||
| 317 | }; | ||
| 318 | |||
| 319 | |||
| 320 | /* | ||
| 321 | * rv515 | ||
| 322 | */ | ||
| 323 | void rv515_errata(struct radeon_device *rdev); | ||
| 324 | void rv515_vram_info(struct radeon_device *rdev); | ||
| 325 | int rv515_gpu_reset(struct radeon_device *rdev); | ||
| 326 | int rv515_mc_init(struct radeon_device *rdev); | ||
| 327 | void rv515_mc_fini(struct radeon_device *rdev); | ||
| 328 | uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg); | ||
| 329 | void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | ||
| 330 | void rv515_ring_start(struct radeon_device *rdev); | ||
| 331 | uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg); | ||
| 332 | void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | ||
| 333 | static struct radeon_asic rv515_asic = { | ||
| 334 | .errata = &rv515_errata, | ||
| 335 | .vram_info = &rv515_vram_info, | ||
| 336 | .gpu_reset = &rv515_gpu_reset, | ||
| 337 | .mc_init = &rv515_mc_init, | ||
| 338 | .mc_fini = &rv515_mc_fini, | ||
| 339 | .wb_init = &r100_wb_init, | ||
| 340 | .wb_fini = &r100_wb_fini, | ||
| 341 | .gart_enable = &r300_gart_enable, | ||
| 342 | .gart_disable = &rv370_pcie_gart_disable, | ||
| 343 | .gart_tlb_flush = &rv370_pcie_gart_tlb_flush, | ||
| 344 | .gart_set_page = &rv370_pcie_gart_set_page, | ||
| 345 | .cp_init = &r100_cp_init, | ||
| 346 | .cp_fini = &r100_cp_fini, | ||
| 347 | .cp_disable = &r100_cp_disable, | ||
| 348 | .ring_start = &rv515_ring_start, | ||
| 349 | .irq_set = &r100_irq_set, | ||
| 350 | .irq_process = &r100_irq_process, | ||
| 351 | .fence_ring_emit = &r300_fence_ring_emit, | ||
| 352 | .cs_parse = &r100_cs_parse, | ||
| 353 | .copy_blit = &r100_copy_blit, | ||
| 354 | .copy_dma = &r300_copy_dma, | ||
| 355 | .copy = &r100_copy_blit, | ||
| 356 | .set_engine_clock = &radeon_atom_set_engine_clock, | ||
| 357 | .set_memory_clock = &radeon_atom_set_memory_clock, | ||
| 358 | .set_pcie_lanes = &rv370_set_pcie_lanes, | ||
| 359 | .set_clock_gating = &radeon_atom_set_clock_gating, | ||
| 360 | }; | ||
| 361 | |||
| 362 | |||
| 363 | /* | ||
| 364 | * r520,rv530,rv560,rv570,r580 | ||
| 365 | */ | ||
| 366 | void r520_errata(struct radeon_device *rdev); | ||
| 367 | void r520_vram_info(struct radeon_device *rdev); | ||
| 368 | int r520_mc_init(struct radeon_device *rdev); | ||
| 369 | void r520_mc_fini(struct radeon_device *rdev); | ||
| 370 | static struct radeon_asic r520_asic = { | ||
| 371 | .errata = &r520_errata, | ||
| 372 | .vram_info = &r520_vram_info, | ||
| 373 | .gpu_reset = &rv515_gpu_reset, | ||
| 374 | .mc_init = &r520_mc_init, | ||
| 375 | .mc_fini = &r520_mc_fini, | ||
| 376 | .wb_init = &r100_wb_init, | ||
| 377 | .wb_fini = &r100_wb_fini, | ||
| 378 | .gart_enable = &r300_gart_enable, | ||
| 379 | .gart_disable = &rv370_pcie_gart_disable, | ||
| 380 | .gart_tlb_flush = &rv370_pcie_gart_tlb_flush, | ||
| 381 | .gart_set_page = &rv370_pcie_gart_set_page, | ||
| 382 | .cp_init = &r100_cp_init, | ||
| 383 | .cp_fini = &r100_cp_fini, | ||
| 384 | .cp_disable = &r100_cp_disable, | ||
| 385 | .ring_start = &rv515_ring_start, | ||
| 386 | .irq_set = &r100_irq_set, | ||
| 387 | .irq_process = &r100_irq_process, | ||
| 388 | .fence_ring_emit = &r300_fence_ring_emit, | ||
| 389 | .cs_parse = &r100_cs_parse, | ||
| 390 | .copy_blit = &r100_copy_blit, | ||
| 391 | .copy_dma = &r300_copy_dma, | ||
| 392 | .copy = &r100_copy_blit, | ||
| 393 | .set_engine_clock = &radeon_atom_set_engine_clock, | ||
| 394 | .set_memory_clock = &radeon_atom_set_memory_clock, | ||
| 395 | .set_pcie_lanes = &rv370_set_pcie_lanes, | ||
| 396 | .set_clock_gating = &radeon_atom_set_clock_gating, | ||
| 397 | }; | ||
| 398 | |||
| 399 | /* | ||
| 400 | * r600,rv610,rv630,rv620,rv635,rv670,rs780,rv770,rv730,rv710 | ||
| 401 | */ | ||
| 402 | uint32_t r600_pciep_rreg(struct radeon_device *rdev, uint32_t reg); | ||
| 403 | void r600_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | ||
| 404 | |||
| 405 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c new file mode 100644 index 000000000000..786632d3e378 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
| @@ -0,0 +1,1298 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2007-8 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * copy of this software and associated documentation files (the "Software"), | ||
| 7 | * to deal in the Software without restriction, including without limitation | ||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 10 | * Software is furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 21 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: Dave Airlie | ||
| 24 | * Alex Deucher | ||
| 25 | */ | ||
| 26 | #include "drmP.h" | ||
| 27 | #include "radeon_drm.h" | ||
| 28 | #include "radeon.h" | ||
| 29 | |||
| 30 | #include "atom.h" | ||
| 31 | #include "atom-bits.h" | ||
| 32 | |||
| 33 | /* from radeon_encoder.c */ | ||
| 34 | extern uint32_t | ||
| 35 | radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, | ||
| 36 | uint8_t dac); | ||
| 37 | extern void radeon_link_encoder_connector(struct drm_device *dev); | ||
| 38 | extern void | ||
| 39 | radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, | ||
| 40 | uint32_t supported_device); | ||
| 41 | |||
| 42 | /* from radeon_connector.c */ | ||
| 43 | extern void | ||
| 44 | radeon_add_atom_connector(struct drm_device *dev, | ||
| 45 | uint32_t connector_id, | ||
| 46 | uint32_t supported_device, | ||
| 47 | int connector_type, | ||
| 48 | struct radeon_i2c_bus_rec *i2c_bus, | ||
| 49 | bool linkb, uint32_t igp_lane_info); | ||
| 50 | |||
| 51 | /* from radeon_legacy_encoder.c */ | ||
| 52 | extern void | ||
| 53 | radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, | ||
| 54 | uint32_t supported_device); | ||
| 55 | |||
| 56 | union atom_supported_devices { | ||
| 57 | struct _ATOM_SUPPORTED_DEVICES_INFO info; | ||
| 58 | struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2; | ||
| 59 | struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1; | ||
| 60 | }; | ||
| 61 | |||
| 62 | static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device | ||
| 63 | *dev, uint8_t id) | ||
| 64 | { | ||
| 65 | struct radeon_device *rdev = dev->dev_private; | ||
| 66 | struct atom_context *ctx = rdev->mode_info.atom_context; | ||
| 67 | ATOM_GPIO_I2C_ASSIGMENT gpio; | ||
| 68 | struct radeon_i2c_bus_rec i2c; | ||
| 69 | int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info); | ||
| 70 | struct _ATOM_GPIO_I2C_INFO *i2c_info; | ||
| 71 | uint16_t data_offset; | ||
| 72 | |||
| 73 | memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec)); | ||
| 74 | i2c.valid = false; | ||
| 75 | |||
| 76 | atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset); | ||
| 77 | |||
| 78 | i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset); | ||
| 79 | |||
| 80 | gpio = i2c_info->asGPIO_Info[id]; | ||
| 81 | |||
| 82 | i2c.mask_clk_reg = le16_to_cpu(gpio.usClkMaskRegisterIndex) * 4; | ||
| 83 | i2c.mask_data_reg = le16_to_cpu(gpio.usDataMaskRegisterIndex) * 4; | ||
| 84 | i2c.put_clk_reg = le16_to_cpu(gpio.usClkEnRegisterIndex) * 4; | ||
| 85 | i2c.put_data_reg = le16_to_cpu(gpio.usDataEnRegisterIndex) * 4; | ||
| 86 | i2c.get_clk_reg = le16_to_cpu(gpio.usClkY_RegisterIndex) * 4; | ||
| 87 | i2c.get_data_reg = le16_to_cpu(gpio.usDataY_RegisterIndex) * 4; | ||
| 88 | i2c.a_clk_reg = le16_to_cpu(gpio.usClkA_RegisterIndex) * 4; | ||
| 89 | i2c.a_data_reg = le16_to_cpu(gpio.usDataA_RegisterIndex) * 4; | ||
| 90 | i2c.mask_clk_mask = (1 << gpio.ucClkMaskShift); | ||
| 91 | i2c.mask_data_mask = (1 << gpio.ucDataMaskShift); | ||
| 92 | i2c.put_clk_mask = (1 << gpio.ucClkEnShift); | ||
| 93 | i2c.put_data_mask = (1 << gpio.ucDataEnShift); | ||
| 94 | i2c.get_clk_mask = (1 << gpio.ucClkY_Shift); | ||
| 95 | i2c.get_data_mask = (1 << gpio.ucDataY_Shift); | ||
| 96 | i2c.a_clk_mask = (1 << gpio.ucClkA_Shift); | ||
| 97 | i2c.a_data_mask = (1 << gpio.ucDataA_Shift); | ||
| 98 | i2c.valid = true; | ||
| 99 | |||
| 100 | return i2c; | ||
| 101 | } | ||
| 102 | |||
| 103 | static bool radeon_atom_apply_quirks(struct drm_device *dev, | ||
| 104 | uint32_t supported_device, | ||
| 105 | int *connector_type, | ||
| 106 | struct radeon_i2c_bus_rec *i2c_bus) | ||
| 107 | { | ||
| 108 | |||
| 109 | /* Asus M2A-VM HDMI board lists the DVI port as HDMI */ | ||
| 110 | if ((dev->pdev->device == 0x791e) && | ||
| 111 | (dev->pdev->subsystem_vendor == 0x1043) && | ||
| 112 | (dev->pdev->subsystem_device == 0x826d)) { | ||
| 113 | if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) && | ||
| 114 | (supported_device == ATOM_DEVICE_DFP3_SUPPORT)) | ||
| 115 | *connector_type = DRM_MODE_CONNECTOR_DVID; | ||
| 116 | } | ||
| 117 | |||
| 118 | /* a-bit f-i90hd - ciaranm on #radeonhd - this board has no DVI */ | ||
| 119 | if ((dev->pdev->device == 0x7941) && | ||
| 120 | (dev->pdev->subsystem_vendor == 0x147b) && | ||
| 121 | (dev->pdev->subsystem_device == 0x2412)) { | ||
| 122 | if (*connector_type == DRM_MODE_CONNECTOR_DVII) | ||
| 123 | return false; | ||
| 124 | } | ||
| 125 | |||
| 126 | /* Falcon NW laptop lists vga ddc line for LVDS */ | ||
| 127 | if ((dev->pdev->device == 0x5653) && | ||
| 128 | (dev->pdev->subsystem_vendor == 0x1462) && | ||
| 129 | (dev->pdev->subsystem_device == 0x0291)) { | ||
| 130 | if (*connector_type == DRM_MODE_CONNECTOR_LVDS) | ||
| 131 | i2c_bus->valid = false; | ||
| 132 | } | ||
| 133 | |||
| 134 | /* Funky macbooks */ | ||
| 135 | if ((dev->pdev->device == 0x71C5) && | ||
| 136 | (dev->pdev->subsystem_vendor == 0x106b) && | ||
| 137 | (dev->pdev->subsystem_device == 0x0080)) { | ||
| 138 | if ((supported_device == ATOM_DEVICE_CRT1_SUPPORT) || | ||
| 139 | (supported_device == ATOM_DEVICE_DFP2_SUPPORT)) | ||
| 140 | return false; | ||
| 141 | } | ||
| 142 | |||
| 143 | /* some BIOSes seem to report DAC on HDMI - they hurt me with their lies */ | ||
| 144 | if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) || | ||
| 145 | (*connector_type == DRM_MODE_CONNECTOR_HDMIB)) { | ||
| 146 | if (supported_device & (ATOM_DEVICE_CRT_SUPPORT)) { | ||
| 147 | return false; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | /* ASUS HD 3600 XT board lists the DVI port as HDMI */ | ||
| 152 | if ((dev->pdev->device == 0x9598) && | ||
| 153 | (dev->pdev->subsystem_vendor == 0x1043) && | ||
| 154 | (dev->pdev->subsystem_device == 0x01da)) { | ||
| 155 | if (*connector_type == DRM_MODE_CONNECTOR_HDMIB) { | ||
| 156 | *connector_type = DRM_MODE_CONNECTOR_DVID; | ||
| 157 | } | ||
| 158 | } | ||
| 159 | |||
| 160 | return true; | ||
| 161 | } | ||
| 162 | |||
| 163 | const int supported_devices_connector_convert[] = { | ||
| 164 | DRM_MODE_CONNECTOR_Unknown, | ||
| 165 | DRM_MODE_CONNECTOR_VGA, | ||
| 166 | DRM_MODE_CONNECTOR_DVII, | ||
| 167 | DRM_MODE_CONNECTOR_DVID, | ||
| 168 | DRM_MODE_CONNECTOR_DVIA, | ||
| 169 | DRM_MODE_CONNECTOR_SVIDEO, | ||
| 170 | DRM_MODE_CONNECTOR_Composite, | ||
| 171 | DRM_MODE_CONNECTOR_LVDS, | ||
| 172 | DRM_MODE_CONNECTOR_Unknown, | ||
| 173 | DRM_MODE_CONNECTOR_Unknown, | ||
| 174 | DRM_MODE_CONNECTOR_HDMIA, | ||
| 175 | DRM_MODE_CONNECTOR_HDMIB, | ||
| 176 | DRM_MODE_CONNECTOR_Unknown, | ||
| 177 | DRM_MODE_CONNECTOR_Unknown, | ||
| 178 | DRM_MODE_CONNECTOR_9PinDIN, | ||
| 179 | DRM_MODE_CONNECTOR_DisplayPort | ||
| 180 | }; | ||
| 181 | |||
| 182 | const int object_connector_convert[] = { | ||
| 183 | DRM_MODE_CONNECTOR_Unknown, | ||
| 184 | DRM_MODE_CONNECTOR_DVII, | ||
| 185 | DRM_MODE_CONNECTOR_DVII, | ||
| 186 | DRM_MODE_CONNECTOR_DVID, | ||
| 187 | DRM_MODE_CONNECTOR_DVID, | ||
| 188 | DRM_MODE_CONNECTOR_VGA, | ||
| 189 | DRM_MODE_CONNECTOR_Composite, | ||
| 190 | DRM_MODE_CONNECTOR_SVIDEO, | ||
| 191 | DRM_MODE_CONNECTOR_Unknown, | ||
| 192 | DRM_MODE_CONNECTOR_9PinDIN, | ||
| 193 | DRM_MODE_CONNECTOR_Unknown, | ||
| 194 | DRM_MODE_CONNECTOR_HDMIA, | ||
| 195 | DRM_MODE_CONNECTOR_HDMIB, | ||
| 196 | DRM_MODE_CONNECTOR_HDMIB, | ||
| 197 | DRM_MODE_CONNECTOR_LVDS, | ||
| 198 | DRM_MODE_CONNECTOR_9PinDIN, | ||
| 199 | DRM_MODE_CONNECTOR_Unknown, | ||
| 200 | DRM_MODE_CONNECTOR_Unknown, | ||
| 201 | DRM_MODE_CONNECTOR_Unknown, | ||
| 202 | DRM_MODE_CONNECTOR_DisplayPort | ||
| 203 | }; | ||
| 204 | |||
| 205 | bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) | ||
| 206 | { | ||
| 207 | struct radeon_device *rdev = dev->dev_private; | ||
| 208 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
| 209 | struct atom_context *ctx = mode_info->atom_context; | ||
| 210 | int index = GetIndexIntoMasterTable(DATA, Object_Header); | ||
| 211 | uint16_t size, data_offset; | ||
| 212 | uint8_t frev, crev, line_mux = 0; | ||
| 213 | ATOM_CONNECTOR_OBJECT_TABLE *con_obj; | ||
| 214 | ATOM_DISPLAY_OBJECT_PATH_TABLE *path_obj; | ||
| 215 | ATOM_OBJECT_HEADER *obj_header; | ||
| 216 | int i, j, path_size, device_support; | ||
| 217 | int connector_type; | ||
| 218 | uint16_t igp_lane_info; | ||
| 219 | bool linkb; | ||
| 220 | struct radeon_i2c_bus_rec ddc_bus; | ||
| 221 | |||
| 222 | atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset); | ||
| 223 | |||
| 224 | if (data_offset == 0) | ||
| 225 | return false; | ||
| 226 | |||
| 227 | if (crev < 2) | ||
| 228 | return false; | ||
| 229 | |||
| 230 | obj_header = (ATOM_OBJECT_HEADER *) (ctx->bios + data_offset); | ||
| 231 | path_obj = (ATOM_DISPLAY_OBJECT_PATH_TABLE *) | ||
| 232 | (ctx->bios + data_offset + | ||
| 233 | le16_to_cpu(obj_header->usDisplayPathTableOffset)); | ||
| 234 | con_obj = (ATOM_CONNECTOR_OBJECT_TABLE *) | ||
| 235 | (ctx->bios + data_offset + | ||
| 236 | le16_to_cpu(obj_header->usConnectorObjectTableOffset)); | ||
| 237 | device_support = le16_to_cpu(obj_header->usDeviceSupport); | ||
| 238 | |||
| 239 | path_size = 0; | ||
| 240 | for (i = 0; i < path_obj->ucNumOfDispPath; i++) { | ||
| 241 | uint8_t *addr = (uint8_t *) path_obj->asDispPath; | ||
| 242 | ATOM_DISPLAY_OBJECT_PATH *path; | ||
| 243 | addr += path_size; | ||
| 244 | path = (ATOM_DISPLAY_OBJECT_PATH *) addr; | ||
| 245 | path_size += le16_to_cpu(path->usSize); | ||
| 246 | linkb = false; | ||
| 247 | |||
| 248 | if (device_support & le16_to_cpu(path->usDeviceTag)) { | ||
| 249 | uint8_t con_obj_id, con_obj_num, con_obj_type; | ||
| 250 | |||
| 251 | con_obj_id = | ||
| 252 | (le16_to_cpu(path->usConnObjectId) & OBJECT_ID_MASK) | ||
| 253 | >> OBJECT_ID_SHIFT; | ||
| 254 | con_obj_num = | ||
| 255 | (le16_to_cpu(path->usConnObjectId) & ENUM_ID_MASK) | ||
| 256 | >> ENUM_ID_SHIFT; | ||
| 257 | con_obj_type = | ||
| 258 | (le16_to_cpu(path->usConnObjectId) & | ||
| 259 | OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; | ||
| 260 | |||
| 261 | if ((le16_to_cpu(path->usDeviceTag) == | ||
| 262 | ATOM_DEVICE_TV1_SUPPORT) | ||
| 263 | || (le16_to_cpu(path->usDeviceTag) == | ||
| 264 | ATOM_DEVICE_TV2_SUPPORT) | ||
| 265 | || (le16_to_cpu(path->usDeviceTag) == | ||
| 266 | ATOM_DEVICE_CV_SUPPORT)) | ||
| 267 | continue; | ||
| 268 | |||
| 269 | if ((rdev->family == CHIP_RS780) && | ||
| 270 | (con_obj_id == | ||
| 271 | CONNECTOR_OBJECT_ID_PCIE_CONNECTOR)) { | ||
| 272 | uint16_t igp_offset = 0; | ||
| 273 | ATOM_INTEGRATED_SYSTEM_INFO_V2 *igp_obj; | ||
| 274 | |||
| 275 | index = | ||
| 276 | GetIndexIntoMasterTable(DATA, | ||
| 277 | IntegratedSystemInfo); | ||
| 278 | |||
| 279 | atom_parse_data_header(ctx, index, &size, &frev, | ||
| 280 | &crev, &igp_offset); | ||
| 281 | |||
| 282 | if (crev >= 2) { | ||
| 283 | igp_obj = | ||
| 284 | (ATOM_INTEGRATED_SYSTEM_INFO_V2 | ||
| 285 | *) (ctx->bios + igp_offset); | ||
| 286 | |||
| 287 | if (igp_obj) { | ||
| 288 | uint32_t slot_config, ct; | ||
| 289 | |||
| 290 | if (con_obj_num == 1) | ||
| 291 | slot_config = | ||
| 292 | igp_obj-> | ||
| 293 | ulDDISlot1Config; | ||
| 294 | else | ||
| 295 | slot_config = | ||
| 296 | igp_obj-> | ||
| 297 | ulDDISlot2Config; | ||
| 298 | |||
| 299 | ct = (slot_config >> 16) & 0xff; | ||
| 300 | connector_type = | ||
| 301 | object_connector_convert | ||
| 302 | [ct]; | ||
| 303 | igp_lane_info = | ||
| 304 | slot_config & 0xffff; | ||
| 305 | } else | ||
| 306 | continue; | ||
| 307 | } else | ||
| 308 | continue; | ||
| 309 | } else { | ||
| 310 | igp_lane_info = 0; | ||
| 311 | connector_type = | ||
| 312 | object_connector_convert[con_obj_id]; | ||
| 313 | } | ||
| 314 | |||
| 315 | if (connector_type == DRM_MODE_CONNECTOR_Unknown) | ||
| 316 | continue; | ||
| 317 | |||
| 318 | for (j = 0; j < ((le16_to_cpu(path->usSize) - 8) / 2); | ||
| 319 | j++) { | ||
| 320 | uint8_t enc_obj_id, enc_obj_num, enc_obj_type; | ||
| 321 | |||
| 322 | enc_obj_id = | ||
| 323 | (le16_to_cpu(path->usGraphicObjIds[j]) & | ||
| 324 | OBJECT_ID_MASK) >> OBJECT_ID_SHIFT; | ||
| 325 | enc_obj_num = | ||
| 326 | (le16_to_cpu(path->usGraphicObjIds[j]) & | ||
| 327 | ENUM_ID_MASK) >> ENUM_ID_SHIFT; | ||
| 328 | enc_obj_type = | ||
| 329 | (le16_to_cpu(path->usGraphicObjIds[j]) & | ||
| 330 | OBJECT_TYPE_MASK) >> OBJECT_TYPE_SHIFT; | ||
| 331 | |||
| 332 | /* FIXME: add support for router objects */ | ||
| 333 | if (enc_obj_type == GRAPH_OBJECT_TYPE_ENCODER) { | ||
| 334 | if (enc_obj_num == 2) | ||
| 335 | linkb = true; | ||
| 336 | else | ||
| 337 | linkb = false; | ||
| 338 | |||
| 339 | radeon_add_atom_encoder(dev, | ||
| 340 | enc_obj_id, | ||
| 341 | le16_to_cpu | ||
| 342 | (path-> | ||
| 343 | usDeviceTag)); | ||
| 344 | |||
| 345 | } | ||
| 346 | } | ||
| 347 | |||
| 348 | /* look up gpio for ddc */ | ||
| 349 | if ((le16_to_cpu(path->usDeviceTag) & | ||
| 350 | (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) | ||
| 351 | == 0) { | ||
| 352 | for (j = 0; j < con_obj->ucNumberOfObjects; j++) { | ||
| 353 | if (le16_to_cpu(path->usConnObjectId) == | ||
| 354 | le16_to_cpu(con_obj->asObjects[j]. | ||
| 355 | usObjectID)) { | ||
| 356 | ATOM_COMMON_RECORD_HEADER | ||
| 357 | *record = | ||
| 358 | (ATOM_COMMON_RECORD_HEADER | ||
| 359 | *) | ||
| 360 | (ctx->bios + data_offset + | ||
| 361 | le16_to_cpu(con_obj-> | ||
| 362 | asObjects[j]. | ||
| 363 | usRecordOffset)); | ||
| 364 | ATOM_I2C_RECORD *i2c_record; | ||
| 365 | |||
| 366 | while (record->ucRecordType > 0 | ||
| 367 | && record-> | ||
| 368 | ucRecordType <= | ||
| 369 | ATOM_MAX_OBJECT_RECORD_NUMBER) { | ||
| 370 | DRM_ERROR | ||
| 371 | ("record type %d\n", | ||
| 372 | record-> | ||
| 373 | ucRecordType); | ||
| 374 | switch (record-> | ||
| 375 | ucRecordType) { | ||
| 376 | case ATOM_I2C_RECORD_TYPE: | ||
| 377 | i2c_record = | ||
| 378 | (ATOM_I2C_RECORD | ||
| 379 | *) record; | ||
| 380 | line_mux = | ||
| 381 | i2c_record-> | ||
| 382 | sucI2cId. | ||
| 383 | bfI2C_LineMux; | ||
| 384 | break; | ||
| 385 | } | ||
| 386 | record = | ||
| 387 | (ATOM_COMMON_RECORD_HEADER | ||
| 388 | *) ((char *)record | ||
| 389 | + | ||
| 390 | record-> | ||
| 391 | ucRecordSize); | ||
| 392 | } | ||
| 393 | break; | ||
| 394 | } | ||
| 395 | } | ||
| 396 | } else | ||
| 397 | line_mux = 0; | ||
| 398 | |||
| 399 | if ((le16_to_cpu(path->usDeviceTag) == | ||
| 400 | ATOM_DEVICE_TV1_SUPPORT) | ||
| 401 | || (le16_to_cpu(path->usDeviceTag) == | ||
| 402 | ATOM_DEVICE_TV2_SUPPORT) | ||
| 403 | || (le16_to_cpu(path->usDeviceTag) == | ||
| 404 | ATOM_DEVICE_CV_SUPPORT)) | ||
| 405 | ddc_bus.valid = false; | ||
| 406 | else | ||
| 407 | ddc_bus = radeon_lookup_gpio(dev, line_mux); | ||
| 408 | |||
| 409 | radeon_add_atom_connector(dev, | ||
| 410 | le16_to_cpu(path-> | ||
| 411 | usConnObjectId), | ||
| 412 | le16_to_cpu(path-> | ||
| 413 | usDeviceTag), | ||
| 414 | connector_type, &ddc_bus, | ||
| 415 | linkb, igp_lane_info); | ||
| 416 | |||
| 417 | } | ||
| 418 | } | ||
| 419 | |||
| 420 | radeon_link_encoder_connector(dev); | ||
| 421 | |||
| 422 | return true; | ||
| 423 | } | ||
| 424 | |||
| 425 | struct bios_connector { | ||
| 426 | bool valid; | ||
| 427 | uint8_t line_mux; | ||
| 428 | uint16_t devices; | ||
| 429 | int connector_type; | ||
| 430 | struct radeon_i2c_bus_rec ddc_bus; | ||
| 431 | }; | ||
| 432 | |||
| 433 | bool radeon_get_atom_connector_info_from_supported_devices_table(struct | ||
| 434 | drm_device | ||
| 435 | *dev) | ||
| 436 | { | ||
| 437 | struct radeon_device *rdev = dev->dev_private; | ||
| 438 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
| 439 | struct atom_context *ctx = mode_info->atom_context; | ||
| 440 | int index = GetIndexIntoMasterTable(DATA, SupportedDevicesInfo); | ||
| 441 | uint16_t size, data_offset; | ||
| 442 | uint8_t frev, crev; | ||
| 443 | uint16_t device_support; | ||
| 444 | uint8_t dac; | ||
| 445 | union atom_supported_devices *supported_devices; | ||
| 446 | int i, j; | ||
| 447 | struct bios_connector bios_connectors[ATOM_MAX_SUPPORTED_DEVICE]; | ||
| 448 | |||
| 449 | atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset); | ||
| 450 | |||
| 451 | supported_devices = | ||
| 452 | (union atom_supported_devices *)(ctx->bios + data_offset); | ||
| 453 | |||
| 454 | device_support = le16_to_cpu(supported_devices->info.usDeviceSupport); | ||
| 455 | |||
| 456 | for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { | ||
| 457 | ATOM_CONNECTOR_INFO_I2C ci = | ||
| 458 | supported_devices->info.asConnInfo[i]; | ||
| 459 | |||
| 460 | bios_connectors[i].valid = false; | ||
| 461 | |||
| 462 | if (!(device_support & (1 << i))) { | ||
| 463 | continue; | ||
| 464 | } | ||
| 465 | |||
| 466 | if (i == ATOM_DEVICE_CV_INDEX) { | ||
| 467 | DRM_DEBUG("Skipping Component Video\n"); | ||
| 468 | continue; | ||
| 469 | } | ||
| 470 | |||
| 471 | if (i == ATOM_DEVICE_TV1_INDEX) { | ||
| 472 | DRM_DEBUG("Skipping TV Out\n"); | ||
| 473 | continue; | ||
| 474 | } | ||
| 475 | |||
| 476 | bios_connectors[i].connector_type = | ||
| 477 | supported_devices_connector_convert[ci.sucConnectorInfo. | ||
| 478 | sbfAccess. | ||
| 479 | bfConnectorType]; | ||
| 480 | |||
| 481 | if (bios_connectors[i].connector_type == | ||
| 482 | DRM_MODE_CONNECTOR_Unknown) | ||
| 483 | continue; | ||
| 484 | |||
| 485 | dac = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC; | ||
| 486 | |||
| 487 | if ((rdev->family == CHIP_RS690) || | ||
| 488 | (rdev->family == CHIP_RS740)) { | ||
| 489 | if ((i == ATOM_DEVICE_DFP2_INDEX) | ||
| 490 | && (ci.sucI2cId.sbfAccess.bfI2C_LineMux == 2)) | ||
| 491 | bios_connectors[i].line_mux = | ||
| 492 | ci.sucI2cId.sbfAccess.bfI2C_LineMux + 1; | ||
| 493 | else if ((i == ATOM_DEVICE_DFP3_INDEX) | ||
| 494 | && (ci.sucI2cId.sbfAccess.bfI2C_LineMux == 1)) | ||
| 495 | bios_connectors[i].line_mux = | ||
| 496 | ci.sucI2cId.sbfAccess.bfI2C_LineMux + 1; | ||
| 497 | else | ||
| 498 | bios_connectors[i].line_mux = | ||
| 499 | ci.sucI2cId.sbfAccess.bfI2C_LineMux; | ||
| 500 | } else | ||
| 501 | bios_connectors[i].line_mux = | ||
| 502 | ci.sucI2cId.sbfAccess.bfI2C_LineMux; | ||
| 503 | |||
| 504 | /* give tv unique connector ids */ | ||
| 505 | if (i == ATOM_DEVICE_TV1_INDEX) { | ||
| 506 | bios_connectors[i].ddc_bus.valid = false; | ||
| 507 | bios_connectors[i].line_mux = 50; | ||
| 508 | } else if (i == ATOM_DEVICE_TV2_INDEX) { | ||
| 509 | bios_connectors[i].ddc_bus.valid = false; | ||
| 510 | bios_connectors[i].line_mux = 51; | ||
| 511 | } else if (i == ATOM_DEVICE_CV_INDEX) { | ||
| 512 | bios_connectors[i].ddc_bus.valid = false; | ||
| 513 | bios_connectors[i].line_mux = 52; | ||
| 514 | } else | ||
| 515 | bios_connectors[i].ddc_bus = | ||
| 516 | radeon_lookup_gpio(dev, | ||
| 517 | bios_connectors[i].line_mux); | ||
| 518 | |||
| 519 | /* Always set the connector type to VGA for CRT1/CRT2. if they are | ||
| 520 | * shared with a DVI port, we'll pick up the DVI connector when we | ||
| 521 | * merge the outputs. Some bioses incorrectly list VGA ports as DVI. | ||
| 522 | */ | ||
| 523 | if (i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX) | ||
| 524 | bios_connectors[i].connector_type = | ||
| 525 | DRM_MODE_CONNECTOR_VGA; | ||
| 526 | |||
| 527 | if (!radeon_atom_apply_quirks | ||
| 528 | (dev, (1 << i), &bios_connectors[i].connector_type, | ||
| 529 | &bios_connectors[i].ddc_bus)) | ||
| 530 | continue; | ||
| 531 | |||
| 532 | bios_connectors[i].valid = true; | ||
| 533 | bios_connectors[i].devices = (1 << i); | ||
| 534 | |||
| 535 | if (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom) | ||
| 536 | radeon_add_atom_encoder(dev, | ||
| 537 | radeon_get_encoder_id(dev, | ||
| 538 | (1 << i), | ||
| 539 | dac), | ||
| 540 | (1 << i)); | ||
| 541 | else | ||
| 542 | radeon_add_legacy_encoder(dev, | ||
| 543 | radeon_get_encoder_id(dev, | ||
| 544 | (1 << | ||
| 545 | i), | ||
| 546 | dac), | ||
| 547 | (1 << i)); | ||
| 548 | } | ||
| 549 | |||
| 550 | /* combine shared connectors */ | ||
| 551 | for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { | ||
| 552 | if (bios_connectors[i].valid) { | ||
| 553 | for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) { | ||
| 554 | if (bios_connectors[j].valid && (i != j)) { | ||
| 555 | if (bios_connectors[i].line_mux == | ||
| 556 | bios_connectors[j].line_mux) { | ||
| 557 | if (((bios_connectors[i]. | ||
| 558 | devices & | ||
| 559 | (ATOM_DEVICE_DFP_SUPPORT)) | ||
| 560 | && (bios_connectors[j]. | ||
| 561 | devices & | ||
| 562 | (ATOM_DEVICE_CRT_SUPPORT))) | ||
| 563 | || | ||
| 564 | ((bios_connectors[j]. | ||
| 565 | devices & | ||
| 566 | (ATOM_DEVICE_DFP_SUPPORT)) | ||
| 567 | && (bios_connectors[i]. | ||
| 568 | devices & | ||
| 569 | (ATOM_DEVICE_CRT_SUPPORT)))) { | ||
| 570 | bios_connectors[i]. | ||
| 571 | devices |= | ||
| 572 | bios_connectors[j]. | ||
| 573 | devices; | ||
| 574 | bios_connectors[i]. | ||
| 575 | connector_type = | ||
| 576 | DRM_MODE_CONNECTOR_DVII; | ||
| 577 | bios_connectors[j]. | ||
| 578 | valid = false; | ||
| 579 | } | ||
| 580 | } | ||
| 581 | } | ||
| 582 | } | ||
| 583 | } | ||
| 584 | } | ||
| 585 | |||
| 586 | /* add the connectors */ | ||
| 587 | for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) { | ||
| 588 | if (bios_connectors[i].valid) | ||
| 589 | radeon_add_atom_connector(dev, | ||
| 590 | bios_connectors[i].line_mux, | ||
| 591 | bios_connectors[i].devices, | ||
| 592 | bios_connectors[i]. | ||
| 593 | connector_type, | ||
| 594 | &bios_connectors[i].ddc_bus, | ||
| 595 | false, 0); | ||
| 596 | } | ||
| 597 | |||
| 598 | radeon_link_encoder_connector(dev); | ||
| 599 | |||
| 600 | return true; | ||
| 601 | } | ||
| 602 | |||
| 603 | union firmware_info { | ||
| 604 | ATOM_FIRMWARE_INFO info; | ||
| 605 | ATOM_FIRMWARE_INFO_V1_2 info_12; | ||
| 606 | ATOM_FIRMWARE_INFO_V1_3 info_13; | ||
| 607 | ATOM_FIRMWARE_INFO_V1_4 info_14; | ||
| 608 | }; | ||
| 609 | |||
| 610 | bool radeon_atom_get_clock_info(struct drm_device *dev) | ||
| 611 | { | ||
| 612 | struct radeon_device *rdev = dev->dev_private; | ||
| 613 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
| 614 | int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); | ||
| 615 | union firmware_info *firmware_info; | ||
| 616 | uint8_t frev, crev; | ||
| 617 | struct radeon_pll *p1pll = &rdev->clock.p1pll; | ||
| 618 | struct radeon_pll *p2pll = &rdev->clock.p2pll; | ||
| 619 | struct radeon_pll *spll = &rdev->clock.spll; | ||
| 620 | struct radeon_pll *mpll = &rdev->clock.mpll; | ||
| 621 | uint16_t data_offset; | ||
| 622 | |||
| 623 | atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, | ||
| 624 | &crev, &data_offset); | ||
| 625 | |||
| 626 | firmware_info = | ||
| 627 | (union firmware_info *)(mode_info->atom_context->bios + | ||
| 628 | data_offset); | ||
| 629 | |||
| 630 | if (firmware_info) { | ||
| 631 | /* pixel clocks */ | ||
| 632 | p1pll->reference_freq = | ||
| 633 | le16_to_cpu(firmware_info->info.usReferenceClock); | ||
| 634 | p1pll->reference_div = 0; | ||
| 635 | |||
| 636 | p1pll->pll_out_min = | ||
| 637 | le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output); | ||
| 638 | p1pll->pll_out_max = | ||
| 639 | le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output); | ||
| 640 | |||
| 641 | if (p1pll->pll_out_min == 0) { | ||
| 642 | if (ASIC_IS_AVIVO(rdev)) | ||
| 643 | p1pll->pll_out_min = 64800; | ||
| 644 | else | ||
| 645 | p1pll->pll_out_min = 20000; | ||
| 646 | } | ||
| 647 | |||
| 648 | p1pll->pll_in_min = | ||
| 649 | le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Input); | ||
| 650 | p1pll->pll_in_max = | ||
| 651 | le16_to_cpu(firmware_info->info.usMaxPixelClockPLL_Input); | ||
| 652 | |||
| 653 | *p2pll = *p1pll; | ||
| 654 | |||
| 655 | /* system clock */ | ||
| 656 | spll->reference_freq = | ||
| 657 | le16_to_cpu(firmware_info->info.usReferenceClock); | ||
| 658 | spll->reference_div = 0; | ||
| 659 | |||
| 660 | spll->pll_out_min = | ||
| 661 | le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Output); | ||
| 662 | spll->pll_out_max = | ||
| 663 | le32_to_cpu(firmware_info->info.ulMaxEngineClockPLL_Output); | ||
| 664 | |||
| 665 | /* ??? */ | ||
| 666 | if (spll->pll_out_min == 0) { | ||
| 667 | if (ASIC_IS_AVIVO(rdev)) | ||
| 668 | spll->pll_out_min = 64800; | ||
| 669 | else | ||
| 670 | spll->pll_out_min = 20000; | ||
| 671 | } | ||
| 672 | |||
| 673 | spll->pll_in_min = | ||
| 674 | le16_to_cpu(firmware_info->info.usMinEngineClockPLL_Input); | ||
| 675 | spll->pll_in_max = | ||
| 676 | le16_to_cpu(firmware_info->info.usMaxEngineClockPLL_Input); | ||
| 677 | |||
| 678 | /* memory clock */ | ||
| 679 | mpll->reference_freq = | ||
| 680 | le16_to_cpu(firmware_info->info.usReferenceClock); | ||
| 681 | mpll->reference_div = 0; | ||
| 682 | |||
| 683 | mpll->pll_out_min = | ||
| 684 | le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Output); | ||
| 685 | mpll->pll_out_max = | ||
| 686 | le32_to_cpu(firmware_info->info.ulMaxMemoryClockPLL_Output); | ||
| 687 | |||
| 688 | /* ??? */ | ||
| 689 | if (mpll->pll_out_min == 0) { | ||
| 690 | if (ASIC_IS_AVIVO(rdev)) | ||
| 691 | mpll->pll_out_min = 64800; | ||
| 692 | else | ||
| 693 | mpll->pll_out_min = 20000; | ||
| 694 | } | ||
| 695 | |||
| 696 | mpll->pll_in_min = | ||
| 697 | le16_to_cpu(firmware_info->info.usMinMemoryClockPLL_Input); | ||
| 698 | mpll->pll_in_max = | ||
| 699 | le16_to_cpu(firmware_info->info.usMaxMemoryClockPLL_Input); | ||
| 700 | |||
| 701 | rdev->clock.default_sclk = | ||
| 702 | le32_to_cpu(firmware_info->info.ulDefaultEngineClock); | ||
| 703 | rdev->clock.default_mclk = | ||
| 704 | le32_to_cpu(firmware_info->info.ulDefaultMemoryClock); | ||
| 705 | |||
| 706 | return true; | ||
| 707 | } | ||
| 708 | return false; | ||
| 709 | } | ||
| 710 | |||
| 711 | struct radeon_encoder_int_tmds *radeon_atombios_get_tmds_info(struct | ||
| 712 | radeon_encoder | ||
| 713 | *encoder) | ||
| 714 | { | ||
| 715 | struct drm_device *dev = encoder->base.dev; | ||
| 716 | struct radeon_device *rdev = dev->dev_private; | ||
| 717 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
| 718 | int index = GetIndexIntoMasterTable(DATA, TMDS_Info); | ||
| 719 | uint16_t data_offset; | ||
| 720 | struct _ATOM_TMDS_INFO *tmds_info; | ||
| 721 | uint8_t frev, crev; | ||
| 722 | uint16_t maxfreq; | ||
| 723 | int i; | ||
| 724 | struct radeon_encoder_int_tmds *tmds = NULL; | ||
| 725 | |||
| 726 | atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, | ||
| 727 | &crev, &data_offset); | ||
| 728 | |||
| 729 | tmds_info = | ||
| 730 | (struct _ATOM_TMDS_INFO *)(mode_info->atom_context->bios + | ||
| 731 | data_offset); | ||
| 732 | |||
| 733 | if (tmds_info) { | ||
| 734 | tmds = | ||
| 735 | kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL); | ||
| 736 | |||
| 737 | if (!tmds) | ||
| 738 | return NULL; | ||
| 739 | |||
| 740 | maxfreq = le16_to_cpu(tmds_info->usMaxFrequency); | ||
| 741 | for (i = 0; i < 4; i++) { | ||
| 742 | tmds->tmds_pll[i].freq = | ||
| 743 | le16_to_cpu(tmds_info->asMiscInfo[i].usFrequency); | ||
| 744 | tmds->tmds_pll[i].value = | ||
| 745 | tmds_info->asMiscInfo[i].ucPLL_ChargePump & 0x3f; | ||
| 746 | tmds->tmds_pll[i].value |= | ||
| 747 | (tmds_info->asMiscInfo[i]. | ||
| 748 | ucPLL_VCO_Gain & 0x3f) << 6; | ||
| 749 | tmds->tmds_pll[i].value |= | ||
| 750 | (tmds_info->asMiscInfo[i]. | ||
| 751 | ucPLL_DutyCycle & 0xf) << 12; | ||
| 752 | tmds->tmds_pll[i].value |= | ||
| 753 | (tmds_info->asMiscInfo[i]. | ||
| 754 | ucPLL_VoltageSwing & 0xf) << 16; | ||
| 755 | |||
| 756 | DRM_DEBUG("TMDS PLL From ATOMBIOS %u %x\n", | ||
| 757 | tmds->tmds_pll[i].freq, | ||
| 758 | tmds->tmds_pll[i].value); | ||
| 759 | |||
| 760 | if (maxfreq == tmds->tmds_pll[i].freq) { | ||
| 761 | tmds->tmds_pll[i].freq = 0xffffffff; | ||
| 762 | break; | ||
| 763 | } | ||
| 764 | } | ||
| 765 | } | ||
| 766 | return tmds; | ||
| 767 | } | ||
| 768 | |||
| 769 | union lvds_info { | ||
| 770 | struct _ATOM_LVDS_INFO info; | ||
| 771 | struct _ATOM_LVDS_INFO_V12 info_12; | ||
| 772 | }; | ||
| 773 | |||
| 774 | struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct | ||
| 775 | radeon_encoder | ||
| 776 | *encoder) | ||
| 777 | { | ||
| 778 | struct drm_device *dev = encoder->base.dev; | ||
| 779 | struct radeon_device *rdev = dev->dev_private; | ||
| 780 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
| 781 | int index = GetIndexIntoMasterTable(DATA, LVDS_Info); | ||
| 782 | uint16_t data_offset; | ||
| 783 | union lvds_info *lvds_info; | ||
| 784 | uint8_t frev, crev; | ||
| 785 | struct radeon_encoder_atom_dig *lvds = NULL; | ||
| 786 | |||
| 787 | atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, | ||
| 788 | &crev, &data_offset); | ||
| 789 | |||
| 790 | lvds_info = | ||
| 791 | (union lvds_info *)(mode_info->atom_context->bios + data_offset); | ||
| 792 | |||
| 793 | if (lvds_info) { | ||
| 794 | lvds = | ||
| 795 | kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL); | ||
| 796 | |||
| 797 | if (!lvds) | ||
| 798 | return NULL; | ||
| 799 | |||
| 800 | lvds->native_mode.dotclock = | ||
| 801 | le16_to_cpu(lvds_info->info.sLCDTiming.usPixClk) * 10; | ||
| 802 | lvds->native_mode.panel_xres = | ||
| 803 | le16_to_cpu(lvds_info->info.sLCDTiming.usHActive); | ||
| 804 | lvds->native_mode.panel_yres = | ||
| 805 | le16_to_cpu(lvds_info->info.sLCDTiming.usVActive); | ||
| 806 | lvds->native_mode.hblank = | ||
| 807 | le16_to_cpu(lvds_info->info.sLCDTiming.usHBlanking_Time); | ||
| 808 | lvds->native_mode.hoverplus = | ||
| 809 | le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncOffset); | ||
| 810 | lvds->native_mode.hsync_width = | ||
| 811 | le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncWidth); | ||
| 812 | lvds->native_mode.vblank = | ||
| 813 | le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time); | ||
| 814 | lvds->native_mode.voverplus = | ||
| 815 | le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset); | ||
| 816 | lvds->native_mode.vsync_width = | ||
| 817 | le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth); | ||
| 818 | lvds->panel_pwr_delay = | ||
| 819 | le16_to_cpu(lvds_info->info.usOffDelayInMs); | ||
| 820 | lvds->lvds_misc = lvds_info->info.ucLVDS_Misc; | ||
| 821 | |||
| 822 | encoder->native_mode = lvds->native_mode; | ||
| 823 | } | ||
| 824 | return lvds; | ||
| 825 | } | ||
| 826 | |||
| 827 | struct radeon_encoder_primary_dac * | ||
| 828 | radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder) | ||
| 829 | { | ||
| 830 | struct drm_device *dev = encoder->base.dev; | ||
| 831 | struct radeon_device *rdev = dev->dev_private; | ||
| 832 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
| 833 | int index = GetIndexIntoMasterTable(DATA, CompassionateData); | ||
| 834 | uint16_t data_offset; | ||
| 835 | struct _COMPASSIONATE_DATA *dac_info; | ||
| 836 | uint8_t frev, crev; | ||
| 837 | uint8_t bg, dac; | ||
| 838 | int i; | ||
| 839 | struct radeon_encoder_primary_dac *p_dac = NULL; | ||
| 840 | |||
| 841 | atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset); | ||
| 842 | |||
| 843 | dac_info = (struct _COMPASSIONATE_DATA *)(mode_info->atom_context->bios + data_offset); | ||
| 844 | |||
| 845 | if (dac_info) { | ||
| 846 | p_dac = kzalloc(sizeof(struct radeon_encoder_primary_dac), GFP_KERNEL); | ||
| 847 | |||
| 848 | if (!p_dac) | ||
| 849 | return NULL; | ||
| 850 | |||
| 851 | bg = dac_info->ucDAC1_BG_Adjustment; | ||
| 852 | dac = dac_info->ucDAC1_DAC_Adjustment; | ||
| 853 | p_dac->ps2_pdac_adj = (bg << 8) | (dac); | ||
| 854 | |||
| 855 | } | ||
| 856 | return p_dac; | ||
| 857 | } | ||
| 858 | |||
| 859 | struct radeon_encoder_tv_dac * | ||
| 860 | radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder) | ||
| 861 | { | ||
| 862 | struct drm_device *dev = encoder->base.dev; | ||
| 863 | struct radeon_device *rdev = dev->dev_private; | ||
| 864 | struct radeon_mode_info *mode_info = &rdev->mode_info; | ||
| 865 | int index = GetIndexIntoMasterTable(DATA, CompassionateData); | ||
| 866 | uint16_t data_offset; | ||
| 867 | struct _COMPASSIONATE_DATA *dac_info; | ||
| 868 | uint8_t frev, crev; | ||
| 869 | uint8_t bg, dac; | ||
| 870 | int i; | ||
| 871 | struct radeon_encoder_tv_dac *tv_dac = NULL; | ||
| 872 | |||
| 873 | atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset); | ||
| 874 | |||
| 875 | dac_info = (struct _COMPASSIONATE_DATA *)(mode_info->atom_context->bios + data_offset); | ||
| 876 | |||
| 877 | if (dac_info) { | ||
| 878 | tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL); | ||
| 879 | |||
| 880 | if (!tv_dac) | ||
| 881 | return NULL; | ||
| 882 | |||
| 883 | bg = dac_info->ucDAC2_CRT2_BG_Adjustment; | ||
| 884 | dac = dac_info->ucDAC2_CRT2_DAC_Adjustment; | ||
| 885 | tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20); | ||
| 886 | |||
| 887 | bg = dac_info->ucDAC2_PAL_BG_Adjustment; | ||
| 888 | dac = dac_info->ucDAC2_PAL_DAC_Adjustment; | ||
| 889 | tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20); | ||
| 890 | |||
| 891 | bg = dac_info->ucDAC2_NTSC_BG_Adjustment; | ||
| 892 | dac = dac_info->ucDAC2_NTSC_DAC_Adjustment; | ||
| 893 | tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); | ||
| 894 | |||
| 895 | } | ||
| 896 | return tv_dac; | ||
| 897 | } | ||
| 898 | |||
| 899 | void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable) | ||
| 900 | { | ||
| 901 | DYNAMIC_CLOCK_GATING_PS_ALLOCATION args; | ||
| 902 | int index = GetIndexIntoMasterTable(COMMAND, DynamicClockGating); | ||
| 903 | |||
| 904 | args.ucEnable = enable; | ||
| 905 | |||
| 906 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 907 | } | ||
| 908 | |||
| 909 | void radeon_atom_static_pwrmgt_setup(struct radeon_device *rdev, int enable) | ||
| 910 | { | ||
| 911 | ENABLE_ASIC_STATIC_PWR_MGT_PS_ALLOCATION args; | ||
| 912 | int index = GetIndexIntoMasterTable(COMMAND, EnableASIC_StaticPwrMgt); | ||
| 913 | |||
| 914 | args.ucEnable = enable; | ||
| 915 | |||
| 916 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 917 | } | ||
| 918 | |||
| 919 | void radeon_atom_set_engine_clock(struct radeon_device *rdev, | ||
| 920 | uint32_t eng_clock) | ||
| 921 | { | ||
| 922 | SET_ENGINE_CLOCK_PS_ALLOCATION args; | ||
| 923 | int index = GetIndexIntoMasterTable(COMMAND, SetEngineClock); | ||
| 924 | |||
| 925 | args.ulTargetEngineClock = eng_clock; /* 10 khz */ | ||
| 926 | |||
| 927 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 928 | } | ||
| 929 | |||
| 930 | void radeon_atom_set_memory_clock(struct radeon_device *rdev, | ||
| 931 | uint32_t mem_clock) | ||
| 932 | { | ||
| 933 | SET_MEMORY_CLOCK_PS_ALLOCATION args; | ||
| 934 | int index = GetIndexIntoMasterTable(COMMAND, SetMemoryClock); | ||
| 935 | |||
| 936 | if (rdev->flags & RADEON_IS_IGP) | ||
| 937 | return; | ||
| 938 | |||
| 939 | args.ulTargetMemoryClock = mem_clock; /* 10 khz */ | ||
| 940 | |||
| 941 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 942 | } | ||
| 943 | |||
| 944 | void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) | ||
| 945 | { | ||
| 946 | struct radeon_device *rdev = dev->dev_private; | ||
| 947 | uint32_t bios_2_scratch, bios_6_scratch; | ||
| 948 | |||
| 949 | if (rdev->family >= CHIP_R600) { | ||
| 950 | bios_2_scratch = RREG32(R600_BIOS_0_SCRATCH); | ||
| 951 | bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH); | ||
| 952 | } else { | ||
| 953 | bios_2_scratch = RREG32(RADEON_BIOS_0_SCRATCH); | ||
| 954 | bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); | ||
| 955 | } | ||
| 956 | |||
| 957 | /* let the bios control the backlight */ | ||
| 958 | bios_2_scratch &= ~ATOM_S2_VRI_BRIGHT_ENABLE; | ||
| 959 | |||
| 960 | /* tell the bios not to handle mode switching */ | ||
| 961 | bios_6_scratch |= (ATOM_S6_ACC_BLOCK_DISPLAY_SWITCH | ATOM_S6_ACC_MODE); | ||
| 962 | |||
| 963 | if (rdev->family >= CHIP_R600) { | ||
| 964 | WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch); | ||
| 965 | WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch); | ||
| 966 | } else { | ||
| 967 | WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch); | ||
| 968 | WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch); | ||
| 969 | } | ||
| 970 | |||
| 971 | } | ||
| 972 | |||
| 973 | void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock) | ||
| 974 | { | ||
| 975 | struct drm_device *dev = encoder->dev; | ||
| 976 | struct radeon_device *rdev = dev->dev_private; | ||
| 977 | uint32_t bios_6_scratch; | ||
| 978 | |||
| 979 | if (rdev->family >= CHIP_R600) | ||
| 980 | bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH); | ||
| 981 | else | ||
| 982 | bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); | ||
| 983 | |||
| 984 | if (lock) | ||
| 985 | bios_6_scratch |= ATOM_S6_CRITICAL_STATE; | ||
| 986 | else | ||
| 987 | bios_6_scratch &= ~ATOM_S6_CRITICAL_STATE; | ||
| 988 | |||
| 989 | if (rdev->family >= CHIP_R600) | ||
| 990 | WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch); | ||
| 991 | else | ||
| 992 | WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch); | ||
| 993 | } | ||
| 994 | |||
| 995 | /* at some point we may want to break this out into individual functions */ | ||
| 996 | void | ||
| 997 | radeon_atombios_connected_scratch_regs(struct drm_connector *connector, | ||
| 998 | struct drm_encoder *encoder, | ||
| 999 | bool connected) | ||
| 1000 | { | ||
| 1001 | struct drm_device *dev = connector->dev; | ||
| 1002 | struct radeon_device *rdev = dev->dev_private; | ||
| 1003 | struct radeon_connector *radeon_connector = | ||
| 1004 | to_radeon_connector(connector); | ||
| 1005 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 1006 | uint32_t bios_0_scratch, bios_3_scratch, bios_6_scratch; | ||
| 1007 | |||
| 1008 | if (rdev->family >= CHIP_R600) { | ||
| 1009 | bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); | ||
| 1010 | bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH); | ||
| 1011 | bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH); | ||
| 1012 | } else { | ||
| 1013 | bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH); | ||
| 1014 | bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH); | ||
| 1015 | bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | if ((radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) && | ||
| 1019 | (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT)) { | ||
| 1020 | if (connected) { | ||
| 1021 | DRM_DEBUG("TV1 connected\n"); | ||
| 1022 | bios_3_scratch |= ATOM_S3_TV1_ACTIVE; | ||
| 1023 | bios_6_scratch |= ATOM_S6_ACC_REQ_TV1; | ||
| 1024 | } else { | ||
| 1025 | DRM_DEBUG("TV1 disconnected\n"); | ||
| 1026 | bios_0_scratch &= ~ATOM_S0_TV1_MASK; | ||
| 1027 | bios_3_scratch &= ~ATOM_S3_TV1_ACTIVE; | ||
| 1028 | bios_6_scratch &= ~ATOM_S6_ACC_REQ_TV1; | ||
| 1029 | } | ||
| 1030 | } | ||
| 1031 | if ((radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) && | ||
| 1032 | (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT)) { | ||
| 1033 | if (connected) { | ||
| 1034 | DRM_DEBUG("CV connected\n"); | ||
| 1035 | bios_3_scratch |= ATOM_S3_CV_ACTIVE; | ||
| 1036 | bios_6_scratch |= ATOM_S6_ACC_REQ_CV; | ||
| 1037 | } else { | ||
| 1038 | DRM_DEBUG("CV disconnected\n"); | ||
| 1039 | bios_0_scratch &= ~ATOM_S0_CV_MASK; | ||
| 1040 | bios_3_scratch &= ~ATOM_S3_CV_ACTIVE; | ||
| 1041 | bios_6_scratch &= ~ATOM_S6_ACC_REQ_CV; | ||
| 1042 | } | ||
| 1043 | } | ||
| 1044 | if ((radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) && | ||
| 1045 | (radeon_connector->devices & ATOM_DEVICE_LCD1_SUPPORT)) { | ||
| 1046 | if (connected) { | ||
| 1047 | DRM_DEBUG("LCD1 connected\n"); | ||
| 1048 | bios_0_scratch |= ATOM_S0_LCD1; | ||
| 1049 | bios_3_scratch |= ATOM_S3_LCD1_ACTIVE; | ||
| 1050 | bios_6_scratch |= ATOM_S6_ACC_REQ_LCD1; | ||
| 1051 | } else { | ||
| 1052 | DRM_DEBUG("LCD1 disconnected\n"); | ||
| 1053 | bios_0_scratch &= ~ATOM_S0_LCD1; | ||
| 1054 | bios_3_scratch &= ~ATOM_S3_LCD1_ACTIVE; | ||
| 1055 | bios_6_scratch &= ~ATOM_S6_ACC_REQ_LCD1; | ||
| 1056 | } | ||
| 1057 | } | ||
| 1058 | if ((radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) && | ||
| 1059 | (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)) { | ||
| 1060 | if (connected) { | ||
| 1061 | DRM_DEBUG("CRT1 connected\n"); | ||
| 1062 | bios_0_scratch |= ATOM_S0_CRT1_COLOR; | ||
| 1063 | bios_3_scratch |= ATOM_S3_CRT1_ACTIVE; | ||
| 1064 | bios_6_scratch |= ATOM_S6_ACC_REQ_CRT1; | ||
| 1065 | } else { | ||
| 1066 | DRM_DEBUG("CRT1 disconnected\n"); | ||
| 1067 | bios_0_scratch &= ~ATOM_S0_CRT1_MASK; | ||
| 1068 | bios_3_scratch &= ~ATOM_S3_CRT1_ACTIVE; | ||
| 1069 | bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT1; | ||
| 1070 | } | ||
| 1071 | } | ||
| 1072 | if ((radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) && | ||
| 1073 | (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)) { | ||
| 1074 | if (connected) { | ||
| 1075 | DRM_DEBUG("CRT2 connected\n"); | ||
| 1076 | bios_0_scratch |= ATOM_S0_CRT2_COLOR; | ||
| 1077 | bios_3_scratch |= ATOM_S3_CRT2_ACTIVE; | ||
| 1078 | bios_6_scratch |= ATOM_S6_ACC_REQ_CRT2; | ||
| 1079 | } else { | ||
| 1080 | DRM_DEBUG("CRT2 disconnected\n"); | ||
| 1081 | bios_0_scratch &= ~ATOM_S0_CRT2_MASK; | ||
| 1082 | bios_3_scratch &= ~ATOM_S3_CRT2_ACTIVE; | ||
| 1083 | bios_6_scratch &= ~ATOM_S6_ACC_REQ_CRT2; | ||
| 1084 | } | ||
| 1085 | } | ||
| 1086 | if ((radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) && | ||
| 1087 | (radeon_connector->devices & ATOM_DEVICE_DFP1_SUPPORT)) { | ||
| 1088 | if (connected) { | ||
| 1089 | DRM_DEBUG("DFP1 connected\n"); | ||
| 1090 | bios_0_scratch |= ATOM_S0_DFP1; | ||
| 1091 | bios_3_scratch |= ATOM_S3_DFP1_ACTIVE; | ||
| 1092 | bios_6_scratch |= ATOM_S6_ACC_REQ_DFP1; | ||
| 1093 | } else { | ||
| 1094 | DRM_DEBUG("DFP1 disconnected\n"); | ||
| 1095 | bios_0_scratch &= ~ATOM_S0_DFP1; | ||
| 1096 | bios_3_scratch &= ~ATOM_S3_DFP1_ACTIVE; | ||
| 1097 | bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP1; | ||
| 1098 | } | ||
| 1099 | } | ||
| 1100 | if ((radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) && | ||
| 1101 | (radeon_connector->devices & ATOM_DEVICE_DFP2_SUPPORT)) { | ||
| 1102 | if (connected) { | ||
| 1103 | DRM_DEBUG("DFP2 connected\n"); | ||
| 1104 | bios_0_scratch |= ATOM_S0_DFP2; | ||
| 1105 | bios_3_scratch |= ATOM_S3_DFP2_ACTIVE; | ||
| 1106 | bios_6_scratch |= ATOM_S6_ACC_REQ_DFP2; | ||
| 1107 | } else { | ||
| 1108 | DRM_DEBUG("DFP2 disconnected\n"); | ||
| 1109 | bios_0_scratch &= ~ATOM_S0_DFP2; | ||
| 1110 | bios_3_scratch &= ~ATOM_S3_DFP2_ACTIVE; | ||
| 1111 | bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP2; | ||
| 1112 | } | ||
| 1113 | } | ||
| 1114 | if ((radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) && | ||
| 1115 | (radeon_connector->devices & ATOM_DEVICE_DFP3_SUPPORT)) { | ||
| 1116 | if (connected) { | ||
| 1117 | DRM_DEBUG("DFP3 connected\n"); | ||
| 1118 | bios_0_scratch |= ATOM_S0_DFP3; | ||
| 1119 | bios_3_scratch |= ATOM_S3_DFP3_ACTIVE; | ||
| 1120 | bios_6_scratch |= ATOM_S6_ACC_REQ_DFP3; | ||
| 1121 | } else { | ||
| 1122 | DRM_DEBUG("DFP3 disconnected\n"); | ||
| 1123 | bios_0_scratch &= ~ATOM_S0_DFP3; | ||
| 1124 | bios_3_scratch &= ~ATOM_S3_DFP3_ACTIVE; | ||
| 1125 | bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP3; | ||
| 1126 | } | ||
| 1127 | } | ||
| 1128 | if ((radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) && | ||
| 1129 | (radeon_connector->devices & ATOM_DEVICE_DFP4_SUPPORT)) { | ||
| 1130 | if (connected) { | ||
| 1131 | DRM_DEBUG("DFP4 connected\n"); | ||
| 1132 | bios_0_scratch |= ATOM_S0_DFP4; | ||
| 1133 | bios_3_scratch |= ATOM_S3_DFP4_ACTIVE; | ||
| 1134 | bios_6_scratch |= ATOM_S6_ACC_REQ_DFP4; | ||
| 1135 | } else { | ||
| 1136 | DRM_DEBUG("DFP4 disconnected\n"); | ||
| 1137 | bios_0_scratch &= ~ATOM_S0_DFP4; | ||
| 1138 | bios_3_scratch &= ~ATOM_S3_DFP4_ACTIVE; | ||
| 1139 | bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP4; | ||
| 1140 | } | ||
| 1141 | } | ||
| 1142 | if ((radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) && | ||
| 1143 | (radeon_connector->devices & ATOM_DEVICE_DFP5_SUPPORT)) { | ||
| 1144 | if (connected) { | ||
| 1145 | DRM_DEBUG("DFP5 connected\n"); | ||
| 1146 | bios_0_scratch |= ATOM_S0_DFP5; | ||
| 1147 | bios_3_scratch |= ATOM_S3_DFP5_ACTIVE; | ||
| 1148 | bios_6_scratch |= ATOM_S6_ACC_REQ_DFP5; | ||
| 1149 | } else { | ||
| 1150 | DRM_DEBUG("DFP5 disconnected\n"); | ||
| 1151 | bios_0_scratch &= ~ATOM_S0_DFP5; | ||
| 1152 | bios_3_scratch &= ~ATOM_S3_DFP5_ACTIVE; | ||
| 1153 | bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP5; | ||
| 1154 | } | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | if (rdev->family >= CHIP_R600) { | ||
| 1158 | WREG32(R600_BIOS_0_SCRATCH, bios_0_scratch); | ||
| 1159 | WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch); | ||
| 1160 | WREG32(R600_BIOS_6_SCRATCH, bios_6_scratch); | ||
| 1161 | } else { | ||
| 1162 | WREG32(RADEON_BIOS_0_SCRATCH, bios_0_scratch); | ||
| 1163 | WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch); | ||
| 1164 | WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch); | ||
| 1165 | } | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | void | ||
| 1169 | radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc) | ||
| 1170 | { | ||
| 1171 | struct drm_device *dev = encoder->dev; | ||
| 1172 | struct radeon_device *rdev = dev->dev_private; | ||
| 1173 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 1174 | uint32_t bios_3_scratch; | ||
| 1175 | |||
| 1176 | if (rdev->family >= CHIP_R600) | ||
| 1177 | bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH); | ||
| 1178 | else | ||
| 1179 | bios_3_scratch = RREG32(RADEON_BIOS_3_SCRATCH); | ||
| 1180 | |||
| 1181 | if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) { | ||
| 1182 | bios_3_scratch &= ~ATOM_S3_TV1_CRTC_ACTIVE; | ||
| 1183 | bios_3_scratch |= (crtc << 18); | ||
| 1184 | } | ||
| 1185 | if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) { | ||
| 1186 | bios_3_scratch &= ~ATOM_S3_CV_CRTC_ACTIVE; | ||
| 1187 | bios_3_scratch |= (crtc << 24); | ||
| 1188 | } | ||
| 1189 | if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) { | ||
| 1190 | bios_3_scratch &= ~ATOM_S3_CRT1_CRTC_ACTIVE; | ||
| 1191 | bios_3_scratch |= (crtc << 16); | ||
| 1192 | } | ||
| 1193 | if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) { | ||
| 1194 | bios_3_scratch &= ~ATOM_S3_CRT2_CRTC_ACTIVE; | ||
| 1195 | bios_3_scratch |= (crtc << 20); | ||
| 1196 | } | ||
| 1197 | if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) { | ||
| 1198 | bios_3_scratch &= ~ATOM_S3_LCD1_CRTC_ACTIVE; | ||
| 1199 | bios_3_scratch |= (crtc << 17); | ||
| 1200 | } | ||
| 1201 | if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) { | ||
| 1202 | bios_3_scratch &= ~ATOM_S3_DFP1_CRTC_ACTIVE; | ||
| 1203 | bios_3_scratch |= (crtc << 19); | ||
| 1204 | } | ||
| 1205 | if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) { | ||
| 1206 | bios_3_scratch &= ~ATOM_S3_DFP2_CRTC_ACTIVE; | ||
| 1207 | bios_3_scratch |= (crtc << 23); | ||
| 1208 | } | ||
| 1209 | if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) { | ||
| 1210 | bios_3_scratch &= ~ATOM_S3_DFP3_CRTC_ACTIVE; | ||
| 1211 | bios_3_scratch |= (crtc << 25); | ||
| 1212 | } | ||
| 1213 | |||
| 1214 | if (rdev->family >= CHIP_R600) | ||
| 1215 | WREG32(R600_BIOS_3_SCRATCH, bios_3_scratch); | ||
| 1216 | else | ||
| 1217 | WREG32(RADEON_BIOS_3_SCRATCH, bios_3_scratch); | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | void | ||
| 1221 | radeon_atombios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on) | ||
| 1222 | { | ||
| 1223 | struct drm_device *dev = encoder->dev; | ||
| 1224 | struct radeon_device *rdev = dev->dev_private; | ||
| 1225 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 1226 | uint32_t bios_2_scratch; | ||
| 1227 | |||
| 1228 | if (rdev->family >= CHIP_R600) | ||
| 1229 | bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH); | ||
| 1230 | else | ||
| 1231 | bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH); | ||
| 1232 | |||
| 1233 | if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) { | ||
| 1234 | if (on) | ||
| 1235 | bios_2_scratch &= ~ATOM_S2_TV1_DPMS_STATE; | ||
| 1236 | else | ||
| 1237 | bios_2_scratch |= ATOM_S2_TV1_DPMS_STATE; | ||
| 1238 | } | ||
| 1239 | if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) { | ||
| 1240 | if (on) | ||
| 1241 | bios_2_scratch &= ~ATOM_S2_CV_DPMS_STATE; | ||
| 1242 | else | ||
| 1243 | bios_2_scratch |= ATOM_S2_CV_DPMS_STATE; | ||
| 1244 | } | ||
| 1245 | if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) { | ||
| 1246 | if (on) | ||
| 1247 | bios_2_scratch &= ~ATOM_S2_CRT1_DPMS_STATE; | ||
| 1248 | else | ||
| 1249 | bios_2_scratch |= ATOM_S2_CRT1_DPMS_STATE; | ||
| 1250 | } | ||
| 1251 | if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) { | ||
| 1252 | if (on) | ||
| 1253 | bios_2_scratch &= ~ATOM_S2_CRT2_DPMS_STATE; | ||
| 1254 | else | ||
| 1255 | bios_2_scratch |= ATOM_S2_CRT2_DPMS_STATE; | ||
| 1256 | } | ||
| 1257 | if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) { | ||
| 1258 | if (on) | ||
| 1259 | bios_2_scratch &= ~ATOM_S2_LCD1_DPMS_STATE; | ||
| 1260 | else | ||
| 1261 | bios_2_scratch |= ATOM_S2_LCD1_DPMS_STATE; | ||
| 1262 | } | ||
| 1263 | if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) { | ||
| 1264 | if (on) | ||
| 1265 | bios_2_scratch &= ~ATOM_S2_DFP1_DPMS_STATE; | ||
| 1266 | else | ||
| 1267 | bios_2_scratch |= ATOM_S2_DFP1_DPMS_STATE; | ||
| 1268 | } | ||
| 1269 | if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) { | ||
| 1270 | if (on) | ||
| 1271 | bios_2_scratch &= ~ATOM_S2_DFP2_DPMS_STATE; | ||
| 1272 | else | ||
| 1273 | bios_2_scratch |= ATOM_S2_DFP2_DPMS_STATE; | ||
| 1274 | } | ||
| 1275 | if (radeon_encoder->devices & ATOM_DEVICE_DFP3_SUPPORT) { | ||
| 1276 | if (on) | ||
| 1277 | bios_2_scratch &= ~ATOM_S2_DFP3_DPMS_STATE; | ||
| 1278 | else | ||
| 1279 | bios_2_scratch |= ATOM_S2_DFP3_DPMS_STATE; | ||
| 1280 | } | ||
| 1281 | if (radeon_encoder->devices & ATOM_DEVICE_DFP4_SUPPORT) { | ||
| 1282 | if (on) | ||
| 1283 | bios_2_scratch &= ~ATOM_S2_DFP4_DPMS_STATE; | ||
| 1284 | else | ||
| 1285 | bios_2_scratch |= ATOM_S2_DFP4_DPMS_STATE; | ||
| 1286 | } | ||
| 1287 | if (radeon_encoder->devices & ATOM_DEVICE_DFP5_SUPPORT) { | ||
| 1288 | if (on) | ||
| 1289 | bios_2_scratch &= ~ATOM_S2_DFP5_DPMS_STATE; | ||
| 1290 | else | ||
| 1291 | bios_2_scratch |= ATOM_S2_DFP5_DPMS_STATE; | ||
| 1292 | } | ||
| 1293 | |||
| 1294 | if (rdev->family >= CHIP_R600) | ||
| 1295 | WREG32(R600_BIOS_2_SCRATCH, bios_2_scratch); | ||
| 1296 | else | ||
| 1297 | WREG32(RADEON_BIOS_2_SCRATCH, bios_2_scratch); | ||
| 1298 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c new file mode 100644 index 000000000000..c44403a2ca76 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_benchmark.c | |||
| @@ -0,0 +1,133 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2009 Jerome Glisse. | ||
| 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: Jerome Glisse | ||
| 23 | */ | ||
| 24 | #include <drm/drmP.h> | ||
| 25 | #include <drm/radeon_drm.h> | ||
| 26 | #include "radeon_reg.h" | ||
| 27 | #include "radeon.h" | ||
| 28 | |||
| 29 | void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize, | ||
| 30 | unsigned sdomain, unsigned ddomain) | ||
| 31 | { | ||
| 32 | struct radeon_object *dobj = NULL; | ||
| 33 | struct radeon_object *sobj = NULL; | ||
| 34 | struct radeon_fence *fence = NULL; | ||
| 35 | uint64_t saddr, daddr; | ||
| 36 | unsigned long start_jiffies; | ||
| 37 | unsigned long end_jiffies; | ||
| 38 | unsigned long time; | ||
| 39 | unsigned i, n, size; | ||
| 40 | int r; | ||
| 41 | |||
| 42 | size = bsize; | ||
| 43 | n = 1024; | ||
| 44 | r = radeon_object_create(rdev, NULL, size, true, sdomain, false, &sobj); | ||
| 45 | if (r) { | ||
| 46 | goto out_cleanup; | ||
| 47 | } | ||
| 48 | r = radeon_object_pin(sobj, sdomain, &saddr); | ||
| 49 | if (r) { | ||
| 50 | goto out_cleanup; | ||
| 51 | } | ||
| 52 | r = radeon_object_create(rdev, NULL, size, true, ddomain, false, &dobj); | ||
| 53 | if (r) { | ||
| 54 | goto out_cleanup; | ||
| 55 | } | ||
| 56 | r = radeon_object_pin(dobj, ddomain, &daddr); | ||
| 57 | if (r) { | ||
| 58 | goto out_cleanup; | ||
| 59 | } | ||
| 60 | start_jiffies = jiffies; | ||
| 61 | for (i = 0; i < n; i++) { | ||
| 62 | r = radeon_fence_create(rdev, &fence); | ||
| 63 | if (r) { | ||
| 64 | goto out_cleanup; | ||
| 65 | } | ||
| 66 | r = radeon_copy_dma(rdev, saddr, daddr, size >> 14, fence); | ||
| 67 | if (r) { | ||
| 68 | goto out_cleanup; | ||
| 69 | } | ||
| 70 | r = radeon_fence_wait(fence, false); | ||
| 71 | if (r) { | ||
| 72 | goto out_cleanup; | ||
| 73 | } | ||
| 74 | radeon_fence_unref(&fence); | ||
| 75 | } | ||
| 76 | end_jiffies = jiffies; | ||
| 77 | time = end_jiffies - start_jiffies; | ||
| 78 | time = jiffies_to_msecs(time); | ||
| 79 | if (time > 0) { | ||
| 80 | i = ((n * size) >> 10) / time; | ||
| 81 | printk(KERN_INFO "radeon: dma %u bo moves of %ukb from %d to %d" | ||
| 82 | " in %lums (%ukb/ms %ukb/s %uM/s)\n", n, size >> 10, | ||
| 83 | sdomain, ddomain, time, i, i * 1000, (i * 1000) / 1024); | ||
| 84 | } | ||
| 85 | start_jiffies = jiffies; | ||
| 86 | for (i = 0; i < n; i++) { | ||
| 87 | r = radeon_fence_create(rdev, &fence); | ||
| 88 | if (r) { | ||
| 89 | goto out_cleanup; | ||
| 90 | } | ||
| 91 | r = radeon_copy_blit(rdev, saddr, daddr, size >> 14, fence); | ||
| 92 | if (r) { | ||
| 93 | goto out_cleanup; | ||
| 94 | } | ||
| 95 | r = radeon_fence_wait(fence, false); | ||
| 96 | if (r) { | ||
| 97 | goto out_cleanup; | ||
| 98 | } | ||
| 99 | radeon_fence_unref(&fence); | ||
| 100 | } | ||
| 101 | end_jiffies = jiffies; | ||
| 102 | time = end_jiffies - start_jiffies; | ||
| 103 | time = jiffies_to_msecs(time); | ||
| 104 | if (time > 0) { | ||
| 105 | i = ((n * size) >> 10) / time; | ||
| 106 | printk(KERN_INFO "radeon: blit %u bo moves of %ukb from %d to %d" | ||
| 107 | " in %lums (%ukb/ms %ukb/s %uM/s)\n", n, size >> 10, | ||
| 108 | sdomain, ddomain, time, i, i * 1000, (i * 1000) / 1024); | ||
| 109 | } | ||
| 110 | out_cleanup: | ||
| 111 | if (sobj) { | ||
| 112 | radeon_object_unpin(sobj); | ||
| 113 | radeon_object_unref(&sobj); | ||
| 114 | } | ||
| 115 | if (dobj) { | ||
| 116 | radeon_object_unpin(dobj); | ||
| 117 | radeon_object_unref(&dobj); | ||
| 118 | } | ||
| 119 | if (fence) { | ||
| 120 | radeon_fence_unref(&fence); | ||
| 121 | } | ||
| 122 | if (r) { | ||
| 123 | printk(KERN_WARNING "Error while benchmarking BO move.\n"); | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | void radeon_benchmark(struct radeon_device *rdev) | ||
| 128 | { | ||
| 129 | radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_GTT, | ||
| 130 | RADEON_GEM_DOMAIN_VRAM); | ||
| 131 | radeon_benchmark_move(rdev, 1024*1024, RADEON_GEM_DOMAIN_VRAM, | ||
| 132 | RADEON_GEM_DOMAIN_GTT); | ||
| 133 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c new file mode 100644 index 000000000000..96e37a6e7ce4 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_bios.c | |||
| @@ -0,0 +1,390 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include "drmP.h" | ||
| 29 | #include "radeon_reg.h" | ||
| 30 | #include "radeon.h" | ||
| 31 | #include "atom.h" | ||
| 32 | |||
| 33 | /* | ||
| 34 | * BIOS. | ||
| 35 | */ | ||
| 36 | static bool radeon_read_bios(struct radeon_device *rdev) | ||
| 37 | { | ||
| 38 | uint8_t __iomem *bios; | ||
| 39 | size_t size; | ||
| 40 | |||
| 41 | rdev->bios = NULL; | ||
| 42 | bios = pci_map_rom(rdev->pdev, &size); | ||
| 43 | if (!bios) { | ||
| 44 | return false; | ||
| 45 | } | ||
| 46 | |||
| 47 | if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { | ||
| 48 | pci_unmap_rom(rdev->pdev, bios); | ||
| 49 | return false; | ||
| 50 | } | ||
| 51 | rdev->bios = kmalloc(size, GFP_KERNEL); | ||
| 52 | if (rdev->bios == NULL) { | ||
| 53 | pci_unmap_rom(rdev->pdev, bios); | ||
| 54 | return false; | ||
| 55 | } | ||
| 56 | memcpy(rdev->bios, bios, size); | ||
| 57 | pci_unmap_rom(rdev->pdev, bios); | ||
| 58 | return true; | ||
| 59 | } | ||
| 60 | |||
| 61 | static bool r700_read_disabled_bios(struct radeon_device *rdev) | ||
| 62 | { | ||
| 63 | uint32_t viph_control; | ||
| 64 | uint32_t bus_cntl; | ||
| 65 | uint32_t d1vga_control; | ||
| 66 | uint32_t d2vga_control; | ||
| 67 | uint32_t vga_render_control; | ||
| 68 | uint32_t rom_cntl; | ||
| 69 | uint32_t cg_spll_func_cntl = 0; | ||
| 70 | uint32_t cg_spll_status; | ||
| 71 | bool r; | ||
| 72 | |||
| 73 | viph_control = RREG32(RADEON_VIPH_CONTROL); | ||
| 74 | bus_cntl = RREG32(RADEON_BUS_CNTL); | ||
| 75 | d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); | ||
| 76 | d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); | ||
| 77 | vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); | ||
| 78 | rom_cntl = RREG32(R600_ROM_CNTL); | ||
| 79 | |||
| 80 | /* disable VIP */ | ||
| 81 | WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); | ||
| 82 | /* enable the rom */ | ||
| 83 | WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); | ||
| 84 | /* Disable VGA mode */ | ||
| 85 | WREG32(AVIVO_D1VGA_CONTROL, | ||
| 86 | (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | | ||
| 87 | AVIVO_DVGA_CONTROL_TIMING_SELECT))); | ||
| 88 | WREG32(AVIVO_D2VGA_CONTROL, | ||
| 89 | (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | | ||
| 90 | AVIVO_DVGA_CONTROL_TIMING_SELECT))); | ||
| 91 | WREG32(AVIVO_VGA_RENDER_CONTROL, | ||
| 92 | (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); | ||
| 93 | |||
| 94 | if (rdev->family == CHIP_RV730) { | ||
| 95 | cg_spll_func_cntl = RREG32(R600_CG_SPLL_FUNC_CNTL); | ||
| 96 | |||
| 97 | /* enable bypass mode */ | ||
| 98 | WREG32(R600_CG_SPLL_FUNC_CNTL, (cg_spll_func_cntl | | ||
| 99 | R600_SPLL_BYPASS_EN)); | ||
| 100 | |||
| 101 | /* wait for SPLL_CHG_STATUS to change to 1 */ | ||
| 102 | cg_spll_status = 0; | ||
| 103 | while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) | ||
| 104 | cg_spll_status = RREG32(R600_CG_SPLL_STATUS); | ||
| 105 | |||
| 106 | WREG32(R600_ROM_CNTL, (rom_cntl & ~R600_SCK_OVERWRITE)); | ||
| 107 | } else | ||
| 108 | WREG32(R600_ROM_CNTL, (rom_cntl | R600_SCK_OVERWRITE)); | ||
| 109 | |||
| 110 | r = radeon_read_bios(rdev); | ||
| 111 | |||
| 112 | /* restore regs */ | ||
| 113 | if (rdev->family == CHIP_RV730) { | ||
| 114 | WREG32(R600_CG_SPLL_FUNC_CNTL, cg_spll_func_cntl); | ||
| 115 | |||
| 116 | /* wait for SPLL_CHG_STATUS to change to 1 */ | ||
| 117 | cg_spll_status = 0; | ||
| 118 | while (!(cg_spll_status & R600_SPLL_CHG_STATUS)) | ||
| 119 | cg_spll_status = RREG32(R600_CG_SPLL_STATUS); | ||
| 120 | } | ||
| 121 | WREG32(RADEON_VIPH_CONTROL, viph_control); | ||
| 122 | WREG32(RADEON_BUS_CNTL, bus_cntl); | ||
| 123 | WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); | ||
| 124 | WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); | ||
| 125 | WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); | ||
| 126 | WREG32(R600_ROM_CNTL, rom_cntl); | ||
| 127 | return r; | ||
| 128 | } | ||
| 129 | |||
| 130 | static bool r600_read_disabled_bios(struct radeon_device *rdev) | ||
| 131 | { | ||
| 132 | uint32_t viph_control; | ||
| 133 | uint32_t bus_cntl; | ||
| 134 | uint32_t d1vga_control; | ||
| 135 | uint32_t d2vga_control; | ||
| 136 | uint32_t vga_render_control; | ||
| 137 | uint32_t rom_cntl; | ||
| 138 | uint32_t general_pwrmgt; | ||
| 139 | uint32_t low_vid_lower_gpio_cntl; | ||
| 140 | uint32_t medium_vid_lower_gpio_cntl; | ||
| 141 | uint32_t high_vid_lower_gpio_cntl; | ||
| 142 | uint32_t ctxsw_vid_lower_gpio_cntl; | ||
| 143 | uint32_t lower_gpio_enable; | ||
| 144 | bool r; | ||
| 145 | |||
| 146 | viph_control = RREG32(RADEON_VIPH_CONTROL); | ||
| 147 | bus_cntl = RREG32(RADEON_BUS_CNTL); | ||
| 148 | d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); | ||
| 149 | d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); | ||
| 150 | vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); | ||
| 151 | rom_cntl = RREG32(R600_ROM_CNTL); | ||
| 152 | general_pwrmgt = RREG32(R600_GENERAL_PWRMGT); | ||
| 153 | low_vid_lower_gpio_cntl = RREG32(R600_LOW_VID_LOWER_GPIO_CNTL); | ||
| 154 | medium_vid_lower_gpio_cntl = RREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL); | ||
| 155 | high_vid_lower_gpio_cntl = RREG32(R600_HIGH_VID_LOWER_GPIO_CNTL); | ||
| 156 | ctxsw_vid_lower_gpio_cntl = RREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL); | ||
| 157 | lower_gpio_enable = RREG32(R600_LOWER_GPIO_ENABLE); | ||
| 158 | |||
| 159 | /* disable VIP */ | ||
| 160 | WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); | ||
| 161 | /* enable the rom */ | ||
| 162 | WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); | ||
| 163 | /* Disable VGA mode */ | ||
| 164 | WREG32(AVIVO_D1VGA_CONTROL, | ||
| 165 | (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | | ||
| 166 | AVIVO_DVGA_CONTROL_TIMING_SELECT))); | ||
| 167 | WREG32(AVIVO_D2VGA_CONTROL, | ||
| 168 | (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | | ||
| 169 | AVIVO_DVGA_CONTROL_TIMING_SELECT))); | ||
| 170 | WREG32(AVIVO_VGA_RENDER_CONTROL, | ||
| 171 | (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); | ||
| 172 | |||
| 173 | WREG32(R600_ROM_CNTL, | ||
| 174 | ((rom_cntl & ~R600_SCK_PRESCALE_CRYSTAL_CLK_MASK) | | ||
| 175 | (1 << R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT) | | ||
| 176 | R600_SCK_OVERWRITE)); | ||
| 177 | |||
| 178 | WREG32(R600_GENERAL_PWRMGT, (general_pwrmgt & ~R600_OPEN_DRAIN_PADS)); | ||
| 179 | WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, | ||
| 180 | (low_vid_lower_gpio_cntl & ~0x400)); | ||
| 181 | WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, | ||
| 182 | (medium_vid_lower_gpio_cntl & ~0x400)); | ||
| 183 | WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, | ||
| 184 | (high_vid_lower_gpio_cntl & ~0x400)); | ||
| 185 | WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, | ||
| 186 | (ctxsw_vid_lower_gpio_cntl & ~0x400)); | ||
| 187 | WREG32(R600_LOWER_GPIO_ENABLE, (lower_gpio_enable | 0x400)); | ||
| 188 | |||
| 189 | r = radeon_read_bios(rdev); | ||
| 190 | |||
| 191 | /* restore regs */ | ||
| 192 | WREG32(RADEON_VIPH_CONTROL, viph_control); | ||
| 193 | WREG32(RADEON_BUS_CNTL, bus_cntl); | ||
| 194 | WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); | ||
| 195 | WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); | ||
| 196 | WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); | ||
| 197 | WREG32(R600_ROM_CNTL, rom_cntl); | ||
| 198 | WREG32(R600_GENERAL_PWRMGT, general_pwrmgt); | ||
| 199 | WREG32(R600_LOW_VID_LOWER_GPIO_CNTL, low_vid_lower_gpio_cntl); | ||
| 200 | WREG32(R600_MEDIUM_VID_LOWER_GPIO_CNTL, medium_vid_lower_gpio_cntl); | ||
| 201 | WREG32(R600_HIGH_VID_LOWER_GPIO_CNTL, high_vid_lower_gpio_cntl); | ||
| 202 | WREG32(R600_CTXSW_VID_LOWER_GPIO_CNTL, ctxsw_vid_lower_gpio_cntl); | ||
| 203 | WREG32(R600_LOWER_GPIO_ENABLE, lower_gpio_enable); | ||
| 204 | return r; | ||
| 205 | } | ||
| 206 | |||
| 207 | static bool avivo_read_disabled_bios(struct radeon_device *rdev) | ||
| 208 | { | ||
| 209 | uint32_t seprom_cntl1; | ||
| 210 | uint32_t viph_control; | ||
| 211 | uint32_t bus_cntl; | ||
| 212 | uint32_t d1vga_control; | ||
| 213 | uint32_t d2vga_control; | ||
| 214 | uint32_t vga_render_control; | ||
| 215 | uint32_t gpiopad_a; | ||
| 216 | uint32_t gpiopad_en; | ||
| 217 | uint32_t gpiopad_mask; | ||
| 218 | bool r; | ||
| 219 | |||
| 220 | seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1); | ||
| 221 | viph_control = RREG32(RADEON_VIPH_CONTROL); | ||
| 222 | bus_cntl = RREG32(RADEON_BUS_CNTL); | ||
| 223 | d1vga_control = RREG32(AVIVO_D1VGA_CONTROL); | ||
| 224 | d2vga_control = RREG32(AVIVO_D2VGA_CONTROL); | ||
| 225 | vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); | ||
| 226 | gpiopad_a = RREG32(RADEON_GPIOPAD_A); | ||
| 227 | gpiopad_en = RREG32(RADEON_GPIOPAD_EN); | ||
| 228 | gpiopad_mask = RREG32(RADEON_GPIOPAD_MASK); | ||
| 229 | |||
| 230 | WREG32(RADEON_SEPROM_CNTL1, | ||
| 231 | ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | | ||
| 232 | (0xc << RADEON_SCK_PRESCALE_SHIFT))); | ||
| 233 | WREG32(RADEON_GPIOPAD_A, 0); | ||
| 234 | WREG32(RADEON_GPIOPAD_EN, 0); | ||
| 235 | WREG32(RADEON_GPIOPAD_MASK, 0); | ||
| 236 | |||
| 237 | /* disable VIP */ | ||
| 238 | WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); | ||
| 239 | |||
| 240 | /* enable the rom */ | ||
| 241 | WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); | ||
| 242 | |||
| 243 | /* Disable VGA mode */ | ||
| 244 | WREG32(AVIVO_D1VGA_CONTROL, | ||
| 245 | (d1vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | | ||
| 246 | AVIVO_DVGA_CONTROL_TIMING_SELECT))); | ||
| 247 | WREG32(AVIVO_D2VGA_CONTROL, | ||
| 248 | (d2vga_control & ~(AVIVO_DVGA_CONTROL_MODE_ENABLE | | ||
| 249 | AVIVO_DVGA_CONTROL_TIMING_SELECT))); | ||
| 250 | WREG32(AVIVO_VGA_RENDER_CONTROL, | ||
| 251 | (vga_render_control & ~AVIVO_VGA_VSTATUS_CNTL_MASK)); | ||
| 252 | |||
| 253 | r = radeon_read_bios(rdev); | ||
| 254 | |||
| 255 | /* restore regs */ | ||
| 256 | WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1); | ||
| 257 | WREG32(RADEON_VIPH_CONTROL, viph_control); | ||
| 258 | WREG32(RADEON_BUS_CNTL, bus_cntl); | ||
| 259 | WREG32(AVIVO_D1VGA_CONTROL, d1vga_control); | ||
| 260 | WREG32(AVIVO_D2VGA_CONTROL, d2vga_control); | ||
| 261 | WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); | ||
| 262 | WREG32(RADEON_GPIOPAD_A, gpiopad_a); | ||
| 263 | WREG32(RADEON_GPIOPAD_EN, gpiopad_en); | ||
| 264 | WREG32(RADEON_GPIOPAD_MASK, gpiopad_mask); | ||
| 265 | return r; | ||
| 266 | } | ||
| 267 | |||
| 268 | static bool legacy_read_disabled_bios(struct radeon_device *rdev) | ||
| 269 | { | ||
| 270 | uint32_t seprom_cntl1; | ||
| 271 | uint32_t viph_control; | ||
| 272 | uint32_t bus_cntl; | ||
| 273 | uint32_t crtc_gen_cntl; | ||
| 274 | uint32_t crtc2_gen_cntl; | ||
| 275 | uint32_t crtc_ext_cntl; | ||
| 276 | uint32_t fp2_gen_cntl; | ||
| 277 | bool r; | ||
| 278 | |||
| 279 | seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1); | ||
| 280 | viph_control = RREG32(RADEON_VIPH_CONTROL); | ||
| 281 | bus_cntl = RREG32(RADEON_BUS_CNTL); | ||
| 282 | crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL); | ||
| 283 | crtc2_gen_cntl = 0; | ||
| 284 | crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); | ||
| 285 | fp2_gen_cntl = 0; | ||
| 286 | |||
| 287 | if (rdev->ddev->pci_device == PCI_DEVICE_ID_ATI_RADEON_QY) { | ||
| 288 | fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); | ||
| 289 | } | ||
| 290 | |||
| 291 | if (!(rdev->flags & RADEON_SINGLE_CRTC)) { | ||
| 292 | crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); | ||
| 293 | } | ||
| 294 | |||
| 295 | WREG32(RADEON_SEPROM_CNTL1, | ||
| 296 | ((seprom_cntl1 & ~RADEON_SCK_PRESCALE_MASK) | | ||
| 297 | (0xc << RADEON_SCK_PRESCALE_SHIFT))); | ||
| 298 | |||
| 299 | /* disable VIP */ | ||
| 300 | WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN)); | ||
| 301 | |||
| 302 | /* enable the rom */ | ||
| 303 | WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); | ||
| 304 | |||
| 305 | /* Turn off mem requests and CRTC for both controllers */ | ||
| 306 | WREG32(RADEON_CRTC_GEN_CNTL, | ||
| 307 | ((crtc_gen_cntl & ~RADEON_CRTC_EN) | | ||
| 308 | (RADEON_CRTC_DISP_REQ_EN_B | | ||
| 309 | RADEON_CRTC_EXT_DISP_EN))); | ||
| 310 | if (!(rdev->flags & RADEON_SINGLE_CRTC)) { | ||
| 311 | WREG32(RADEON_CRTC2_GEN_CNTL, | ||
| 312 | ((crtc2_gen_cntl & ~RADEON_CRTC2_EN) | | ||
| 313 | RADEON_CRTC2_DISP_REQ_EN_B)); | ||
| 314 | } | ||
| 315 | /* Turn off CRTC */ | ||
| 316 | WREG32(RADEON_CRTC_EXT_CNTL, | ||
| 317 | ((crtc_ext_cntl & ~RADEON_CRTC_CRT_ON) | | ||
| 318 | (RADEON_CRTC_SYNC_TRISTAT | | ||
| 319 | RADEON_CRTC_DISPLAY_DIS))); | ||
| 320 | |||
| 321 | if (rdev->ddev->pci_device == PCI_DEVICE_ID_ATI_RADEON_QY) { | ||
| 322 | WREG32(RADEON_FP2_GEN_CNTL, (fp2_gen_cntl & ~RADEON_FP2_ON)); | ||
| 323 | } | ||
| 324 | |||
| 325 | r = radeon_read_bios(rdev); | ||
| 326 | |||
| 327 | /* restore regs */ | ||
| 328 | WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1); | ||
| 329 | WREG32(RADEON_VIPH_CONTROL, viph_control); | ||
| 330 | WREG32(RADEON_BUS_CNTL, bus_cntl); | ||
| 331 | WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); | ||
| 332 | if (!(rdev->flags & RADEON_SINGLE_CRTC)) { | ||
| 333 | WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); | ||
| 334 | } | ||
| 335 | WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); | ||
| 336 | if (rdev->ddev->pci_device == PCI_DEVICE_ID_ATI_RADEON_QY) { | ||
| 337 | WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); | ||
| 338 | } | ||
| 339 | return r; | ||
| 340 | } | ||
| 341 | |||
| 342 | static bool radeon_read_disabled_bios(struct radeon_device *rdev) | ||
| 343 | { | ||
| 344 | if (rdev->family >= CHIP_RV770) | ||
| 345 | return r700_read_disabled_bios(rdev); | ||
| 346 | else if (rdev->family >= CHIP_R600) | ||
| 347 | return r600_read_disabled_bios(rdev); | ||
| 348 | else if (rdev->family >= CHIP_RS600) | ||
| 349 | return avivo_read_disabled_bios(rdev); | ||
| 350 | else | ||
| 351 | return legacy_read_disabled_bios(rdev); | ||
| 352 | } | ||
| 353 | |||
| 354 | bool radeon_get_bios(struct radeon_device *rdev) | ||
| 355 | { | ||
| 356 | bool r; | ||
| 357 | uint16_t tmp; | ||
| 358 | |||
| 359 | r = radeon_read_bios(rdev); | ||
| 360 | if (r == false) { | ||
| 361 | r = radeon_read_disabled_bios(rdev); | ||
| 362 | } | ||
| 363 | if (r == false || rdev->bios == NULL) { | ||
| 364 | DRM_ERROR("Unable to locate a BIOS ROM\n"); | ||
| 365 | rdev->bios = NULL; | ||
| 366 | return false; | ||
| 367 | } | ||
| 368 | if (rdev->bios[0] != 0x55 || rdev->bios[1] != 0xaa) { | ||
| 369 | goto free_bios; | ||
| 370 | } | ||
| 371 | |||
| 372 | rdev->bios_header_start = RBIOS16(0x48); | ||
| 373 | if (!rdev->bios_header_start) { | ||
| 374 | goto free_bios; | ||
| 375 | } | ||
| 376 | tmp = rdev->bios_header_start + 4; | ||
| 377 | if (!memcmp(rdev->bios + tmp, "ATOM", 4) || | ||
| 378 | !memcmp(rdev->bios + tmp, "MOTA", 4)) { | ||
| 379 | rdev->is_atom_bios = true; | ||
| 380 | } else { | ||
| 381 | rdev->is_atom_bios = false; | ||
| 382 | } | ||
| 383 | |||
| 384 | DRM_DEBUG("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM"); | ||
| 385 | return true; | ||
| 386 | free_bios: | ||
| 387 | kfree(rdev->bios); | ||
| 388 | rdev->bios = NULL; | ||
| 389 | return false; | ||
| 390 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c new file mode 100644 index 000000000000..a37cbce53181 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_clocks.c | |||
| @@ -0,0 +1,833 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include "drmP.h" | ||
| 29 | #include "radeon_drm.h" | ||
| 30 | #include "radeon_reg.h" | ||
| 31 | #include "radeon.h" | ||
| 32 | #include "atom.h" | ||
| 33 | |||
| 34 | /* 10 khz */ | ||
| 35 | static uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev) | ||
| 36 | { | ||
| 37 | struct radeon_pll *spll = &rdev->clock.spll; | ||
| 38 | uint32_t fb_div, ref_div, post_div, sclk; | ||
| 39 | |||
| 40 | fb_div = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV); | ||
| 41 | fb_div = (fb_div >> RADEON_SPLL_FB_DIV_SHIFT) & RADEON_SPLL_FB_DIV_MASK; | ||
| 42 | fb_div <<= 1; | ||
| 43 | fb_div *= spll->reference_freq; | ||
| 44 | |||
| 45 | ref_div = | ||
| 46 | RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK; | ||
| 47 | sclk = fb_div / ref_div; | ||
| 48 | |||
| 49 | post_div = RREG32_PLL(RADEON_SCLK_CNTL) & RADEON_SCLK_SRC_SEL_MASK; | ||
| 50 | if (post_div == 2) | ||
| 51 | sclk >>= 1; | ||
| 52 | else if (post_div == 3) | ||
| 53 | sclk >>= 2; | ||
| 54 | else if (post_div == 4) | ||
| 55 | sclk >>= 4; | ||
| 56 | |||
| 57 | return sclk; | ||
| 58 | } | ||
| 59 | |||
| 60 | /* 10 khz */ | ||
| 61 | static uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev) | ||
| 62 | { | ||
| 63 | struct radeon_pll *mpll = &rdev->clock.mpll; | ||
| 64 | uint32_t fb_div, ref_div, post_div, mclk; | ||
| 65 | |||
| 66 | fb_div = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV); | ||
| 67 | fb_div = (fb_div >> RADEON_MPLL_FB_DIV_SHIFT) & RADEON_MPLL_FB_DIV_MASK; | ||
| 68 | fb_div <<= 1; | ||
| 69 | fb_div *= mpll->reference_freq; | ||
| 70 | |||
| 71 | ref_div = | ||
| 72 | RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK; | ||
| 73 | mclk = fb_div / ref_div; | ||
| 74 | |||
| 75 | post_div = RREG32_PLL(RADEON_MCLK_CNTL) & 0x7; | ||
| 76 | if (post_div == 2) | ||
| 77 | mclk >>= 1; | ||
| 78 | else if (post_div == 3) | ||
| 79 | mclk >>= 2; | ||
| 80 | else if (post_div == 4) | ||
| 81 | mclk >>= 4; | ||
| 82 | |||
| 83 | return mclk; | ||
| 84 | } | ||
| 85 | |||
| 86 | void radeon_get_clock_info(struct drm_device *dev) | ||
| 87 | { | ||
| 88 | struct radeon_device *rdev = dev->dev_private; | ||
| 89 | struct radeon_pll *p1pll = &rdev->clock.p1pll; | ||
| 90 | struct radeon_pll *p2pll = &rdev->clock.p2pll; | ||
| 91 | struct radeon_pll *spll = &rdev->clock.spll; | ||
| 92 | struct radeon_pll *mpll = &rdev->clock.mpll; | ||
| 93 | int ret; | ||
| 94 | |||
| 95 | if (rdev->is_atom_bios) | ||
| 96 | ret = radeon_atom_get_clock_info(dev); | ||
| 97 | else | ||
| 98 | ret = radeon_combios_get_clock_info(dev); | ||
| 99 | |||
| 100 | if (ret) { | ||
| 101 | if (p1pll->reference_div < 2) | ||
| 102 | p1pll->reference_div = 12; | ||
| 103 | if (p2pll->reference_div < 2) | ||
| 104 | p2pll->reference_div = 12; | ||
| 105 | if (spll->reference_div < 2) | ||
| 106 | spll->reference_div = | ||
| 107 | RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & | ||
| 108 | RADEON_M_SPLL_REF_DIV_MASK; | ||
| 109 | if (mpll->reference_div < 2) | ||
| 110 | mpll->reference_div = spll->reference_div; | ||
| 111 | } else { | ||
| 112 | if (ASIC_IS_AVIVO(rdev)) { | ||
| 113 | /* TODO FALLBACK */ | ||
| 114 | } else { | ||
| 115 | DRM_INFO("Using generic clock info\n"); | ||
| 116 | |||
| 117 | if (rdev->flags & RADEON_IS_IGP) { | ||
| 118 | p1pll->reference_freq = 1432; | ||
| 119 | p2pll->reference_freq = 1432; | ||
| 120 | spll->reference_freq = 1432; | ||
| 121 | mpll->reference_freq = 1432; | ||
| 122 | } else { | ||
| 123 | p1pll->reference_freq = 2700; | ||
| 124 | p2pll->reference_freq = 2700; | ||
| 125 | spll->reference_freq = 2700; | ||
| 126 | mpll->reference_freq = 2700; | ||
| 127 | } | ||
| 128 | p1pll->reference_div = | ||
| 129 | RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff; | ||
| 130 | if (p1pll->reference_div < 2) | ||
| 131 | p1pll->reference_div = 12; | ||
| 132 | p2pll->reference_div = p1pll->reference_div; | ||
| 133 | |||
| 134 | if (rdev->family >= CHIP_R420) { | ||
| 135 | p1pll->pll_in_min = 100; | ||
| 136 | p1pll->pll_in_max = 1350; | ||
| 137 | p1pll->pll_out_min = 20000; | ||
| 138 | p1pll->pll_out_max = 50000; | ||
| 139 | p2pll->pll_in_min = 100; | ||
| 140 | p2pll->pll_in_max = 1350; | ||
| 141 | p2pll->pll_out_min = 20000; | ||
| 142 | p2pll->pll_out_max = 50000; | ||
| 143 | } else { | ||
| 144 | p1pll->pll_in_min = 40; | ||
| 145 | p1pll->pll_in_max = 500; | ||
| 146 | p1pll->pll_out_min = 12500; | ||
| 147 | p1pll->pll_out_max = 35000; | ||
| 148 | p2pll->pll_in_min = 40; | ||
| 149 | p2pll->pll_in_max = 500; | ||
| 150 | p2pll->pll_out_min = 12500; | ||
| 151 | p2pll->pll_out_max = 35000; | ||
| 152 | } | ||
| 153 | |||
| 154 | spll->reference_div = | ||
| 155 | RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & | ||
| 156 | RADEON_M_SPLL_REF_DIV_MASK; | ||
| 157 | mpll->reference_div = spll->reference_div; | ||
| 158 | rdev->clock.default_sclk = | ||
| 159 | radeon_legacy_get_engine_clock(rdev); | ||
| 160 | rdev->clock.default_mclk = | ||
| 161 | radeon_legacy_get_memory_clock(rdev); | ||
| 162 | } | ||
| 163 | } | ||
| 164 | |||
| 165 | /* pixel clocks */ | ||
| 166 | if (ASIC_IS_AVIVO(rdev)) { | ||
| 167 | p1pll->min_post_div = 2; | ||
| 168 | p1pll->max_post_div = 0x7f; | ||
| 169 | p1pll->min_frac_feedback_div = 0; | ||
| 170 | p1pll->max_frac_feedback_div = 9; | ||
| 171 | p2pll->min_post_div = 2; | ||
| 172 | p2pll->max_post_div = 0x7f; | ||
| 173 | p2pll->min_frac_feedback_div = 0; | ||
| 174 | p2pll->max_frac_feedback_div = 9; | ||
| 175 | } else { | ||
| 176 | p1pll->min_post_div = 1; | ||
| 177 | p1pll->max_post_div = 16; | ||
| 178 | p1pll->min_frac_feedback_div = 0; | ||
| 179 | p1pll->max_frac_feedback_div = 0; | ||
| 180 | p2pll->min_post_div = 1; | ||
| 181 | p2pll->max_post_div = 12; | ||
| 182 | p2pll->min_frac_feedback_div = 0; | ||
| 183 | p2pll->max_frac_feedback_div = 0; | ||
| 184 | } | ||
| 185 | |||
| 186 | p1pll->min_ref_div = 2; | ||
| 187 | p1pll->max_ref_div = 0x3ff; | ||
| 188 | p1pll->min_feedback_div = 4; | ||
| 189 | p1pll->max_feedback_div = 0x7ff; | ||
| 190 | p1pll->best_vco = 0; | ||
| 191 | |||
| 192 | p2pll->min_ref_div = 2; | ||
| 193 | p2pll->max_ref_div = 0x3ff; | ||
| 194 | p2pll->min_feedback_div = 4; | ||
| 195 | p2pll->max_feedback_div = 0x7ff; | ||
| 196 | p2pll->best_vco = 0; | ||
| 197 | |||
| 198 | /* system clock */ | ||
| 199 | spll->min_post_div = 1; | ||
| 200 | spll->max_post_div = 1; | ||
| 201 | spll->min_ref_div = 2; | ||
| 202 | spll->max_ref_div = 0xff; | ||
| 203 | spll->min_feedback_div = 4; | ||
| 204 | spll->max_feedback_div = 0xff; | ||
| 205 | spll->best_vco = 0; | ||
| 206 | |||
| 207 | /* memory clock */ | ||
| 208 | mpll->min_post_div = 1; | ||
| 209 | mpll->max_post_div = 1; | ||
| 210 | mpll->min_ref_div = 2; | ||
| 211 | mpll->max_ref_div = 0xff; | ||
| 212 | mpll->min_feedback_div = 4; | ||
| 213 | mpll->max_feedback_div = 0xff; | ||
| 214 | mpll->best_vco = 0; | ||
| 215 | |||
| 216 | } | ||
| 217 | |||
| 218 | /* 10 khz */ | ||
| 219 | static uint32_t calc_eng_mem_clock(struct radeon_device *rdev, | ||
| 220 | uint32_t req_clock, | ||
| 221 | int *fb_div, int *post_div) | ||
| 222 | { | ||
| 223 | struct radeon_pll *spll = &rdev->clock.spll; | ||
| 224 | int ref_div = spll->reference_div; | ||
| 225 | |||
| 226 | if (!ref_div) | ||
| 227 | ref_div = | ||
| 228 | RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & | ||
| 229 | RADEON_M_SPLL_REF_DIV_MASK; | ||
| 230 | |||
| 231 | if (req_clock < 15000) { | ||
| 232 | *post_div = 8; | ||
| 233 | req_clock *= 8; | ||
| 234 | } else if (req_clock < 30000) { | ||
| 235 | *post_div = 4; | ||
| 236 | req_clock *= 4; | ||
| 237 | } else if (req_clock < 60000) { | ||
| 238 | *post_div = 2; | ||
| 239 | req_clock *= 2; | ||
| 240 | } else | ||
| 241 | *post_div = 1; | ||
| 242 | |||
| 243 | req_clock *= ref_div; | ||
| 244 | req_clock += spll->reference_freq; | ||
| 245 | req_clock /= (2 * spll->reference_freq); | ||
| 246 | |||
| 247 | *fb_div = req_clock & 0xff; | ||
| 248 | |||
| 249 | req_clock = (req_clock & 0xffff) << 1; | ||
| 250 | req_clock *= spll->reference_freq; | ||
| 251 | req_clock /= ref_div; | ||
| 252 | req_clock /= *post_div; | ||
| 253 | |||
| 254 | return req_clock; | ||
| 255 | } | ||
| 256 | |||
| 257 | /* 10 khz */ | ||
| 258 | void radeon_legacy_set_engine_clock(struct radeon_device *rdev, | ||
| 259 | uint32_t eng_clock) | ||
| 260 | { | ||
| 261 | uint32_t tmp; | ||
| 262 | int fb_div, post_div; | ||
| 263 | |||
| 264 | /* XXX: wait for idle */ | ||
| 265 | |||
| 266 | eng_clock = calc_eng_mem_clock(rdev, eng_clock, &fb_div, &post_div); | ||
| 267 | |||
| 268 | tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL); | ||
| 269 | tmp &= ~RADEON_DONT_USE_XTALIN; | ||
| 270 | WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp); | ||
| 271 | |||
| 272 | tmp = RREG32_PLL(RADEON_SCLK_CNTL); | ||
| 273 | tmp &= ~RADEON_SCLK_SRC_SEL_MASK; | ||
| 274 | WREG32_PLL(RADEON_SCLK_CNTL, tmp); | ||
| 275 | |||
| 276 | udelay(10); | ||
| 277 | |||
| 278 | tmp = RREG32_PLL(RADEON_SPLL_CNTL); | ||
| 279 | tmp |= RADEON_SPLL_SLEEP; | ||
| 280 | WREG32_PLL(RADEON_SPLL_CNTL, tmp); | ||
| 281 | |||
| 282 | udelay(2); | ||
| 283 | |||
| 284 | tmp = RREG32_PLL(RADEON_SPLL_CNTL); | ||
| 285 | tmp |= RADEON_SPLL_RESET; | ||
| 286 | WREG32_PLL(RADEON_SPLL_CNTL, tmp); | ||
| 287 | |||
| 288 | udelay(200); | ||
| 289 | |||
| 290 | tmp = RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV); | ||
| 291 | tmp &= ~(RADEON_SPLL_FB_DIV_MASK << RADEON_SPLL_FB_DIV_SHIFT); | ||
| 292 | tmp |= (fb_div & RADEON_SPLL_FB_DIV_MASK) << RADEON_SPLL_FB_DIV_SHIFT; | ||
| 293 | WREG32_PLL(RADEON_M_SPLL_REF_FB_DIV, tmp); | ||
| 294 | |||
| 295 | /* XXX: verify on different asics */ | ||
| 296 | tmp = RREG32_PLL(RADEON_SPLL_CNTL); | ||
| 297 | tmp &= ~RADEON_SPLL_PVG_MASK; | ||
| 298 | if ((eng_clock * post_div) >= 90000) | ||
| 299 | tmp |= (0x7 << RADEON_SPLL_PVG_SHIFT); | ||
| 300 | else | ||
| 301 | tmp |= (0x4 << RADEON_SPLL_PVG_SHIFT); | ||
| 302 | WREG32_PLL(RADEON_SPLL_CNTL, tmp); | ||
| 303 | |||
| 304 | tmp = RREG32_PLL(RADEON_SPLL_CNTL); | ||
| 305 | tmp &= ~RADEON_SPLL_SLEEP; | ||
| 306 | WREG32_PLL(RADEON_SPLL_CNTL, tmp); | ||
| 307 | |||
| 308 | udelay(2); | ||
| 309 | |||
| 310 | tmp = RREG32_PLL(RADEON_SPLL_CNTL); | ||
| 311 | tmp &= ~RADEON_SPLL_RESET; | ||
| 312 | WREG32_PLL(RADEON_SPLL_CNTL, tmp); | ||
| 313 | |||
| 314 | udelay(200); | ||
| 315 | |||
| 316 | tmp = RREG32_PLL(RADEON_SCLK_CNTL); | ||
| 317 | tmp &= ~RADEON_SCLK_SRC_SEL_MASK; | ||
| 318 | switch (post_div) { | ||
| 319 | case 1: | ||
| 320 | default: | ||
| 321 | tmp |= 1; | ||
| 322 | break; | ||
| 323 | case 2: | ||
| 324 | tmp |= 2; | ||
| 325 | break; | ||
| 326 | case 4: | ||
| 327 | tmp |= 3; | ||
| 328 | break; | ||
| 329 | case 8: | ||
| 330 | tmp |= 4; | ||
| 331 | break; | ||
| 332 | } | ||
| 333 | WREG32_PLL(RADEON_SCLK_CNTL, tmp); | ||
| 334 | |||
| 335 | udelay(20); | ||
| 336 | |||
| 337 | tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL); | ||
| 338 | tmp |= RADEON_DONT_USE_XTALIN; | ||
| 339 | WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp); | ||
| 340 | |||
| 341 | udelay(10); | ||
| 342 | } | ||
| 343 | |||
| 344 | void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable) | ||
| 345 | { | ||
| 346 | uint32_t tmp; | ||
| 347 | |||
| 348 | if (enable) { | ||
| 349 | if (rdev->flags & RADEON_SINGLE_CRTC) { | ||
| 350 | tmp = RREG32_PLL(RADEON_SCLK_CNTL); | ||
| 351 | if ((RREG32(RADEON_CONFIG_CNTL) & | ||
| 352 | RADEON_CFG_ATI_REV_ID_MASK) > | ||
| 353 | RADEON_CFG_ATI_REV_A13) { | ||
| 354 | tmp &= | ||
| 355 | ~(RADEON_SCLK_FORCE_CP | | ||
| 356 | RADEON_SCLK_FORCE_RB); | ||
| 357 | } | ||
| 358 | tmp &= | ||
| 359 | ~(RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | | ||
| 360 | RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_SE | | ||
| 361 | RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_RE | | ||
| 362 | RADEON_SCLK_FORCE_PB | RADEON_SCLK_FORCE_TAM | | ||
| 363 | RADEON_SCLK_FORCE_TDM); | ||
| 364 | WREG32_PLL(RADEON_SCLK_CNTL, tmp); | ||
| 365 | } else if (ASIC_IS_R300(rdev)) { | ||
| 366 | if ((rdev->family == CHIP_RS400) || | ||
| 367 | (rdev->family == CHIP_RS480)) { | ||
| 368 | tmp = RREG32_PLL(RADEON_SCLK_CNTL); | ||
| 369 | tmp &= | ||
| 370 | ~(RADEON_SCLK_FORCE_DISP2 | | ||
| 371 | RADEON_SCLK_FORCE_CP | | ||
| 372 | RADEON_SCLK_FORCE_HDP | | ||
| 373 | RADEON_SCLK_FORCE_DISP1 | | ||
| 374 | RADEON_SCLK_FORCE_TOP | | ||
| 375 | RADEON_SCLK_FORCE_E2 | R300_SCLK_FORCE_VAP | ||
| 376 | | RADEON_SCLK_FORCE_IDCT | | ||
| 377 | RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR | ||
| 378 | | R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX | ||
| 379 | | R300_SCLK_FORCE_US | | ||
| 380 | RADEON_SCLK_FORCE_TV_SCLK | | ||
| 381 | R300_SCLK_FORCE_SU | | ||
| 382 | RADEON_SCLK_FORCE_OV0); | ||
| 383 | tmp |= RADEON_DYN_STOP_LAT_MASK; | ||
| 384 | tmp |= | ||
| 385 | RADEON_SCLK_FORCE_TOP | | ||
| 386 | RADEON_SCLK_FORCE_VIP; | ||
| 387 | WREG32_PLL(RADEON_SCLK_CNTL, tmp); | ||
| 388 | |||
| 389 | tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); | ||
| 390 | tmp &= ~RADEON_SCLK_MORE_FORCEON; | ||
| 391 | tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT; | ||
| 392 | WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); | ||
| 393 | |||
| 394 | tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); | ||
| 395 | tmp |= (RADEON_PIXCLK_ALWAYS_ONb | | ||
| 396 | RADEON_PIXCLK_DAC_ALWAYS_ONb); | ||
| 397 | WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); | ||
| 398 | |||
| 399 | tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); | ||
| 400 | tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | | ||
| 401 | RADEON_PIX2CLK_DAC_ALWAYS_ONb | | ||
| 402 | RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | | ||
| 403 | R300_DVOCLK_ALWAYS_ONb | | ||
| 404 | RADEON_PIXCLK_BLEND_ALWAYS_ONb | | ||
| 405 | RADEON_PIXCLK_GV_ALWAYS_ONb | | ||
| 406 | R300_PIXCLK_DVO_ALWAYS_ONb | | ||
| 407 | RADEON_PIXCLK_LVDS_ALWAYS_ONb | | ||
| 408 | RADEON_PIXCLK_TMDS_ALWAYS_ONb | | ||
| 409 | R300_PIXCLK_TRANS_ALWAYS_ONb | | ||
| 410 | R300_PIXCLK_TVO_ALWAYS_ONb | | ||
| 411 | R300_P2G2CLK_ALWAYS_ONb | | ||
| 412 | R300_P2G2CLK_ALWAYS_ONb); | ||
| 413 | WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); | ||
| 414 | } else if (rdev->family >= CHIP_RV350) { | ||
| 415 | tmp = RREG32_PLL(R300_SCLK_CNTL2); | ||
| 416 | tmp &= ~(R300_SCLK_FORCE_TCL | | ||
| 417 | R300_SCLK_FORCE_GA | | ||
| 418 | R300_SCLK_FORCE_CBA); | ||
| 419 | tmp |= (R300_SCLK_TCL_MAX_DYN_STOP_LAT | | ||
| 420 | R300_SCLK_GA_MAX_DYN_STOP_LAT | | ||
| 421 | R300_SCLK_CBA_MAX_DYN_STOP_LAT); | ||
| 422 | WREG32_PLL(R300_SCLK_CNTL2, tmp); | ||
| 423 | |||
| 424 | tmp = RREG32_PLL(RADEON_SCLK_CNTL); | ||
| 425 | tmp &= | ||
| 426 | ~(RADEON_SCLK_FORCE_DISP2 | | ||
| 427 | RADEON_SCLK_FORCE_CP | | ||
| 428 | RADEON_SCLK_FORCE_HDP | | ||
| 429 | RADEON_SCLK_FORCE_DISP1 | | ||
| 430 | RADEON_SCLK_FORCE_TOP | | ||
| 431 | RADEON_SCLK_FORCE_E2 | R300_SCLK_FORCE_VAP | ||
| 432 | | RADEON_SCLK_FORCE_IDCT | | ||
| 433 | RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR | ||
| 434 | | R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX | ||
| 435 | | R300_SCLK_FORCE_US | | ||
| 436 | RADEON_SCLK_FORCE_TV_SCLK | | ||
| 437 | R300_SCLK_FORCE_SU | | ||
| 438 | RADEON_SCLK_FORCE_OV0); | ||
| 439 | tmp |= RADEON_DYN_STOP_LAT_MASK; | ||
| 440 | WREG32_PLL(RADEON_SCLK_CNTL, tmp); | ||
| 441 | |||
| 442 | tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); | ||
| 443 | tmp &= ~RADEON_SCLK_MORE_FORCEON; | ||
| 444 | tmp |= RADEON_SCLK_MORE_MAX_DYN_STOP_LAT; | ||
| 445 | WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); | ||
| 446 | |||
| 447 | tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); | ||
| 448 | tmp |= (RADEON_PIXCLK_ALWAYS_ONb | | ||
| 449 | RADEON_PIXCLK_DAC_ALWAYS_ONb); | ||
| 450 | WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); | ||
| 451 | |||
| 452 | tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); | ||
| 453 | tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | | ||
| 454 | RADEON_PIX2CLK_DAC_ALWAYS_ONb | | ||
| 455 | RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | | ||
| 456 | R300_DVOCLK_ALWAYS_ONb | | ||
| 457 | RADEON_PIXCLK_BLEND_ALWAYS_ONb | | ||
| 458 | RADEON_PIXCLK_GV_ALWAYS_ONb | | ||
| 459 | R300_PIXCLK_DVO_ALWAYS_ONb | | ||
| 460 | RADEON_PIXCLK_LVDS_ALWAYS_ONb | | ||
| 461 | RADEON_PIXCLK_TMDS_ALWAYS_ONb | | ||
| 462 | R300_PIXCLK_TRANS_ALWAYS_ONb | | ||
| 463 | R300_PIXCLK_TVO_ALWAYS_ONb | | ||
| 464 | R300_P2G2CLK_ALWAYS_ONb | | ||
| 465 | R300_P2G2CLK_ALWAYS_ONb); | ||
| 466 | WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); | ||
| 467 | |||
| 468 | tmp = RREG32_PLL(RADEON_MCLK_MISC); | ||
| 469 | tmp |= (RADEON_MC_MCLK_DYN_ENABLE | | ||
| 470 | RADEON_IO_MCLK_DYN_ENABLE); | ||
| 471 | WREG32_PLL(RADEON_MCLK_MISC, tmp); | ||
| 472 | |||
| 473 | tmp = RREG32_PLL(RADEON_MCLK_CNTL); | ||
| 474 | tmp |= (RADEON_FORCEON_MCLKA | | ||
| 475 | RADEON_FORCEON_MCLKB); | ||
| 476 | |||
| 477 | tmp &= ~(RADEON_FORCEON_YCLKA | | ||
| 478 | RADEON_FORCEON_YCLKB | | ||
| 479 | RADEON_FORCEON_MC); | ||
| 480 | |||
| 481 | /* Some releases of vbios have set DISABLE_MC_MCLKA | ||
| 482 | and DISABLE_MC_MCLKB bits in the vbios table. Setting these | ||
| 483 | bits will cause H/W hang when reading video memory with dynamic clocking | ||
| 484 | enabled. */ | ||
| 485 | if ((tmp & R300_DISABLE_MC_MCLKA) && | ||
| 486 | (tmp & R300_DISABLE_MC_MCLKB)) { | ||
| 487 | /* If both bits are set, then check the active channels */ | ||
| 488 | tmp = RREG32_PLL(RADEON_MCLK_CNTL); | ||
| 489 | if (rdev->mc.vram_width == 64) { | ||
| 490 | if (RREG32(RADEON_MEM_CNTL) & | ||
| 491 | R300_MEM_USE_CD_CH_ONLY) | ||
| 492 | tmp &= | ||
| 493 | ~R300_DISABLE_MC_MCLKB; | ||
| 494 | else | ||
| 495 | tmp &= | ||
| 496 | ~R300_DISABLE_MC_MCLKA; | ||
| 497 | } else { | ||
| 498 | tmp &= ~(R300_DISABLE_MC_MCLKA | | ||
| 499 | R300_DISABLE_MC_MCLKB); | ||
| 500 | } | ||
| 501 | } | ||
| 502 | |||
| 503 | WREG32_PLL(RADEON_MCLK_CNTL, tmp); | ||
| 504 | } else { | ||
| 505 | tmp = RREG32_PLL(RADEON_SCLK_CNTL); | ||
| 506 | tmp &= ~(R300_SCLK_FORCE_VAP); | ||
| 507 | tmp |= RADEON_SCLK_FORCE_CP; | ||
| 508 | WREG32_PLL(RADEON_SCLK_CNTL, tmp); | ||
| 509 | udelay(15000); | ||
| 510 | |||
| 511 | tmp = RREG32_PLL(R300_SCLK_CNTL2); | ||
| 512 | tmp &= ~(R300_SCLK_FORCE_TCL | | ||
| 513 | R300_SCLK_FORCE_GA | | ||
| 514 | R300_SCLK_FORCE_CBA); | ||
| 515 | WREG32_PLL(R300_SCLK_CNTL2, tmp); | ||
| 516 | } | ||
| 517 | } else { | ||
| 518 | tmp = RREG32_PLL(RADEON_CLK_PWRMGT_CNTL); | ||
| 519 | |||
| 520 | tmp &= ~(RADEON_ACTIVE_HILO_LAT_MASK | | ||
| 521 | RADEON_DISP_DYN_STOP_LAT_MASK | | ||
| 522 | RADEON_DYN_STOP_MODE_MASK); | ||
| 523 | |||
| 524 | tmp |= (RADEON_ENGIN_DYNCLK_MODE | | ||
| 525 | (0x01 << RADEON_ACTIVE_HILO_LAT_SHIFT)); | ||
| 526 | WREG32_PLL(RADEON_CLK_PWRMGT_CNTL, tmp); | ||
| 527 | udelay(15000); | ||
| 528 | |||
| 529 | tmp = RREG32_PLL(RADEON_CLK_PIN_CNTL); | ||
| 530 | tmp |= RADEON_SCLK_DYN_START_CNTL; | ||
| 531 | WREG32_PLL(RADEON_CLK_PIN_CNTL, tmp); | ||
| 532 | udelay(15000); | ||
| 533 | |||
| 534 | /* When DRI is enabled, setting DYN_STOP_LAT to zero can cause some R200 | ||
| 535 | to lockup randomly, leave them as set by BIOS. | ||
| 536 | */ | ||
| 537 | tmp = RREG32_PLL(RADEON_SCLK_CNTL); | ||
| 538 | /*tmp &= RADEON_SCLK_SRC_SEL_MASK; */ | ||
| 539 | tmp &= ~RADEON_SCLK_FORCEON_MASK; | ||
| 540 | |||
| 541 | /*RAGE_6::A11 A12 A12N1 A13, RV250::A11 A12, R300 */ | ||
| 542 | if (((rdev->family == CHIP_RV250) && | ||
| 543 | ((RREG32(RADEON_CONFIG_CNTL) & | ||
| 544 | RADEON_CFG_ATI_REV_ID_MASK) < | ||
| 545 | RADEON_CFG_ATI_REV_A13)) | ||
| 546 | || ((rdev->family == CHIP_RV100) | ||
| 547 | && | ||
| 548 | ((RREG32(RADEON_CONFIG_CNTL) & | ||
| 549 | RADEON_CFG_ATI_REV_ID_MASK) <= | ||
| 550 | RADEON_CFG_ATI_REV_A13))) { | ||
| 551 | tmp |= RADEON_SCLK_FORCE_CP; | ||
| 552 | tmp |= RADEON_SCLK_FORCE_VIP; | ||
| 553 | } | ||
| 554 | |||
| 555 | WREG32_PLL(RADEON_SCLK_CNTL, tmp); | ||
| 556 | |||
| 557 | if ((rdev->family == CHIP_RV200) || | ||
| 558 | (rdev->family == CHIP_RV250) || | ||
| 559 | (rdev->family == CHIP_RV280)) { | ||
| 560 | tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); | ||
| 561 | tmp &= ~RADEON_SCLK_MORE_FORCEON; | ||
| 562 | |||
| 563 | /* RV200::A11 A12 RV250::A11 A12 */ | ||
| 564 | if (((rdev->family == CHIP_RV200) || | ||
| 565 | (rdev->family == CHIP_RV250)) && | ||
| 566 | ((RREG32(RADEON_CONFIG_CNTL) & | ||
| 567 | RADEON_CFG_ATI_REV_ID_MASK) < | ||
| 568 | RADEON_CFG_ATI_REV_A13)) { | ||
| 569 | tmp |= RADEON_SCLK_MORE_FORCEON; | ||
| 570 | } | ||
| 571 | WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); | ||
| 572 | udelay(15000); | ||
| 573 | } | ||
| 574 | |||
| 575 | /* RV200::A11 A12, RV250::A11 A12 */ | ||
| 576 | if (((rdev->family == CHIP_RV200) || | ||
| 577 | (rdev->family == CHIP_RV250)) && | ||
| 578 | ((RREG32(RADEON_CONFIG_CNTL) & | ||
| 579 | RADEON_CFG_ATI_REV_ID_MASK) < | ||
| 580 | RADEON_CFG_ATI_REV_A13)) { | ||
| 581 | tmp = RREG32_PLL(RADEON_PLL_PWRMGT_CNTL); | ||
| 582 | tmp |= RADEON_TCL_BYPASS_DISABLE; | ||
| 583 | WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp); | ||
| 584 | } | ||
| 585 | udelay(15000); | ||
| 586 | |||
| 587 | /*enable dynamic mode for display clocks (PIXCLK and PIX2CLK) */ | ||
| 588 | tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); | ||
| 589 | tmp |= (RADEON_PIX2CLK_ALWAYS_ONb | | ||
| 590 | RADEON_PIX2CLK_DAC_ALWAYS_ONb | | ||
| 591 | RADEON_PIXCLK_BLEND_ALWAYS_ONb | | ||
| 592 | RADEON_PIXCLK_GV_ALWAYS_ONb | | ||
| 593 | RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb | | ||
| 594 | RADEON_PIXCLK_LVDS_ALWAYS_ONb | | ||
| 595 | RADEON_PIXCLK_TMDS_ALWAYS_ONb); | ||
| 596 | |||
| 597 | WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); | ||
| 598 | udelay(15000); | ||
| 599 | |||
| 600 | tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); | ||
| 601 | tmp |= (RADEON_PIXCLK_ALWAYS_ONb | | ||
| 602 | RADEON_PIXCLK_DAC_ALWAYS_ONb); | ||
| 603 | |||
| 604 | WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); | ||
| 605 | udelay(15000); | ||
| 606 | } | ||
| 607 | } else { | ||
| 608 | /* Turn everything OFF (ForceON to everything) */ | ||
| 609 | if (rdev->flags & RADEON_SINGLE_CRTC) { | ||
| 610 | tmp = RREG32_PLL(RADEON_SCLK_CNTL); | ||
| 611 | tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_HDP | | ||
| 612 | RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_TOP | ||
| 613 | | RADEON_SCLK_FORCE_E2 | RADEON_SCLK_FORCE_SE | | ||
| 614 | RADEON_SCLK_FORCE_IDCT | RADEON_SCLK_FORCE_VIP | | ||
| 615 | RADEON_SCLK_FORCE_RE | RADEON_SCLK_FORCE_PB | | ||
| 616 | RADEON_SCLK_FORCE_TAM | RADEON_SCLK_FORCE_TDM | | ||
| 617 | RADEON_SCLK_FORCE_RB); | ||
| 618 | WREG32_PLL(RADEON_SCLK_CNTL, tmp); | ||
| 619 | } else if ((rdev->family == CHIP_RS400) || | ||
| 620 | (rdev->family == CHIP_RS480)) { | ||
| 621 | tmp = RREG32_PLL(RADEON_SCLK_CNTL); | ||
| 622 | tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP | | ||
| 623 | RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | ||
| 624 | | RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 | | ||
| 625 | R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT | | ||
| 626 | RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR | | ||
| 627 | R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX | | ||
| 628 | R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK | | ||
| 629 | R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0); | ||
| 630 | WREG32_PLL(RADEON_SCLK_CNTL, tmp); | ||
| 631 | |||
| 632 | tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); | ||
| 633 | tmp |= RADEON_SCLK_MORE_FORCEON; | ||
| 634 | WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); | ||
| 635 | |||
| 636 | tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); | ||
| 637 | tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | | ||
| 638 | RADEON_PIXCLK_DAC_ALWAYS_ONb | | ||
| 639 | R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF); | ||
| 640 | WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); | ||
| 641 | |||
| 642 | tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); | ||
| 643 | tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | | ||
| 644 | RADEON_PIX2CLK_DAC_ALWAYS_ONb | | ||
| 645 | RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | | ||
| 646 | R300_DVOCLK_ALWAYS_ONb | | ||
| 647 | RADEON_PIXCLK_BLEND_ALWAYS_ONb | | ||
| 648 | RADEON_PIXCLK_GV_ALWAYS_ONb | | ||
| 649 | R300_PIXCLK_DVO_ALWAYS_ONb | | ||
| 650 | RADEON_PIXCLK_LVDS_ALWAYS_ONb | | ||
| 651 | RADEON_PIXCLK_TMDS_ALWAYS_ONb | | ||
| 652 | R300_PIXCLK_TRANS_ALWAYS_ONb | | ||
| 653 | R300_PIXCLK_TVO_ALWAYS_ONb | | ||
| 654 | R300_P2G2CLK_ALWAYS_ONb | | ||
| 655 | R300_P2G2CLK_ALWAYS_ONb | | ||
| 656 | R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF); | ||
| 657 | WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); | ||
| 658 | } else if (rdev->family >= CHIP_RV350) { | ||
| 659 | /* for RV350/M10, no delays are required. */ | ||
| 660 | tmp = RREG32_PLL(R300_SCLK_CNTL2); | ||
| 661 | tmp |= (R300_SCLK_FORCE_TCL | | ||
| 662 | R300_SCLK_FORCE_GA | R300_SCLK_FORCE_CBA); | ||
| 663 | WREG32_PLL(R300_SCLK_CNTL2, tmp); | ||
| 664 | |||
| 665 | tmp = RREG32_PLL(RADEON_SCLK_CNTL); | ||
| 666 | tmp |= (RADEON_SCLK_FORCE_DISP2 | RADEON_SCLK_FORCE_CP | | ||
| 667 | RADEON_SCLK_FORCE_HDP | RADEON_SCLK_FORCE_DISP1 | ||
| 668 | | RADEON_SCLK_FORCE_TOP | RADEON_SCLK_FORCE_E2 | | ||
| 669 | R300_SCLK_FORCE_VAP | RADEON_SCLK_FORCE_IDCT | | ||
| 670 | RADEON_SCLK_FORCE_VIP | R300_SCLK_FORCE_SR | | ||
| 671 | R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX | | ||
| 672 | R300_SCLK_FORCE_US | RADEON_SCLK_FORCE_TV_SCLK | | ||
| 673 | R300_SCLK_FORCE_SU | RADEON_SCLK_FORCE_OV0); | ||
| 674 | WREG32_PLL(RADEON_SCLK_CNTL, tmp); | ||
| 675 | |||
| 676 | tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); | ||
| 677 | tmp |= RADEON_SCLK_MORE_FORCEON; | ||
| 678 | WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); | ||
| 679 | |||
| 680 | tmp = RREG32_PLL(RADEON_MCLK_CNTL); | ||
| 681 | tmp |= (RADEON_FORCEON_MCLKA | | ||
| 682 | RADEON_FORCEON_MCLKB | | ||
| 683 | RADEON_FORCEON_YCLKA | | ||
| 684 | RADEON_FORCEON_YCLKB | RADEON_FORCEON_MC); | ||
| 685 | WREG32_PLL(RADEON_MCLK_CNTL, tmp); | ||
| 686 | |||
| 687 | tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); | ||
| 688 | tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | | ||
| 689 | RADEON_PIXCLK_DAC_ALWAYS_ONb | | ||
| 690 | R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF); | ||
| 691 | WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); | ||
| 692 | |||
| 693 | tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); | ||
| 694 | tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | | ||
| 695 | RADEON_PIX2CLK_DAC_ALWAYS_ONb | | ||
| 696 | RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb | | ||
| 697 | R300_DVOCLK_ALWAYS_ONb | | ||
| 698 | RADEON_PIXCLK_BLEND_ALWAYS_ONb | | ||
| 699 | RADEON_PIXCLK_GV_ALWAYS_ONb | | ||
| 700 | R300_PIXCLK_DVO_ALWAYS_ONb | | ||
| 701 | RADEON_PIXCLK_LVDS_ALWAYS_ONb | | ||
| 702 | RADEON_PIXCLK_TMDS_ALWAYS_ONb | | ||
| 703 | R300_PIXCLK_TRANS_ALWAYS_ONb | | ||
| 704 | R300_PIXCLK_TVO_ALWAYS_ONb | | ||
| 705 | R300_P2G2CLK_ALWAYS_ONb | | ||
| 706 | R300_P2G2CLK_ALWAYS_ONb | | ||
| 707 | R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF); | ||
| 708 | WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); | ||
| 709 | } else { | ||
| 710 | tmp = RREG32_PLL(RADEON_SCLK_CNTL); | ||
| 711 | tmp |= (RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_E2); | ||
| 712 | tmp |= RADEON_SCLK_FORCE_SE; | ||
| 713 | |||
| 714 | if (rdev->flags & RADEON_SINGLE_CRTC) { | ||
| 715 | tmp |= (RADEON_SCLK_FORCE_RB | | ||
| 716 | RADEON_SCLK_FORCE_TDM | | ||
| 717 | RADEON_SCLK_FORCE_TAM | | ||
| 718 | RADEON_SCLK_FORCE_PB | | ||
| 719 | RADEON_SCLK_FORCE_RE | | ||
| 720 | RADEON_SCLK_FORCE_VIP | | ||
| 721 | RADEON_SCLK_FORCE_IDCT | | ||
| 722 | RADEON_SCLK_FORCE_TOP | | ||
| 723 | RADEON_SCLK_FORCE_DISP1 | | ||
| 724 | RADEON_SCLK_FORCE_DISP2 | | ||
| 725 | RADEON_SCLK_FORCE_HDP); | ||
| 726 | } else if ((rdev->family == CHIP_R300) || | ||
| 727 | (rdev->family == CHIP_R350)) { | ||
| 728 | tmp |= (RADEON_SCLK_FORCE_HDP | | ||
| 729 | RADEON_SCLK_FORCE_DISP1 | | ||
| 730 | RADEON_SCLK_FORCE_DISP2 | | ||
| 731 | RADEON_SCLK_FORCE_TOP | | ||
| 732 | RADEON_SCLK_FORCE_IDCT | | ||
| 733 | RADEON_SCLK_FORCE_VIP); | ||
| 734 | } | ||
| 735 | WREG32_PLL(RADEON_SCLK_CNTL, tmp); | ||
| 736 | |||
| 737 | udelay(16000); | ||
| 738 | |||
| 739 | if ((rdev->family == CHIP_R300) || | ||
| 740 | (rdev->family == CHIP_R350)) { | ||
| 741 | tmp = RREG32_PLL(R300_SCLK_CNTL2); | ||
| 742 | tmp |= (R300_SCLK_FORCE_TCL | | ||
| 743 | R300_SCLK_FORCE_GA | | ||
| 744 | R300_SCLK_FORCE_CBA); | ||
| 745 | WREG32_PLL(R300_SCLK_CNTL2, tmp); | ||
| 746 | udelay(16000); | ||
| 747 | } | ||
| 748 | |||
| 749 | if (rdev->flags & RADEON_IS_IGP) { | ||
| 750 | tmp = RREG32_PLL(RADEON_MCLK_CNTL); | ||
| 751 | tmp &= ~(RADEON_FORCEON_MCLKA | | ||
| 752 | RADEON_FORCEON_YCLKA); | ||
| 753 | WREG32_PLL(RADEON_MCLK_CNTL, tmp); | ||
| 754 | udelay(16000); | ||
| 755 | } | ||
| 756 | |||
| 757 | if ((rdev->family == CHIP_RV200) || | ||
| 758 | (rdev->family == CHIP_RV250) || | ||
| 759 | (rdev->family == CHIP_RV280)) { | ||
| 760 | tmp = RREG32_PLL(RADEON_SCLK_MORE_CNTL); | ||
| 761 | tmp |= RADEON_SCLK_MORE_FORCEON; | ||
| 762 | WREG32_PLL(RADEON_SCLK_MORE_CNTL, tmp); | ||
| 763 | udelay(16000); | ||
| 764 | } | ||
| 765 | |||
| 766 | tmp = RREG32_PLL(RADEON_PIXCLKS_CNTL); | ||
| 767 | tmp &= ~(RADEON_PIX2CLK_ALWAYS_ONb | | ||
| 768 | RADEON_PIX2CLK_DAC_ALWAYS_ONb | | ||
| 769 | RADEON_PIXCLK_BLEND_ALWAYS_ONb | | ||
| 770 | RADEON_PIXCLK_GV_ALWAYS_ONb | | ||
| 771 | RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb | | ||
| 772 | RADEON_PIXCLK_LVDS_ALWAYS_ONb | | ||
| 773 | RADEON_PIXCLK_TMDS_ALWAYS_ONb); | ||
| 774 | |||
| 775 | WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); | ||
| 776 | udelay(16000); | ||
| 777 | |||
| 778 | tmp = RREG32_PLL(RADEON_VCLK_ECP_CNTL); | ||
| 779 | tmp &= ~(RADEON_PIXCLK_ALWAYS_ONb | | ||
| 780 | RADEON_PIXCLK_DAC_ALWAYS_ONb); | ||
| 781 | WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); | ||
| 782 | } | ||
| 783 | } | ||
| 784 | } | ||
| 785 | |||
| 786 | static void radeon_apply_clock_quirks(struct radeon_device *rdev) | ||
| 787 | { | ||
| 788 | uint32_t tmp; | ||
| 789 | |||
| 790 | /* XXX make sure engine is idle */ | ||
| 791 | |||
| 792 | if (rdev->family < CHIP_RS600) { | ||
| 793 | tmp = RREG32_PLL(RADEON_SCLK_CNTL); | ||
| 794 | if (ASIC_IS_R300(rdev) || ASIC_IS_RV100(rdev)) | ||
| 795 | tmp |= RADEON_SCLK_FORCE_CP | RADEON_SCLK_FORCE_VIP; | ||
| 796 | if ((rdev->family == CHIP_RV250) | ||
| 797 | || (rdev->family == CHIP_RV280)) | ||
| 798 | tmp |= | ||
| 799 | RADEON_SCLK_FORCE_DISP1 | RADEON_SCLK_FORCE_DISP2; | ||
| 800 | if ((rdev->family == CHIP_RV350) | ||
| 801 | || (rdev->family == CHIP_RV380)) | ||
| 802 | tmp |= R300_SCLK_FORCE_VAP; | ||
| 803 | if (rdev->family == CHIP_R420) | ||
| 804 | tmp |= R300_SCLK_FORCE_PX | R300_SCLK_FORCE_TX; | ||
| 805 | WREG32_PLL(RADEON_SCLK_CNTL, tmp); | ||
| 806 | } else if (rdev->family < CHIP_R600) { | ||
| 807 | tmp = RREG32_PLL(AVIVO_CP_DYN_CNTL); | ||
| 808 | tmp |= AVIVO_CP_FORCEON; | ||
| 809 | WREG32_PLL(AVIVO_CP_DYN_CNTL, tmp); | ||
| 810 | |||
| 811 | tmp = RREG32_PLL(AVIVO_E2_DYN_CNTL); | ||
| 812 | tmp |= AVIVO_E2_FORCEON; | ||
| 813 | WREG32_PLL(AVIVO_E2_DYN_CNTL, tmp); | ||
| 814 | |||
| 815 | tmp = RREG32_PLL(AVIVO_IDCT_DYN_CNTL); | ||
| 816 | tmp |= AVIVO_IDCT_FORCEON; | ||
| 817 | WREG32_PLL(AVIVO_IDCT_DYN_CNTL, tmp); | ||
| 818 | } | ||
| 819 | } | ||
| 820 | |||
| 821 | int radeon_static_clocks_init(struct drm_device *dev) | ||
| 822 | { | ||
| 823 | struct radeon_device *rdev = dev->dev_private; | ||
| 824 | |||
| 825 | /* XXX make sure engine is idle */ | ||
| 826 | |||
| 827 | if (radeon_dynclks != -1) { | ||
| 828 | if (radeon_dynclks) | ||
| 829 | radeon_set_clock_gating(rdev, 1); | ||
| 830 | } | ||
| 831 | radeon_apply_clock_quirks(rdev); | ||
| 832 | return 0; | ||
| 833 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c new file mode 100644 index 000000000000..06e8038bc4ac --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_combios.c | |||
| @@ -0,0 +1,2481 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2004 ATI Technologies Inc., Markham, Ontario | ||
| 3 | * Copyright 2007-8 Advanced Micro Devices, Inc. | ||
| 4 | * Copyright 2008 Red Hat Inc. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | */ | ||
| 27 | #include "drmP.h" | ||
| 28 | #include "radeon_drm.h" | ||
| 29 | #include "radeon.h" | ||
| 30 | #include "atom.h" | ||
| 31 | |||
| 32 | #ifdef CONFIG_PPC_PMAC | ||
| 33 | /* not sure which of these are needed */ | ||
| 34 | #include <asm/machdep.h> | ||
| 35 | #include <asm/pmac_feature.h> | ||
| 36 | #include <asm/prom.h> | ||
| 37 | #include <asm/pci-bridge.h> | ||
| 38 | #endif /* CONFIG_PPC_PMAC */ | ||
| 39 | |||
| 40 | /* from radeon_encoder.c */ | ||
| 41 | extern uint32_t | ||
| 42 | radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, | ||
| 43 | uint8_t dac); | ||
| 44 | extern void radeon_link_encoder_connector(struct drm_device *dev); | ||
| 45 | |||
| 46 | /* from radeon_connector.c */ | ||
| 47 | extern void | ||
| 48 | radeon_add_legacy_connector(struct drm_device *dev, | ||
| 49 | uint32_t connector_id, | ||
| 50 | uint32_t supported_device, | ||
| 51 | int connector_type, | ||
| 52 | struct radeon_i2c_bus_rec *i2c_bus); | ||
| 53 | |||
| 54 | /* from radeon_legacy_encoder.c */ | ||
| 55 | extern void | ||
| 56 | radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, | ||
| 57 | uint32_t supported_device); | ||
| 58 | |||
| 59 | /* old legacy ATI BIOS routines */ | ||
| 60 | |||
| 61 | /* COMBIOS table offsets */ | ||
| 62 | enum radeon_combios_table_offset { | ||
| 63 | /* absolute offset tables */ | ||
| 64 | COMBIOS_ASIC_INIT_1_TABLE, | ||
| 65 | COMBIOS_BIOS_SUPPORT_TABLE, | ||
| 66 | COMBIOS_DAC_PROGRAMMING_TABLE, | ||
| 67 | COMBIOS_MAX_COLOR_DEPTH_TABLE, | ||
| 68 | COMBIOS_CRTC_INFO_TABLE, | ||
| 69 | COMBIOS_PLL_INFO_TABLE, | ||
| 70 | COMBIOS_TV_INFO_TABLE, | ||
| 71 | COMBIOS_DFP_INFO_TABLE, | ||
| 72 | COMBIOS_HW_CONFIG_INFO_TABLE, | ||
| 73 | COMBIOS_MULTIMEDIA_INFO_TABLE, | ||
| 74 | COMBIOS_TV_STD_PATCH_TABLE, | ||
| 75 | COMBIOS_LCD_INFO_TABLE, | ||
| 76 | COMBIOS_MOBILE_INFO_TABLE, | ||
| 77 | COMBIOS_PLL_INIT_TABLE, | ||
| 78 | COMBIOS_MEM_CONFIG_TABLE, | ||
| 79 | COMBIOS_SAVE_MASK_TABLE, | ||
| 80 | COMBIOS_HARDCODED_EDID_TABLE, | ||
| 81 | COMBIOS_ASIC_INIT_2_TABLE, | ||
| 82 | COMBIOS_CONNECTOR_INFO_TABLE, | ||
| 83 | COMBIOS_DYN_CLK_1_TABLE, | ||
| 84 | COMBIOS_RESERVED_MEM_TABLE, | ||
| 85 | COMBIOS_EXT_TMDS_INFO_TABLE, | ||
| 86 | COMBIOS_MEM_CLK_INFO_TABLE, | ||
| 87 | COMBIOS_EXT_DAC_INFO_TABLE, | ||
| 88 | COMBIOS_MISC_INFO_TABLE, | ||
| 89 | COMBIOS_CRT_INFO_TABLE, | ||
| 90 | COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE, | ||
| 91 | COMBIOS_COMPONENT_VIDEO_INFO_TABLE, | ||
| 92 | COMBIOS_FAN_SPEED_INFO_TABLE, | ||
| 93 | COMBIOS_OVERDRIVE_INFO_TABLE, | ||
| 94 | COMBIOS_OEM_INFO_TABLE, | ||
| 95 | COMBIOS_DYN_CLK_2_TABLE, | ||
| 96 | COMBIOS_POWER_CONNECTOR_INFO_TABLE, | ||
| 97 | COMBIOS_I2C_INFO_TABLE, | ||
| 98 | /* relative offset tables */ | ||
| 99 | COMBIOS_ASIC_INIT_3_TABLE, /* offset from misc info */ | ||
| 100 | COMBIOS_ASIC_INIT_4_TABLE, /* offset from misc info */ | ||
| 101 | COMBIOS_DETECTED_MEM_TABLE, /* offset from misc info */ | ||
| 102 | COMBIOS_ASIC_INIT_5_TABLE, /* offset from misc info */ | ||
| 103 | COMBIOS_RAM_RESET_TABLE, /* offset from mem config */ | ||
| 104 | COMBIOS_POWERPLAY_INFO_TABLE, /* offset from mobile info */ | ||
| 105 | COMBIOS_GPIO_INFO_TABLE, /* offset from mobile info */ | ||
| 106 | COMBIOS_LCD_DDC_INFO_TABLE, /* offset from mobile info */ | ||
| 107 | COMBIOS_TMDS_POWER_TABLE, /* offset from mobile info */ | ||
| 108 | COMBIOS_TMDS_POWER_ON_TABLE, /* offset from tmds power */ | ||
| 109 | COMBIOS_TMDS_POWER_OFF_TABLE, /* offset from tmds power */ | ||
| 110 | }; | ||
| 111 | |||
| 112 | enum radeon_combios_ddc { | ||
| 113 | DDC_NONE_DETECTED, | ||
| 114 | DDC_MONID, | ||
| 115 | DDC_DVI, | ||
| 116 | DDC_VGA, | ||
| 117 | DDC_CRT2, | ||
| 118 | DDC_LCD, | ||
| 119 | DDC_GPIO, | ||
| 120 | }; | ||
| 121 | |||
| 122 | enum radeon_combios_connector { | ||
| 123 | CONNECTOR_NONE_LEGACY, | ||
| 124 | CONNECTOR_PROPRIETARY_LEGACY, | ||
| 125 | CONNECTOR_CRT_LEGACY, | ||
| 126 | CONNECTOR_DVI_I_LEGACY, | ||
| 127 | CONNECTOR_DVI_D_LEGACY, | ||
| 128 | CONNECTOR_CTV_LEGACY, | ||
| 129 | CONNECTOR_STV_LEGACY, | ||
| 130 | CONNECTOR_UNSUPPORTED_LEGACY | ||
| 131 | }; | ||
| 132 | |||
| 133 | const int legacy_connector_convert[] = { | ||
| 134 | DRM_MODE_CONNECTOR_Unknown, | ||
| 135 | DRM_MODE_CONNECTOR_DVID, | ||
| 136 | DRM_MODE_CONNECTOR_VGA, | ||
| 137 | DRM_MODE_CONNECTOR_DVII, | ||
| 138 | DRM_MODE_CONNECTOR_DVID, | ||
| 139 | DRM_MODE_CONNECTOR_Composite, | ||
| 140 | DRM_MODE_CONNECTOR_SVIDEO, | ||
| 141 | DRM_MODE_CONNECTOR_Unknown, | ||
| 142 | }; | ||
| 143 | |||
| 144 | static uint16_t combios_get_table_offset(struct drm_device *dev, | ||
| 145 | enum radeon_combios_table_offset table) | ||
| 146 | { | ||
| 147 | struct radeon_device *rdev = dev->dev_private; | ||
| 148 | int rev; | ||
| 149 | uint16_t offset = 0, check_offset; | ||
| 150 | |||
| 151 | switch (table) { | ||
| 152 | /* absolute offset tables */ | ||
| 153 | case COMBIOS_ASIC_INIT_1_TABLE: | ||
| 154 | check_offset = RBIOS16(rdev->bios_header_start + 0xc); | ||
| 155 | if (check_offset) | ||
| 156 | offset = check_offset; | ||
| 157 | break; | ||
| 158 | case COMBIOS_BIOS_SUPPORT_TABLE: | ||
| 159 | check_offset = RBIOS16(rdev->bios_header_start + 0x14); | ||
| 160 | if (check_offset) | ||
| 161 | offset = check_offset; | ||
| 162 | break; | ||
| 163 | case COMBIOS_DAC_PROGRAMMING_TABLE: | ||
| 164 | check_offset = RBIOS16(rdev->bios_header_start + 0x2a); | ||
| 165 | if (check_offset) | ||
| 166 | offset = check_offset; | ||
| 167 | break; | ||
| 168 | case COMBIOS_MAX_COLOR_DEPTH_TABLE: | ||
| 169 | check_offset = RBIOS16(rdev->bios_header_start + 0x2c); | ||
| 170 | if (check_offset) | ||
| 171 | offset = check_offset; | ||
| 172 | break; | ||
| 173 | case COMBIOS_CRTC_INFO_TABLE: | ||
| 174 | check_offset = RBIOS16(rdev->bios_header_start + 0x2e); | ||
| 175 | if (check_offset) | ||
| 176 | offset = check_offset; | ||
| 177 | break; | ||
| 178 | case COMBIOS_PLL_INFO_TABLE: | ||
| 179 | check_offset = RBIOS16(rdev->bios_header_start + 0x30); | ||
| 180 | if (check_offset) | ||
| 181 | offset = check_offset; | ||
| 182 | break; | ||
| 183 | case COMBIOS_TV_INFO_TABLE: | ||
| 184 | check_offset = RBIOS16(rdev->bios_header_start + 0x32); | ||
| 185 | if (check_offset) | ||
| 186 | offset = check_offset; | ||
| 187 | break; | ||
| 188 | case COMBIOS_DFP_INFO_TABLE: | ||
| 189 | check_offset = RBIOS16(rdev->bios_header_start + 0x34); | ||
| 190 | if (check_offset) | ||
| 191 | offset = check_offset; | ||
| 192 | break; | ||
| 193 | case COMBIOS_HW_CONFIG_INFO_TABLE: | ||
| 194 | check_offset = RBIOS16(rdev->bios_header_start + 0x36); | ||
| 195 | if (check_offset) | ||
| 196 | offset = check_offset; | ||
| 197 | break; | ||
| 198 | case COMBIOS_MULTIMEDIA_INFO_TABLE: | ||
| 199 | check_offset = RBIOS16(rdev->bios_header_start + 0x38); | ||
| 200 | if (check_offset) | ||
| 201 | offset = check_offset; | ||
| 202 | break; | ||
| 203 | case COMBIOS_TV_STD_PATCH_TABLE: | ||
| 204 | check_offset = RBIOS16(rdev->bios_header_start + 0x3e); | ||
| 205 | if (check_offset) | ||
| 206 | offset = check_offset; | ||
| 207 | break; | ||
| 208 | case COMBIOS_LCD_INFO_TABLE: | ||
| 209 | check_offset = RBIOS16(rdev->bios_header_start + 0x40); | ||
| 210 | if (check_offset) | ||
| 211 | offset = check_offset; | ||
| 212 | break; | ||
| 213 | case COMBIOS_MOBILE_INFO_TABLE: | ||
| 214 | check_offset = RBIOS16(rdev->bios_header_start + 0x42); | ||
| 215 | if (check_offset) | ||
| 216 | offset = check_offset; | ||
| 217 | break; | ||
| 218 | case COMBIOS_PLL_INIT_TABLE: | ||
| 219 | check_offset = RBIOS16(rdev->bios_header_start + 0x46); | ||
| 220 | if (check_offset) | ||
| 221 | offset = check_offset; | ||
| 222 | break; | ||
| 223 | case COMBIOS_MEM_CONFIG_TABLE: | ||
| 224 | check_offset = RBIOS16(rdev->bios_header_start + 0x48); | ||
| 225 | if (check_offset) | ||
| 226 | offset = check_offset; | ||
| 227 | break; | ||
| 228 | case COMBIOS_SAVE_MASK_TABLE: | ||
| 229 | check_offset = RBIOS16(rdev->bios_header_start + 0x4a); | ||
| 230 | if (check_offset) | ||
| 231 | offset = check_offset; | ||
| 232 | break; | ||
| 233 | case COMBIOS_HARDCODED_EDID_TABLE: | ||
| 234 | check_offset = RBIOS16(rdev->bios_header_start + 0x4c); | ||
| 235 | if (check_offset) | ||
| 236 | offset = check_offset; | ||
| 237 | break; | ||
| 238 | case COMBIOS_ASIC_INIT_2_TABLE: | ||
| 239 | check_offset = RBIOS16(rdev->bios_header_start + 0x4e); | ||
| 240 | if (check_offset) | ||
| 241 | offset = check_offset; | ||
| 242 | break; | ||
| 243 | case COMBIOS_CONNECTOR_INFO_TABLE: | ||
| 244 | check_offset = RBIOS16(rdev->bios_header_start + 0x50); | ||
| 245 | if (check_offset) | ||
| 246 | offset = check_offset; | ||
| 247 | break; | ||
| 248 | case COMBIOS_DYN_CLK_1_TABLE: | ||
| 249 | check_offset = RBIOS16(rdev->bios_header_start + 0x52); | ||
| 250 | if (check_offset) | ||
| 251 | offset = check_offset; | ||
| 252 | break; | ||
| 253 | case COMBIOS_RESERVED_MEM_TABLE: | ||
| 254 | check_offset = RBIOS16(rdev->bios_header_start + 0x54); | ||
| 255 | if (check_offset) | ||
| 256 | offset = check_offset; | ||
| 257 | break; | ||
| 258 | case COMBIOS_EXT_TMDS_INFO_TABLE: | ||
| 259 | check_offset = RBIOS16(rdev->bios_header_start + 0x58); | ||
| 260 | if (check_offset) | ||
| 261 | offset = check_offset; | ||
| 262 | break; | ||
| 263 | case COMBIOS_MEM_CLK_INFO_TABLE: | ||
| 264 | check_offset = RBIOS16(rdev->bios_header_start + 0x5a); | ||
| 265 | if (check_offset) | ||
| 266 | offset = check_offset; | ||
| 267 | break; | ||
| 268 | case COMBIOS_EXT_DAC_INFO_TABLE: | ||
| 269 | check_offset = RBIOS16(rdev->bios_header_start + 0x5c); | ||
| 270 | if (check_offset) | ||
| 271 | offset = check_offset; | ||
| 272 | break; | ||
| 273 | case COMBIOS_MISC_INFO_TABLE: | ||
| 274 | check_offset = RBIOS16(rdev->bios_header_start + 0x5e); | ||
| 275 | if (check_offset) | ||
| 276 | offset = check_offset; | ||
| 277 | break; | ||
| 278 | case COMBIOS_CRT_INFO_TABLE: | ||
| 279 | check_offset = RBIOS16(rdev->bios_header_start + 0x60); | ||
| 280 | if (check_offset) | ||
| 281 | offset = check_offset; | ||
| 282 | break; | ||
| 283 | case COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE: | ||
| 284 | check_offset = RBIOS16(rdev->bios_header_start + 0x62); | ||
| 285 | if (check_offset) | ||
| 286 | offset = check_offset; | ||
| 287 | break; | ||
| 288 | case COMBIOS_COMPONENT_VIDEO_INFO_TABLE: | ||
| 289 | check_offset = RBIOS16(rdev->bios_header_start + 0x64); | ||
| 290 | if (check_offset) | ||
| 291 | offset = check_offset; | ||
| 292 | break; | ||
| 293 | case COMBIOS_FAN_SPEED_INFO_TABLE: | ||
| 294 | check_offset = RBIOS16(rdev->bios_header_start + 0x66); | ||
| 295 | if (check_offset) | ||
| 296 | offset = check_offset; | ||
| 297 | break; | ||
| 298 | case COMBIOS_OVERDRIVE_INFO_TABLE: | ||
| 299 | check_offset = RBIOS16(rdev->bios_header_start + 0x68); | ||
| 300 | if (check_offset) | ||
| 301 | offset = check_offset; | ||
| 302 | break; | ||
| 303 | case COMBIOS_OEM_INFO_TABLE: | ||
| 304 | check_offset = RBIOS16(rdev->bios_header_start + 0x6a); | ||
| 305 | if (check_offset) | ||
| 306 | offset = check_offset; | ||
| 307 | break; | ||
| 308 | case COMBIOS_DYN_CLK_2_TABLE: | ||
| 309 | check_offset = RBIOS16(rdev->bios_header_start + 0x6c); | ||
| 310 | if (check_offset) | ||
| 311 | offset = check_offset; | ||
| 312 | break; | ||
| 313 | case COMBIOS_POWER_CONNECTOR_INFO_TABLE: | ||
| 314 | check_offset = RBIOS16(rdev->bios_header_start + 0x6e); | ||
| 315 | if (check_offset) | ||
| 316 | offset = check_offset; | ||
| 317 | break; | ||
| 318 | case COMBIOS_I2C_INFO_TABLE: | ||
| 319 | check_offset = RBIOS16(rdev->bios_header_start + 0x70); | ||
| 320 | if (check_offset) | ||
| 321 | offset = check_offset; | ||
| 322 | break; | ||
| 323 | /* relative offset tables */ | ||
| 324 | case COMBIOS_ASIC_INIT_3_TABLE: /* offset from misc info */ | ||
| 325 | check_offset = | ||
| 326 | combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE); | ||
| 327 | if (check_offset) { | ||
| 328 | rev = RBIOS8(check_offset); | ||
| 329 | if (rev > 0) { | ||
| 330 | check_offset = RBIOS16(check_offset + 0x3); | ||
| 331 | if (check_offset) | ||
| 332 | offset = check_offset; | ||
| 333 | } | ||
| 334 | } | ||
| 335 | break; | ||
| 336 | case COMBIOS_ASIC_INIT_4_TABLE: /* offset from misc info */ | ||
| 337 | check_offset = | ||
| 338 | combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE); | ||
| 339 | if (check_offset) { | ||
| 340 | rev = RBIOS8(check_offset); | ||
| 341 | if (rev > 0) { | ||
| 342 | check_offset = RBIOS16(check_offset + 0x5); | ||
| 343 | if (check_offset) | ||
| 344 | offset = check_offset; | ||
| 345 | } | ||
| 346 | } | ||
| 347 | break; | ||
| 348 | case COMBIOS_DETECTED_MEM_TABLE: /* offset from misc info */ | ||
| 349 | check_offset = | ||
| 350 | combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE); | ||
| 351 | if (check_offset) { | ||
| 352 | rev = RBIOS8(check_offset); | ||
| 353 | if (rev > 0) { | ||
| 354 | check_offset = RBIOS16(check_offset + 0x7); | ||
| 355 | if (check_offset) | ||
| 356 | offset = check_offset; | ||
| 357 | } | ||
| 358 | } | ||
| 359 | break; | ||
| 360 | case COMBIOS_ASIC_INIT_5_TABLE: /* offset from misc info */ | ||
| 361 | check_offset = | ||
| 362 | combios_get_table_offset(dev, COMBIOS_MISC_INFO_TABLE); | ||
| 363 | if (check_offset) { | ||
| 364 | rev = RBIOS8(check_offset); | ||
| 365 | if (rev == 2) { | ||
| 366 | check_offset = RBIOS16(check_offset + 0x9); | ||
| 367 | if (check_offset) | ||
| 368 | offset = check_offset; | ||
| 369 | } | ||
| 370 | } | ||
| 371 | break; | ||
| 372 | case COMBIOS_RAM_RESET_TABLE: /* offset from mem config */ | ||
| 373 | check_offset = | ||
| 374 | combios_get_table_offset(dev, COMBIOS_MEM_CONFIG_TABLE); | ||
| 375 | if (check_offset) { | ||
| 376 | while (RBIOS8(check_offset++)); | ||
| 377 | check_offset += 2; | ||
| 378 | if (check_offset) | ||
| 379 | offset = check_offset; | ||
| 380 | } | ||
| 381 | break; | ||
| 382 | case COMBIOS_POWERPLAY_INFO_TABLE: /* offset from mobile info */ | ||
| 383 | check_offset = | ||
| 384 | combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE); | ||
| 385 | if (check_offset) { | ||
| 386 | check_offset = RBIOS16(check_offset + 0x11); | ||
| 387 | if (check_offset) | ||
| 388 | offset = check_offset; | ||
| 389 | } | ||
| 390 | break; | ||
| 391 | case COMBIOS_GPIO_INFO_TABLE: /* offset from mobile info */ | ||
| 392 | check_offset = | ||
| 393 | combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE); | ||
| 394 | if (check_offset) { | ||
| 395 | check_offset = RBIOS16(check_offset + 0x13); | ||
| 396 | if (check_offset) | ||
| 397 | offset = check_offset; | ||
| 398 | } | ||
| 399 | break; | ||
| 400 | case COMBIOS_LCD_DDC_INFO_TABLE: /* offset from mobile info */ | ||
| 401 | check_offset = | ||
| 402 | combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE); | ||
| 403 | if (check_offset) { | ||
| 404 | check_offset = RBIOS16(check_offset + 0x15); | ||
| 405 | if (check_offset) | ||
| 406 | offset = check_offset; | ||
| 407 | } | ||
| 408 | break; | ||
| 409 | case COMBIOS_TMDS_POWER_TABLE: /* offset from mobile info */ | ||
| 410 | check_offset = | ||
| 411 | combios_get_table_offset(dev, COMBIOS_MOBILE_INFO_TABLE); | ||
| 412 | if (check_offset) { | ||
| 413 | check_offset = RBIOS16(check_offset + 0x17); | ||
| 414 | if (check_offset) | ||
| 415 | offset = check_offset; | ||
| 416 | } | ||
| 417 | break; | ||
| 418 | case COMBIOS_TMDS_POWER_ON_TABLE: /* offset from tmds power */ | ||
| 419 | check_offset = | ||
| 420 | combios_get_table_offset(dev, COMBIOS_TMDS_POWER_TABLE); | ||
| 421 | if (check_offset) { | ||
| 422 | check_offset = RBIOS16(check_offset + 0x2); | ||
| 423 | if (check_offset) | ||
| 424 | offset = check_offset; | ||
| 425 | } | ||
| 426 | break; | ||
| 427 | case COMBIOS_TMDS_POWER_OFF_TABLE: /* offset from tmds power */ | ||
| 428 | check_offset = | ||
| 429 | combios_get_table_offset(dev, COMBIOS_TMDS_POWER_TABLE); | ||
| 430 | if (check_offset) { | ||
| 431 | check_offset = RBIOS16(check_offset + 0x4); | ||
| 432 | if (check_offset) | ||
| 433 | offset = check_offset; | ||
| 434 | } | ||
| 435 | break; | ||
| 436 | default: | ||
| 437 | break; | ||
| 438 | } | ||
| 439 | |||
| 440 | return offset; | ||
| 441 | |||
| 442 | } | ||
| 443 | |||
| 444 | struct radeon_i2c_bus_rec combios_setup_i2c_bus(int ddc_line) | ||
| 445 | { | ||
| 446 | struct radeon_i2c_bus_rec i2c; | ||
| 447 | |||
| 448 | i2c.mask_clk_mask = RADEON_GPIO_EN_1; | ||
| 449 | i2c.mask_data_mask = RADEON_GPIO_EN_0; | ||
| 450 | i2c.a_clk_mask = RADEON_GPIO_A_1; | ||
| 451 | i2c.a_data_mask = RADEON_GPIO_A_0; | ||
| 452 | i2c.put_clk_mask = RADEON_GPIO_EN_1; | ||
| 453 | i2c.put_data_mask = RADEON_GPIO_EN_0; | ||
| 454 | i2c.get_clk_mask = RADEON_GPIO_Y_1; | ||
| 455 | i2c.get_data_mask = RADEON_GPIO_Y_0; | ||
| 456 | if ((ddc_line == RADEON_LCD_GPIO_MASK) || | ||
| 457 | (ddc_line == RADEON_MDGPIO_EN_REG)) { | ||
| 458 | i2c.mask_clk_reg = ddc_line; | ||
| 459 | i2c.mask_data_reg = ddc_line; | ||
| 460 | i2c.a_clk_reg = ddc_line; | ||
| 461 | i2c.a_data_reg = ddc_line; | ||
| 462 | i2c.put_clk_reg = ddc_line; | ||
| 463 | i2c.put_data_reg = ddc_line; | ||
| 464 | i2c.get_clk_reg = ddc_line + 4; | ||
| 465 | i2c.get_data_reg = ddc_line + 4; | ||
| 466 | } else { | ||
| 467 | i2c.mask_clk_reg = ddc_line; | ||
| 468 | i2c.mask_data_reg = ddc_line; | ||
| 469 | i2c.a_clk_reg = ddc_line; | ||
| 470 | i2c.a_data_reg = ddc_line; | ||
| 471 | i2c.put_clk_reg = ddc_line; | ||
| 472 | i2c.put_data_reg = ddc_line; | ||
| 473 | i2c.get_clk_reg = ddc_line; | ||
| 474 | i2c.get_data_reg = ddc_line; | ||
| 475 | } | ||
| 476 | |||
| 477 | if (ddc_line) | ||
| 478 | i2c.valid = true; | ||
| 479 | else | ||
| 480 | i2c.valid = false; | ||
| 481 | |||
| 482 | return i2c; | ||
| 483 | } | ||
| 484 | |||
| 485 | bool radeon_combios_get_clock_info(struct drm_device *dev) | ||
| 486 | { | ||
| 487 | struct radeon_device *rdev = dev->dev_private; | ||
| 488 | uint16_t pll_info; | ||
| 489 | struct radeon_pll *p1pll = &rdev->clock.p1pll; | ||
| 490 | struct radeon_pll *p2pll = &rdev->clock.p2pll; | ||
| 491 | struct radeon_pll *spll = &rdev->clock.spll; | ||
| 492 | struct radeon_pll *mpll = &rdev->clock.mpll; | ||
| 493 | int8_t rev; | ||
| 494 | uint16_t sclk, mclk; | ||
| 495 | |||
| 496 | if (rdev->bios == NULL) | ||
| 497 | return NULL; | ||
| 498 | |||
| 499 | pll_info = combios_get_table_offset(dev, COMBIOS_PLL_INFO_TABLE); | ||
| 500 | if (pll_info) { | ||
| 501 | rev = RBIOS8(pll_info); | ||
| 502 | |||
| 503 | /* pixel clocks */ | ||
| 504 | p1pll->reference_freq = RBIOS16(pll_info + 0xe); | ||
| 505 | p1pll->reference_div = RBIOS16(pll_info + 0x10); | ||
| 506 | p1pll->pll_out_min = RBIOS32(pll_info + 0x12); | ||
| 507 | p1pll->pll_out_max = RBIOS32(pll_info + 0x16); | ||
| 508 | |||
| 509 | if (rev > 9) { | ||
| 510 | p1pll->pll_in_min = RBIOS32(pll_info + 0x36); | ||
| 511 | p1pll->pll_in_max = RBIOS32(pll_info + 0x3a); | ||
| 512 | } else { | ||
| 513 | p1pll->pll_in_min = 40; | ||
| 514 | p1pll->pll_in_max = 500; | ||
| 515 | } | ||
| 516 | *p2pll = *p1pll; | ||
| 517 | |||
| 518 | /* system clock */ | ||
| 519 | spll->reference_freq = RBIOS16(pll_info + 0x1a); | ||
| 520 | spll->reference_div = RBIOS16(pll_info + 0x1c); | ||
| 521 | spll->pll_out_min = RBIOS32(pll_info + 0x1e); | ||
| 522 | spll->pll_out_max = RBIOS32(pll_info + 0x22); | ||
| 523 | |||
| 524 | if (rev > 10) { | ||
| 525 | spll->pll_in_min = RBIOS32(pll_info + 0x48); | ||
| 526 | spll->pll_in_max = RBIOS32(pll_info + 0x4c); | ||
| 527 | } else { | ||
| 528 | /* ??? */ | ||
| 529 | spll->pll_in_min = 40; | ||
| 530 | spll->pll_in_max = 500; | ||
| 531 | } | ||
| 532 | |||
| 533 | /* memory clock */ | ||
| 534 | mpll->reference_freq = RBIOS16(pll_info + 0x26); | ||
| 535 | mpll->reference_div = RBIOS16(pll_info + 0x28); | ||
| 536 | mpll->pll_out_min = RBIOS32(pll_info + 0x2a); | ||
| 537 | mpll->pll_out_max = RBIOS32(pll_info + 0x2e); | ||
| 538 | |||
| 539 | if (rev > 10) { | ||
| 540 | mpll->pll_in_min = RBIOS32(pll_info + 0x5a); | ||
| 541 | mpll->pll_in_max = RBIOS32(pll_info + 0x5e); | ||
| 542 | } else { | ||
| 543 | /* ??? */ | ||
| 544 | mpll->pll_in_min = 40; | ||
| 545 | mpll->pll_in_max = 500; | ||
| 546 | } | ||
| 547 | |||
| 548 | /* default sclk/mclk */ | ||
| 549 | sclk = RBIOS16(pll_info + 0xa); | ||
| 550 | mclk = RBIOS16(pll_info + 0x8); | ||
| 551 | if (sclk == 0) | ||
| 552 | sclk = 200 * 100; | ||
| 553 | if (mclk == 0) | ||
| 554 | mclk = 200 * 100; | ||
| 555 | |||
| 556 | rdev->clock.default_sclk = sclk; | ||
| 557 | rdev->clock.default_mclk = mclk; | ||
| 558 | |||
| 559 | return true; | ||
| 560 | } | ||
| 561 | return false; | ||
| 562 | } | ||
| 563 | |||
| 564 | struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct | ||
| 565 | radeon_encoder | ||
| 566 | *encoder) | ||
| 567 | { | ||
| 568 | struct drm_device *dev = encoder->base.dev; | ||
| 569 | struct radeon_device *rdev = dev->dev_private; | ||
| 570 | uint16_t dac_info; | ||
| 571 | uint8_t rev, bg, dac; | ||
| 572 | struct radeon_encoder_primary_dac *p_dac = NULL; | ||
| 573 | |||
| 574 | if (rdev->bios == NULL) | ||
| 575 | return NULL; | ||
| 576 | |||
| 577 | /* check CRT table */ | ||
| 578 | dac_info = combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE); | ||
| 579 | if (dac_info) { | ||
| 580 | p_dac = | ||
| 581 | kzalloc(sizeof(struct radeon_encoder_primary_dac), | ||
| 582 | GFP_KERNEL); | ||
| 583 | |||
| 584 | if (!p_dac) | ||
| 585 | return NULL; | ||
| 586 | |||
| 587 | rev = RBIOS8(dac_info) & 0x3; | ||
| 588 | if (rev < 2) { | ||
| 589 | bg = RBIOS8(dac_info + 0x2) & 0xf; | ||
| 590 | dac = (RBIOS8(dac_info + 0x2) >> 4) & 0xf; | ||
| 591 | p_dac->ps2_pdac_adj = (bg << 8) | (dac); | ||
| 592 | } else { | ||
| 593 | bg = RBIOS8(dac_info + 0x2) & 0xf; | ||
| 594 | dac = RBIOS8(dac_info + 0x3) & 0xf; | ||
| 595 | p_dac->ps2_pdac_adj = (bg << 8) | (dac); | ||
| 596 | } | ||
| 597 | |||
| 598 | } | ||
| 599 | |||
| 600 | return p_dac; | ||
| 601 | } | ||
| 602 | |||
| 603 | static enum radeon_tv_std | ||
| 604 | radeon_combios_get_tv_info(struct radeon_encoder *encoder) | ||
| 605 | { | ||
| 606 | struct drm_device *dev = encoder->base.dev; | ||
| 607 | struct radeon_device *rdev = dev->dev_private; | ||
| 608 | uint16_t tv_info; | ||
| 609 | enum radeon_tv_std tv_std = TV_STD_NTSC; | ||
| 610 | |||
| 611 | tv_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); | ||
| 612 | if (tv_info) { | ||
| 613 | if (RBIOS8(tv_info + 6) == 'T') { | ||
| 614 | switch (RBIOS8(tv_info + 7) & 0xf) { | ||
| 615 | case 1: | ||
| 616 | tv_std = TV_STD_NTSC; | ||
| 617 | DRM_INFO("Default TV standard: NTSC\n"); | ||
| 618 | break; | ||
| 619 | case 2: | ||
| 620 | tv_std = TV_STD_PAL; | ||
| 621 | DRM_INFO("Default TV standard: PAL\n"); | ||
| 622 | break; | ||
| 623 | case 3: | ||
| 624 | tv_std = TV_STD_PAL_M; | ||
| 625 | DRM_INFO("Default TV standard: PAL-M\n"); | ||
| 626 | break; | ||
| 627 | case 4: | ||
| 628 | tv_std = TV_STD_PAL_60; | ||
| 629 | DRM_INFO("Default TV standard: PAL-60\n"); | ||
| 630 | break; | ||
| 631 | case 5: | ||
| 632 | tv_std = TV_STD_NTSC_J; | ||
| 633 | DRM_INFO("Default TV standard: NTSC-J\n"); | ||
| 634 | break; | ||
| 635 | case 6: | ||
| 636 | tv_std = TV_STD_SCART_PAL; | ||
| 637 | DRM_INFO("Default TV standard: SCART-PAL\n"); | ||
| 638 | break; | ||
| 639 | default: | ||
| 640 | tv_std = TV_STD_NTSC; | ||
| 641 | DRM_INFO | ||
| 642 | ("Unknown TV standard; defaulting to NTSC\n"); | ||
| 643 | break; | ||
| 644 | } | ||
| 645 | |||
| 646 | switch ((RBIOS8(tv_info + 9) >> 2) & 0x3) { | ||
| 647 | case 0: | ||
| 648 | DRM_INFO("29.498928713 MHz TV ref clk\n"); | ||
| 649 | break; | ||
| 650 | case 1: | ||
| 651 | DRM_INFO("28.636360000 MHz TV ref clk\n"); | ||
| 652 | break; | ||
| 653 | case 2: | ||
| 654 | DRM_INFO("14.318180000 MHz TV ref clk\n"); | ||
| 655 | break; | ||
| 656 | case 3: | ||
| 657 | DRM_INFO("27.000000000 MHz TV ref clk\n"); | ||
| 658 | break; | ||
| 659 | default: | ||
| 660 | break; | ||
| 661 | } | ||
| 662 | } | ||
| 663 | } | ||
| 664 | return tv_std; | ||
| 665 | } | ||
| 666 | |||
| 667 | static const uint32_t default_tvdac_adj[CHIP_LAST] = { | ||
| 668 | 0x00000000, /* r100 */ | ||
| 669 | 0x00280000, /* rv100 */ | ||
| 670 | 0x00000000, /* rs100 */ | ||
| 671 | 0x00880000, /* rv200 */ | ||
| 672 | 0x00000000, /* rs200 */ | ||
| 673 | 0x00000000, /* r200 */ | ||
| 674 | 0x00770000, /* rv250 */ | ||
| 675 | 0x00290000, /* rs300 */ | ||
| 676 | 0x00560000, /* rv280 */ | ||
| 677 | 0x00780000, /* r300 */ | ||
| 678 | 0x00770000, /* r350 */ | ||
| 679 | 0x00780000, /* rv350 */ | ||
| 680 | 0x00780000, /* rv380 */ | ||
| 681 | 0x01080000, /* r420 */ | ||
| 682 | 0x01080000, /* r423 */ | ||
| 683 | 0x01080000, /* rv410 */ | ||
| 684 | 0x00780000, /* rs400 */ | ||
| 685 | 0x00780000, /* rs480 */ | ||
| 686 | }; | ||
| 687 | |||
| 688 | static struct radeon_encoder_tv_dac | ||
| 689 | *radeon_legacy_get_tv_dac_info_from_table(struct radeon_device *rdev) | ||
| 690 | { | ||
| 691 | struct radeon_encoder_tv_dac *tv_dac = NULL; | ||
| 692 | |||
| 693 | tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL); | ||
| 694 | |||
| 695 | if (!tv_dac) | ||
| 696 | return NULL; | ||
| 697 | |||
| 698 | tv_dac->ps2_tvdac_adj = default_tvdac_adj[rdev->family]; | ||
| 699 | if ((rdev->flags & RADEON_IS_MOBILITY) && (rdev->family == CHIP_RV250)) | ||
| 700 | tv_dac->ps2_tvdac_adj = 0x00880000; | ||
| 701 | tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj; | ||
| 702 | tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj; | ||
| 703 | |||
| 704 | return tv_dac; | ||
| 705 | } | ||
| 706 | |||
| 707 | struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct | ||
| 708 | radeon_encoder | ||
| 709 | *encoder) | ||
| 710 | { | ||
| 711 | struct drm_device *dev = encoder->base.dev; | ||
| 712 | struct radeon_device *rdev = dev->dev_private; | ||
| 713 | uint16_t dac_info; | ||
| 714 | uint8_t rev, bg, dac; | ||
| 715 | struct radeon_encoder_tv_dac *tv_dac = NULL; | ||
| 716 | |||
| 717 | if (rdev->bios == NULL) | ||
| 718 | return radeon_legacy_get_tv_dac_info_from_table(rdev); | ||
| 719 | |||
| 720 | /* first check TV table */ | ||
| 721 | dac_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); | ||
| 722 | if (dac_info) { | ||
| 723 | tv_dac = | ||
| 724 | kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL); | ||
| 725 | |||
| 726 | if (!tv_dac) | ||
| 727 | return NULL; | ||
| 728 | |||
| 729 | rev = RBIOS8(dac_info + 0x3); | ||
| 730 | if (rev > 4) { | ||
| 731 | bg = RBIOS8(dac_info + 0xc) & 0xf; | ||
| 732 | dac = RBIOS8(dac_info + 0xd) & 0xf; | ||
| 733 | tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20); | ||
| 734 | |||
| 735 | bg = RBIOS8(dac_info + 0xe) & 0xf; | ||
| 736 | dac = RBIOS8(dac_info + 0xf) & 0xf; | ||
| 737 | tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20); | ||
| 738 | |||
| 739 | bg = RBIOS8(dac_info + 0x10) & 0xf; | ||
| 740 | dac = RBIOS8(dac_info + 0x11) & 0xf; | ||
| 741 | tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); | ||
| 742 | } else if (rev > 1) { | ||
| 743 | bg = RBIOS8(dac_info + 0xc) & 0xf; | ||
| 744 | dac = (RBIOS8(dac_info + 0xc) >> 4) & 0xf; | ||
| 745 | tv_dac->ps2_tvdac_adj = (bg << 16) | (dac << 20); | ||
| 746 | |||
| 747 | bg = RBIOS8(dac_info + 0xd) & 0xf; | ||
| 748 | dac = (RBIOS8(dac_info + 0xd) >> 4) & 0xf; | ||
| 749 | tv_dac->pal_tvdac_adj = (bg << 16) | (dac << 20); | ||
| 750 | |||
| 751 | bg = RBIOS8(dac_info + 0xe) & 0xf; | ||
| 752 | dac = (RBIOS8(dac_info + 0xe) >> 4) & 0xf; | ||
| 753 | tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); | ||
| 754 | } | ||
| 755 | |||
| 756 | tv_dac->tv_std = radeon_combios_get_tv_info(encoder); | ||
| 757 | |||
| 758 | } else { | ||
| 759 | /* then check CRT table */ | ||
| 760 | dac_info = | ||
| 761 | combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE); | ||
| 762 | if (dac_info) { | ||
| 763 | tv_dac = | ||
| 764 | kzalloc(sizeof(struct radeon_encoder_tv_dac), | ||
| 765 | GFP_KERNEL); | ||
| 766 | |||
| 767 | if (!tv_dac) | ||
| 768 | return NULL; | ||
| 769 | |||
| 770 | rev = RBIOS8(dac_info) & 0x3; | ||
| 771 | if (rev < 2) { | ||
| 772 | bg = RBIOS8(dac_info + 0x3) & 0xf; | ||
| 773 | dac = (RBIOS8(dac_info + 0x3) >> 4) & 0xf; | ||
| 774 | tv_dac->ps2_tvdac_adj = | ||
| 775 | (bg << 16) | (dac << 20); | ||
| 776 | tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj; | ||
| 777 | tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj; | ||
| 778 | } else { | ||
| 779 | bg = RBIOS8(dac_info + 0x4) & 0xf; | ||
| 780 | dac = RBIOS8(dac_info + 0x5) & 0xf; | ||
| 781 | tv_dac->ps2_tvdac_adj = | ||
| 782 | (bg << 16) | (dac << 20); | ||
| 783 | tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj; | ||
| 784 | tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj; | ||
| 785 | } | ||
| 786 | } else { | ||
| 787 | DRM_INFO("No TV DAC info found in BIOS\n"); | ||
| 788 | return radeon_legacy_get_tv_dac_info_from_table(rdev); | ||
| 789 | } | ||
| 790 | } | ||
| 791 | |||
| 792 | return tv_dac; | ||
| 793 | } | ||
| 794 | |||
| 795 | static struct radeon_encoder_lvds *radeon_legacy_get_lvds_info_from_regs(struct | ||
| 796 | radeon_device | ||
| 797 | *rdev) | ||
| 798 | { | ||
| 799 | struct radeon_encoder_lvds *lvds = NULL; | ||
| 800 | uint32_t fp_vert_stretch, fp_horz_stretch; | ||
| 801 | uint32_t ppll_div_sel, ppll_val; | ||
| 802 | |||
| 803 | lvds = kzalloc(sizeof(struct radeon_encoder_lvds), GFP_KERNEL); | ||
| 804 | |||
| 805 | if (!lvds) | ||
| 806 | return NULL; | ||
| 807 | |||
| 808 | fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH); | ||
| 809 | fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH); | ||
| 810 | |||
| 811 | if (fp_vert_stretch & RADEON_VERT_STRETCH_ENABLE) | ||
| 812 | lvds->native_mode.panel_yres = | ||
| 813 | ((fp_vert_stretch & RADEON_VERT_PANEL_SIZE) >> | ||
| 814 | RADEON_VERT_PANEL_SHIFT) + 1; | ||
| 815 | else | ||
| 816 | lvds->native_mode.panel_yres = | ||
| 817 | (RREG32(RADEON_CRTC_V_TOTAL_DISP) >> 16) + 1; | ||
| 818 | |||
| 819 | if (fp_horz_stretch & RADEON_HORZ_STRETCH_ENABLE) | ||
| 820 | lvds->native_mode.panel_xres = | ||
| 821 | (((fp_horz_stretch & RADEON_HORZ_PANEL_SIZE) >> | ||
| 822 | RADEON_HORZ_PANEL_SHIFT) + 1) * 8; | ||
| 823 | else | ||
| 824 | lvds->native_mode.panel_xres = | ||
| 825 | ((RREG32(RADEON_CRTC_H_TOTAL_DISP) >> 16) + 1) * 8; | ||
| 826 | |||
| 827 | if ((lvds->native_mode.panel_xres < 640) || | ||
| 828 | (lvds->native_mode.panel_yres < 480)) { | ||
| 829 | lvds->native_mode.panel_xres = 640; | ||
| 830 | lvds->native_mode.panel_yres = 480; | ||
| 831 | } | ||
| 832 | |||
| 833 | ppll_div_sel = RREG8(RADEON_CLOCK_CNTL_INDEX + 1) & 0x3; | ||
| 834 | ppll_val = RREG32_PLL(RADEON_PPLL_DIV_0 + ppll_div_sel); | ||
| 835 | if ((ppll_val & 0x000707ff) == 0x1bb) | ||
| 836 | lvds->use_bios_dividers = false; | ||
| 837 | else { | ||
| 838 | lvds->panel_ref_divider = | ||
| 839 | RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff; | ||
| 840 | lvds->panel_post_divider = (ppll_val >> 16) & 0x7; | ||
| 841 | lvds->panel_fb_divider = ppll_val & 0x7ff; | ||
| 842 | |||
| 843 | if ((lvds->panel_ref_divider != 0) && | ||
| 844 | (lvds->panel_fb_divider > 3)) | ||
| 845 | lvds->use_bios_dividers = true; | ||
| 846 | } | ||
| 847 | lvds->panel_vcc_delay = 200; | ||
| 848 | |||
| 849 | DRM_INFO("Panel info derived from registers\n"); | ||
| 850 | DRM_INFO("Panel Size %dx%d\n", lvds->native_mode.panel_xres, | ||
| 851 | lvds->native_mode.panel_yres); | ||
| 852 | |||
| 853 | return lvds; | ||
| 854 | } | ||
| 855 | |||
| 856 | struct radeon_encoder_lvds *radeon_combios_get_lvds_info(struct radeon_encoder | ||
| 857 | *encoder) | ||
| 858 | { | ||
| 859 | struct drm_device *dev = encoder->base.dev; | ||
| 860 | struct radeon_device *rdev = dev->dev_private; | ||
| 861 | uint16_t lcd_info; | ||
| 862 | uint32_t panel_setup; | ||
| 863 | char stmp[30]; | ||
| 864 | int tmp, i; | ||
| 865 | struct radeon_encoder_lvds *lvds = NULL; | ||
| 866 | |||
| 867 | if (rdev->bios == NULL) | ||
| 868 | return radeon_legacy_get_lvds_info_from_regs(rdev); | ||
| 869 | |||
| 870 | lcd_info = combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE); | ||
| 871 | |||
| 872 | if (lcd_info) { | ||
| 873 | lvds = kzalloc(sizeof(struct radeon_encoder_lvds), GFP_KERNEL); | ||
| 874 | |||
| 875 | if (!lvds) | ||
| 876 | return NULL; | ||
| 877 | |||
| 878 | for (i = 0; i < 24; i++) | ||
| 879 | stmp[i] = RBIOS8(lcd_info + i + 1); | ||
| 880 | stmp[24] = 0; | ||
| 881 | |||
| 882 | DRM_INFO("Panel ID String: %s\n", stmp); | ||
| 883 | |||
| 884 | lvds->native_mode.panel_xres = RBIOS16(lcd_info + 0x19); | ||
| 885 | lvds->native_mode.panel_yres = RBIOS16(lcd_info + 0x1b); | ||
| 886 | |||
| 887 | DRM_INFO("Panel Size %dx%d\n", lvds->native_mode.panel_xres, | ||
| 888 | lvds->native_mode.panel_yres); | ||
| 889 | |||
| 890 | lvds->panel_vcc_delay = RBIOS16(lcd_info + 0x2c); | ||
| 891 | if (lvds->panel_vcc_delay > 2000 || lvds->panel_vcc_delay < 0) | ||
| 892 | lvds->panel_vcc_delay = 2000; | ||
| 893 | |||
| 894 | lvds->panel_pwr_delay = RBIOS8(lcd_info + 0x24); | ||
| 895 | lvds->panel_digon_delay = RBIOS16(lcd_info + 0x38) & 0xf; | ||
| 896 | lvds->panel_blon_delay = (RBIOS16(lcd_info + 0x38) >> 4) & 0xf; | ||
| 897 | |||
| 898 | lvds->panel_ref_divider = RBIOS16(lcd_info + 0x2e); | ||
| 899 | lvds->panel_post_divider = RBIOS8(lcd_info + 0x30); | ||
| 900 | lvds->panel_fb_divider = RBIOS16(lcd_info + 0x31); | ||
| 901 | if ((lvds->panel_ref_divider != 0) && | ||
| 902 | (lvds->panel_fb_divider > 3)) | ||
| 903 | lvds->use_bios_dividers = true; | ||
| 904 | |||
| 905 | panel_setup = RBIOS32(lcd_info + 0x39); | ||
| 906 | lvds->lvds_gen_cntl = 0xff00; | ||
| 907 | if (panel_setup & 0x1) | ||
| 908 | lvds->lvds_gen_cntl |= RADEON_LVDS_PANEL_FORMAT; | ||
| 909 | |||
| 910 | if ((panel_setup >> 4) & 0x1) | ||
| 911 | lvds->lvds_gen_cntl |= RADEON_LVDS_PANEL_TYPE; | ||
| 912 | |||
| 913 | switch ((panel_setup >> 8) & 0x7) { | ||
| 914 | case 0: | ||
| 915 | lvds->lvds_gen_cntl |= RADEON_LVDS_NO_FM; | ||
| 916 | break; | ||
| 917 | case 1: | ||
| 918 | lvds->lvds_gen_cntl |= RADEON_LVDS_2_GREY; | ||
| 919 | break; | ||
| 920 | case 2: | ||
| 921 | lvds->lvds_gen_cntl |= RADEON_LVDS_4_GREY; | ||
| 922 | break; | ||
| 923 | default: | ||
| 924 | break; | ||
| 925 | } | ||
| 926 | |||
| 927 | if ((panel_setup >> 16) & 0x1) | ||
| 928 | lvds->lvds_gen_cntl |= RADEON_LVDS_FP_POL_LOW; | ||
| 929 | |||
| 930 | if ((panel_setup >> 17) & 0x1) | ||
| 931 | lvds->lvds_gen_cntl |= RADEON_LVDS_LP_POL_LOW; | ||
| 932 | |||
| 933 | if ((panel_setup >> 18) & 0x1) | ||
| 934 | lvds->lvds_gen_cntl |= RADEON_LVDS_DTM_POL_LOW; | ||
| 935 | |||
| 936 | if ((panel_setup >> 23) & 0x1) | ||
| 937 | lvds->lvds_gen_cntl |= RADEON_LVDS_BL_CLK_SEL; | ||
| 938 | |||
| 939 | lvds->lvds_gen_cntl |= (panel_setup & 0xf0000000); | ||
| 940 | |||
| 941 | for (i = 0; i < 32; i++) { | ||
| 942 | tmp = RBIOS16(lcd_info + 64 + i * 2); | ||
| 943 | if (tmp == 0) | ||
| 944 | break; | ||
| 945 | |||
| 946 | if ((RBIOS16(tmp) == lvds->native_mode.panel_xres) && | ||
| 947 | (RBIOS16(tmp + 2) == | ||
| 948 | lvds->native_mode.panel_yres)) { | ||
| 949 | lvds->native_mode.hblank = | ||
| 950 | (RBIOS16(tmp + 17) - RBIOS16(tmp + 19)) * 8; | ||
| 951 | lvds->native_mode.hoverplus = | ||
| 952 | (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) - | ||
| 953 | 1) * 8; | ||
| 954 | lvds->native_mode.hsync_width = | ||
| 955 | RBIOS8(tmp + 23) * 8; | ||
| 956 | |||
| 957 | lvds->native_mode.vblank = (RBIOS16(tmp + 24) - | ||
| 958 | RBIOS16(tmp + 26)); | ||
| 959 | lvds->native_mode.voverplus = | ||
| 960 | ((RBIOS16(tmp + 28) & 0x7ff) - | ||
| 961 | RBIOS16(tmp + 26)); | ||
| 962 | lvds->native_mode.vsync_width = | ||
| 963 | ((RBIOS16(tmp + 28) & 0xf800) >> 11); | ||
| 964 | lvds->native_mode.dotclock = | ||
| 965 | RBIOS16(tmp + 9) * 10; | ||
| 966 | lvds->native_mode.flags = 0; | ||
| 967 | } | ||
| 968 | } | ||
| 969 | encoder->native_mode = lvds->native_mode; | ||
| 970 | } else { | ||
| 971 | DRM_INFO("No panel info found in BIOS\n"); | ||
| 972 | return radeon_legacy_get_lvds_info_from_regs(rdev); | ||
| 973 | } | ||
| 974 | return lvds; | ||
| 975 | } | ||
| 976 | |||
| 977 | static const struct radeon_tmds_pll default_tmds_pll[CHIP_LAST][4] = { | ||
| 978 | {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /* CHIP_R100 */ | ||
| 979 | {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /* CHIP_RV100 */ | ||
| 980 | {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_RS100 */ | ||
| 981 | {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /* CHIP_RV200 */ | ||
| 982 | {{12000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /* CHIP_RS200 */ | ||
| 983 | {{15000, 0xa1b}, {0xffffffff, 0xa3f}, {0, 0}, {0, 0}}, /* CHIP_R200 */ | ||
| 984 | {{15500, 0x81b}, {0xffffffff, 0x83f}, {0, 0}, {0, 0}}, /* CHIP_RV250 */ | ||
| 985 | {{0, 0}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_RS300 */ | ||
| 986 | {{13000, 0x400f4}, {15000, 0x400f7}, {0xffffffff, 0x40111}, {0, 0}}, /* CHIP_RV280 */ | ||
| 987 | {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_R300 */ | ||
| 988 | {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_R350 */ | ||
| 989 | {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /* CHIP_RV350 */ | ||
| 990 | {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /* CHIP_RV380 */ | ||
| 991 | {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_R420 */ | ||
| 992 | {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_R423 */ | ||
| 993 | {{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_RV410 */ | ||
| 994 | {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /* CHIP_RS400 */ | ||
| 995 | {{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /* CHIP_RS480 */ | ||
| 996 | }; | ||
| 997 | |||
| 998 | static struct radeon_encoder_int_tmds | ||
| 999 | *radeon_legacy_get_tmds_info_from_table(struct radeon_device *rdev) | ||
| 1000 | { | ||
| 1001 | int i; | ||
| 1002 | struct radeon_encoder_int_tmds *tmds = NULL; | ||
| 1003 | |||
| 1004 | tmds = kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL); | ||
| 1005 | |||
| 1006 | if (!tmds) | ||
| 1007 | return NULL; | ||
| 1008 | |||
| 1009 | for (i = 0; i < 4; i++) { | ||
| 1010 | tmds->tmds_pll[i].value = | ||
| 1011 | default_tmds_pll[rdev->family][i].value; | ||
| 1012 | tmds->tmds_pll[i].freq = default_tmds_pll[rdev->family][i].freq; | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | return tmds; | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | struct radeon_encoder_int_tmds *radeon_combios_get_tmds_info(struct | ||
| 1019 | radeon_encoder | ||
| 1020 | *encoder) | ||
| 1021 | { | ||
| 1022 | struct drm_device *dev = encoder->base.dev; | ||
| 1023 | struct radeon_device *rdev = dev->dev_private; | ||
| 1024 | uint16_t tmds_info; | ||
| 1025 | int i, n; | ||
| 1026 | uint8_t ver; | ||
| 1027 | struct radeon_encoder_int_tmds *tmds = NULL; | ||
| 1028 | |||
| 1029 | if (rdev->bios == NULL) | ||
| 1030 | return radeon_legacy_get_tmds_info_from_table(rdev); | ||
| 1031 | |||
| 1032 | tmds_info = combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE); | ||
| 1033 | |||
| 1034 | if (tmds_info) { | ||
| 1035 | tmds = | ||
| 1036 | kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL); | ||
| 1037 | |||
| 1038 | if (!tmds) | ||
| 1039 | return NULL; | ||
| 1040 | |||
| 1041 | ver = RBIOS8(tmds_info); | ||
| 1042 | DRM_INFO("DFP table revision: %d\n", ver); | ||
| 1043 | if (ver == 3) { | ||
| 1044 | n = RBIOS8(tmds_info + 5) + 1; | ||
| 1045 | if (n > 4) | ||
| 1046 | n = 4; | ||
| 1047 | for (i = 0; i < n; i++) { | ||
| 1048 | tmds->tmds_pll[i].value = | ||
| 1049 | RBIOS32(tmds_info + i * 10 + 0x08); | ||
| 1050 | tmds->tmds_pll[i].freq = | ||
| 1051 | RBIOS16(tmds_info + i * 10 + 0x10); | ||
| 1052 | DRM_DEBUG("TMDS PLL From COMBIOS %u %x\n", | ||
| 1053 | tmds->tmds_pll[i].freq, | ||
| 1054 | tmds->tmds_pll[i].value); | ||
| 1055 | } | ||
| 1056 | } else if (ver == 4) { | ||
| 1057 | int stride = 0; | ||
| 1058 | n = RBIOS8(tmds_info + 5) + 1; | ||
| 1059 | if (n > 4) | ||
| 1060 | n = 4; | ||
| 1061 | for (i = 0; i < n; i++) { | ||
| 1062 | tmds->tmds_pll[i].value = | ||
| 1063 | RBIOS32(tmds_info + stride + 0x08); | ||
| 1064 | tmds->tmds_pll[i].freq = | ||
| 1065 | RBIOS16(tmds_info + stride + 0x10); | ||
| 1066 | if (i == 0) | ||
| 1067 | stride += 10; | ||
| 1068 | else | ||
| 1069 | stride += 6; | ||
| 1070 | DRM_DEBUG("TMDS PLL From COMBIOS %u %x\n", | ||
| 1071 | tmds->tmds_pll[i].freq, | ||
| 1072 | tmds->tmds_pll[i].value); | ||
| 1073 | } | ||
| 1074 | } | ||
| 1075 | } else | ||
| 1076 | DRM_INFO("No TMDS info found in BIOS\n"); | ||
| 1077 | return tmds; | ||
| 1078 | } | ||
| 1079 | |||
| 1080 | void radeon_combios_get_ext_tmds_info(struct radeon_encoder *encoder) | ||
| 1081 | { | ||
| 1082 | struct drm_device *dev = encoder->base.dev; | ||
| 1083 | struct radeon_device *rdev = dev->dev_private; | ||
| 1084 | uint16_t ext_tmds_info; | ||
| 1085 | uint8_t ver; | ||
| 1086 | |||
| 1087 | if (rdev->bios == NULL) | ||
| 1088 | return; | ||
| 1089 | |||
| 1090 | ext_tmds_info = | ||
| 1091 | combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE); | ||
| 1092 | if (ext_tmds_info) { | ||
| 1093 | ver = RBIOS8(ext_tmds_info); | ||
| 1094 | DRM_INFO("External TMDS Table revision: %d\n", ver); | ||
| 1095 | // TODO | ||
| 1096 | } | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) | ||
| 1100 | { | ||
| 1101 | struct radeon_device *rdev = dev->dev_private; | ||
| 1102 | struct radeon_i2c_bus_rec ddc_i2c; | ||
| 1103 | |||
| 1104 | rdev->mode_info.connector_table = radeon_connector_table; | ||
| 1105 | if (rdev->mode_info.connector_table == CT_NONE) { | ||
| 1106 | #ifdef CONFIG_PPC_PMAC | ||
| 1107 | if (machine_is_compatible("PowerBook3,3")) { | ||
| 1108 | /* powerbook with VGA */ | ||
| 1109 | rdev->mode_info.connector_table = CT_POWERBOOK_VGA; | ||
| 1110 | } else if (machine_is_compatible("PowerBook3,4") || | ||
| 1111 | machine_is_compatible("PowerBook3,5")) { | ||
| 1112 | /* powerbook with internal tmds */ | ||
| 1113 | rdev->mode_info.connector_table = CT_POWERBOOK_INTERNAL; | ||
| 1114 | } else if (machine_is_compatible("PowerBook5,1") || | ||
| 1115 | machine_is_compatible("PowerBook5,2") || | ||
| 1116 | machine_is_compatible("PowerBook5,3") || | ||
| 1117 | machine_is_compatible("PowerBook5,4") || | ||
| 1118 | machine_is_compatible("PowerBook5,5")) { | ||
| 1119 | /* powerbook with external single link tmds (sil164) */ | ||
| 1120 | rdev->mode_info.connector_table = CT_POWERBOOK_EXTERNAL; | ||
| 1121 | } else if (machine_is_compatible("PowerBook5,6")) { | ||
| 1122 | /* powerbook with external dual or single link tmds */ | ||
| 1123 | rdev->mode_info.connector_table = CT_POWERBOOK_EXTERNAL; | ||
| 1124 | } else if (machine_is_compatible("PowerBook5,7") || | ||
| 1125 | machine_is_compatible("PowerBook5,8") || | ||
| 1126 | machine_is_compatible("PowerBook5,9")) { | ||
| 1127 | /* PowerBook6,2 ? */ | ||
| 1128 | /* powerbook with external dual link tmds (sil1178?) */ | ||
| 1129 | rdev->mode_info.connector_table = CT_POWERBOOK_EXTERNAL; | ||
| 1130 | } else if (machine_is_compatible("PowerBook4,1") || | ||
| 1131 | machine_is_compatible("PowerBook4,2") || | ||
| 1132 | machine_is_compatible("PowerBook4,3") || | ||
| 1133 | machine_is_compatible("PowerBook6,3") || | ||
| 1134 | machine_is_compatible("PowerBook6,5") || | ||
| 1135 | machine_is_compatible("PowerBook6,7")) { | ||
| 1136 | /* ibook */ | ||
| 1137 | rdev->mode_info.connector_table = CT_IBOOK; | ||
| 1138 | } else if (machine_is_compatible("PowerMac4,4")) { | ||
| 1139 | /* emac */ | ||
| 1140 | rdev->mode_info.connector_table = CT_EMAC; | ||
| 1141 | } else if (machine_is_compatible("PowerMac10,1")) { | ||
| 1142 | /* mini with internal tmds */ | ||
| 1143 | rdev->mode_info.connector_table = CT_MINI_INTERNAL; | ||
| 1144 | } else if (machine_is_compatible("PowerMac10,2")) { | ||
| 1145 | /* mini with external tmds */ | ||
| 1146 | rdev->mode_info.connector_table = CT_MINI_EXTERNAL; | ||
| 1147 | } else if (machine_is_compatible("PowerMac12,1")) { | ||
| 1148 | /* PowerMac8,1 ? */ | ||
| 1149 | /* imac g5 isight */ | ||
| 1150 | rdev->mode_info.connector_table = CT_IMAC_G5_ISIGHT; | ||
| 1151 | } else | ||
| 1152 | #endif /* CONFIG_PPC_PMAC */ | ||
| 1153 | rdev->mode_info.connector_table = CT_GENERIC; | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | switch (rdev->mode_info.connector_table) { | ||
| 1157 | case CT_GENERIC: | ||
| 1158 | DRM_INFO("Connector Table: %d (generic)\n", | ||
| 1159 | rdev->mode_info.connector_table); | ||
| 1160 | /* these are the most common settings */ | ||
| 1161 | if (rdev->flags & RADEON_SINGLE_CRTC) { | ||
| 1162 | /* VGA - primary dac */ | ||
| 1163 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); | ||
| 1164 | radeon_add_legacy_encoder(dev, | ||
| 1165 | radeon_get_encoder_id(dev, | ||
| 1166 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1167 | 1), | ||
| 1168 | ATOM_DEVICE_CRT1_SUPPORT); | ||
| 1169 | radeon_add_legacy_connector(dev, 0, | ||
| 1170 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1171 | DRM_MODE_CONNECTOR_VGA, | ||
| 1172 | &ddc_i2c); | ||
| 1173 | } else if (rdev->flags & RADEON_IS_MOBILITY) { | ||
| 1174 | /* LVDS */ | ||
| 1175 | ddc_i2c = combios_setup_i2c_bus(RADEON_LCD_GPIO_MASK); | ||
| 1176 | radeon_add_legacy_encoder(dev, | ||
| 1177 | radeon_get_encoder_id(dev, | ||
| 1178 | ATOM_DEVICE_LCD1_SUPPORT, | ||
| 1179 | 0), | ||
| 1180 | ATOM_DEVICE_LCD1_SUPPORT); | ||
| 1181 | radeon_add_legacy_connector(dev, 0, | ||
| 1182 | ATOM_DEVICE_LCD1_SUPPORT, | ||
| 1183 | DRM_MODE_CONNECTOR_LVDS, | ||
| 1184 | &ddc_i2c); | ||
| 1185 | |||
| 1186 | /* VGA - primary dac */ | ||
| 1187 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); | ||
| 1188 | radeon_add_legacy_encoder(dev, | ||
| 1189 | radeon_get_encoder_id(dev, | ||
| 1190 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1191 | 1), | ||
| 1192 | ATOM_DEVICE_CRT1_SUPPORT); | ||
| 1193 | radeon_add_legacy_connector(dev, 1, | ||
| 1194 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1195 | DRM_MODE_CONNECTOR_VGA, | ||
| 1196 | &ddc_i2c); | ||
| 1197 | } else { | ||
| 1198 | /* DVI-I - tv dac, int tmds */ | ||
| 1199 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); | ||
| 1200 | radeon_add_legacy_encoder(dev, | ||
| 1201 | radeon_get_encoder_id(dev, | ||
| 1202 | ATOM_DEVICE_DFP1_SUPPORT, | ||
| 1203 | 0), | ||
| 1204 | ATOM_DEVICE_DFP1_SUPPORT); | ||
| 1205 | radeon_add_legacy_encoder(dev, | ||
| 1206 | radeon_get_encoder_id(dev, | ||
| 1207 | ATOM_DEVICE_CRT2_SUPPORT, | ||
| 1208 | 2), | ||
| 1209 | ATOM_DEVICE_CRT2_SUPPORT); | ||
| 1210 | radeon_add_legacy_connector(dev, 0, | ||
| 1211 | ATOM_DEVICE_DFP1_SUPPORT | | ||
| 1212 | ATOM_DEVICE_CRT2_SUPPORT, | ||
| 1213 | DRM_MODE_CONNECTOR_DVII, | ||
| 1214 | &ddc_i2c); | ||
| 1215 | |||
| 1216 | /* VGA - primary dac */ | ||
| 1217 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); | ||
| 1218 | radeon_add_legacy_encoder(dev, | ||
| 1219 | radeon_get_encoder_id(dev, | ||
| 1220 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1221 | 1), | ||
| 1222 | ATOM_DEVICE_CRT1_SUPPORT); | ||
| 1223 | radeon_add_legacy_connector(dev, 1, | ||
| 1224 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1225 | DRM_MODE_CONNECTOR_VGA, | ||
| 1226 | &ddc_i2c); | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | if (rdev->family != CHIP_R100 && rdev->family != CHIP_R200) { | ||
| 1230 | /* TV - tv dac */ | ||
| 1231 | radeon_add_legacy_encoder(dev, | ||
| 1232 | radeon_get_encoder_id(dev, | ||
| 1233 | ATOM_DEVICE_TV1_SUPPORT, | ||
| 1234 | 2), | ||
| 1235 | ATOM_DEVICE_TV1_SUPPORT); | ||
| 1236 | radeon_add_legacy_connector(dev, 2, | ||
| 1237 | ATOM_DEVICE_TV1_SUPPORT, | ||
| 1238 | DRM_MODE_CONNECTOR_SVIDEO, | ||
| 1239 | &ddc_i2c); | ||
| 1240 | } | ||
| 1241 | break; | ||
| 1242 | case CT_IBOOK: | ||
| 1243 | DRM_INFO("Connector Table: %d (ibook)\n", | ||
| 1244 | rdev->mode_info.connector_table); | ||
| 1245 | /* LVDS */ | ||
| 1246 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); | ||
| 1247 | radeon_add_legacy_encoder(dev, | ||
| 1248 | radeon_get_encoder_id(dev, | ||
| 1249 | ATOM_DEVICE_LCD1_SUPPORT, | ||
| 1250 | 0), | ||
| 1251 | ATOM_DEVICE_LCD1_SUPPORT); | ||
| 1252 | radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT, | ||
| 1253 | DRM_MODE_CONNECTOR_LVDS, &ddc_i2c); | ||
| 1254 | /* VGA - TV DAC */ | ||
| 1255 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); | ||
| 1256 | radeon_add_legacy_encoder(dev, | ||
| 1257 | radeon_get_encoder_id(dev, | ||
| 1258 | ATOM_DEVICE_CRT2_SUPPORT, | ||
| 1259 | 2), | ||
| 1260 | ATOM_DEVICE_CRT2_SUPPORT); | ||
| 1261 | radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT, | ||
| 1262 | DRM_MODE_CONNECTOR_VGA, &ddc_i2c); | ||
| 1263 | /* TV - TV DAC */ | ||
| 1264 | radeon_add_legacy_encoder(dev, | ||
| 1265 | radeon_get_encoder_id(dev, | ||
| 1266 | ATOM_DEVICE_TV1_SUPPORT, | ||
| 1267 | 2), | ||
| 1268 | ATOM_DEVICE_TV1_SUPPORT); | ||
| 1269 | radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, | ||
| 1270 | DRM_MODE_CONNECTOR_SVIDEO, | ||
| 1271 | &ddc_i2c); | ||
| 1272 | break; | ||
| 1273 | case CT_POWERBOOK_EXTERNAL: | ||
| 1274 | DRM_INFO("Connector Table: %d (powerbook external tmds)\n", | ||
| 1275 | rdev->mode_info.connector_table); | ||
| 1276 | /* LVDS */ | ||
| 1277 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); | ||
| 1278 | radeon_add_legacy_encoder(dev, | ||
| 1279 | radeon_get_encoder_id(dev, | ||
| 1280 | ATOM_DEVICE_LCD1_SUPPORT, | ||
| 1281 | 0), | ||
| 1282 | ATOM_DEVICE_LCD1_SUPPORT); | ||
| 1283 | radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT, | ||
| 1284 | DRM_MODE_CONNECTOR_LVDS, &ddc_i2c); | ||
| 1285 | /* DVI-I - primary dac, ext tmds */ | ||
| 1286 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); | ||
| 1287 | radeon_add_legacy_encoder(dev, | ||
| 1288 | radeon_get_encoder_id(dev, | ||
| 1289 | ATOM_DEVICE_DFP2_SUPPORT, | ||
| 1290 | 0), | ||
| 1291 | ATOM_DEVICE_DFP2_SUPPORT); | ||
| 1292 | radeon_add_legacy_encoder(dev, | ||
| 1293 | radeon_get_encoder_id(dev, | ||
| 1294 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1295 | 1), | ||
| 1296 | ATOM_DEVICE_CRT1_SUPPORT); | ||
| 1297 | radeon_add_legacy_connector(dev, 1, | ||
| 1298 | ATOM_DEVICE_DFP2_SUPPORT | | ||
| 1299 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1300 | DRM_MODE_CONNECTOR_DVII, &ddc_i2c); | ||
| 1301 | /* TV - TV DAC */ | ||
| 1302 | radeon_add_legacy_encoder(dev, | ||
| 1303 | radeon_get_encoder_id(dev, | ||
| 1304 | ATOM_DEVICE_TV1_SUPPORT, | ||
| 1305 | 2), | ||
| 1306 | ATOM_DEVICE_TV1_SUPPORT); | ||
| 1307 | radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, | ||
| 1308 | DRM_MODE_CONNECTOR_SVIDEO, | ||
| 1309 | &ddc_i2c); | ||
| 1310 | break; | ||
| 1311 | case CT_POWERBOOK_INTERNAL: | ||
| 1312 | DRM_INFO("Connector Table: %d (powerbook internal tmds)\n", | ||
| 1313 | rdev->mode_info.connector_table); | ||
| 1314 | /* LVDS */ | ||
| 1315 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); | ||
| 1316 | radeon_add_legacy_encoder(dev, | ||
| 1317 | radeon_get_encoder_id(dev, | ||
| 1318 | ATOM_DEVICE_LCD1_SUPPORT, | ||
| 1319 | 0), | ||
| 1320 | ATOM_DEVICE_LCD1_SUPPORT); | ||
| 1321 | radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT, | ||
| 1322 | DRM_MODE_CONNECTOR_LVDS, &ddc_i2c); | ||
| 1323 | /* DVI-I - primary dac, int tmds */ | ||
| 1324 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); | ||
| 1325 | radeon_add_legacy_encoder(dev, | ||
| 1326 | radeon_get_encoder_id(dev, | ||
| 1327 | ATOM_DEVICE_DFP1_SUPPORT, | ||
| 1328 | 0), | ||
| 1329 | ATOM_DEVICE_DFP1_SUPPORT); | ||
| 1330 | radeon_add_legacy_encoder(dev, | ||
| 1331 | radeon_get_encoder_id(dev, | ||
| 1332 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1333 | 1), | ||
| 1334 | ATOM_DEVICE_CRT1_SUPPORT); | ||
| 1335 | radeon_add_legacy_connector(dev, 1, | ||
| 1336 | ATOM_DEVICE_DFP1_SUPPORT | | ||
| 1337 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1338 | DRM_MODE_CONNECTOR_DVII, &ddc_i2c); | ||
| 1339 | /* TV - TV DAC */ | ||
| 1340 | radeon_add_legacy_encoder(dev, | ||
| 1341 | radeon_get_encoder_id(dev, | ||
| 1342 | ATOM_DEVICE_TV1_SUPPORT, | ||
| 1343 | 2), | ||
| 1344 | ATOM_DEVICE_TV1_SUPPORT); | ||
| 1345 | radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, | ||
| 1346 | DRM_MODE_CONNECTOR_SVIDEO, | ||
| 1347 | &ddc_i2c); | ||
| 1348 | break; | ||
| 1349 | case CT_POWERBOOK_VGA: | ||
| 1350 | DRM_INFO("Connector Table: %d (powerbook vga)\n", | ||
| 1351 | rdev->mode_info.connector_table); | ||
| 1352 | /* LVDS */ | ||
| 1353 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); | ||
| 1354 | radeon_add_legacy_encoder(dev, | ||
| 1355 | radeon_get_encoder_id(dev, | ||
| 1356 | ATOM_DEVICE_LCD1_SUPPORT, | ||
| 1357 | 0), | ||
| 1358 | ATOM_DEVICE_LCD1_SUPPORT); | ||
| 1359 | radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_LCD1_SUPPORT, | ||
| 1360 | DRM_MODE_CONNECTOR_LVDS, &ddc_i2c); | ||
| 1361 | /* VGA - primary dac */ | ||
| 1362 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); | ||
| 1363 | radeon_add_legacy_encoder(dev, | ||
| 1364 | radeon_get_encoder_id(dev, | ||
| 1365 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1366 | 1), | ||
| 1367 | ATOM_DEVICE_CRT1_SUPPORT); | ||
| 1368 | radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1369 | DRM_MODE_CONNECTOR_VGA, &ddc_i2c); | ||
| 1370 | /* TV - TV DAC */ | ||
| 1371 | radeon_add_legacy_encoder(dev, | ||
| 1372 | radeon_get_encoder_id(dev, | ||
| 1373 | ATOM_DEVICE_TV1_SUPPORT, | ||
| 1374 | 2), | ||
| 1375 | ATOM_DEVICE_TV1_SUPPORT); | ||
| 1376 | radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, | ||
| 1377 | DRM_MODE_CONNECTOR_SVIDEO, | ||
| 1378 | &ddc_i2c); | ||
| 1379 | break; | ||
| 1380 | case CT_MINI_EXTERNAL: | ||
| 1381 | DRM_INFO("Connector Table: %d (mini external tmds)\n", | ||
| 1382 | rdev->mode_info.connector_table); | ||
| 1383 | /* DVI-I - tv dac, ext tmds */ | ||
| 1384 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC); | ||
| 1385 | radeon_add_legacy_encoder(dev, | ||
| 1386 | radeon_get_encoder_id(dev, | ||
| 1387 | ATOM_DEVICE_DFP2_SUPPORT, | ||
| 1388 | 0), | ||
| 1389 | ATOM_DEVICE_DFP2_SUPPORT); | ||
| 1390 | radeon_add_legacy_encoder(dev, | ||
| 1391 | radeon_get_encoder_id(dev, | ||
| 1392 | ATOM_DEVICE_CRT2_SUPPORT, | ||
| 1393 | 2), | ||
| 1394 | ATOM_DEVICE_CRT2_SUPPORT); | ||
| 1395 | radeon_add_legacy_connector(dev, 0, | ||
| 1396 | ATOM_DEVICE_DFP2_SUPPORT | | ||
| 1397 | ATOM_DEVICE_CRT2_SUPPORT, | ||
| 1398 | DRM_MODE_CONNECTOR_DVII, &ddc_i2c); | ||
| 1399 | /* TV - TV DAC */ | ||
| 1400 | radeon_add_legacy_encoder(dev, | ||
| 1401 | radeon_get_encoder_id(dev, | ||
| 1402 | ATOM_DEVICE_TV1_SUPPORT, | ||
| 1403 | 2), | ||
| 1404 | ATOM_DEVICE_TV1_SUPPORT); | ||
| 1405 | radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT, | ||
| 1406 | DRM_MODE_CONNECTOR_SVIDEO, | ||
| 1407 | &ddc_i2c); | ||
| 1408 | break; | ||
| 1409 | case CT_MINI_INTERNAL: | ||
| 1410 | DRM_INFO("Connector Table: %d (mini internal tmds)\n", | ||
| 1411 | rdev->mode_info.connector_table); | ||
| 1412 | /* DVI-I - tv dac, int tmds */ | ||
| 1413 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC); | ||
| 1414 | radeon_add_legacy_encoder(dev, | ||
| 1415 | radeon_get_encoder_id(dev, | ||
| 1416 | ATOM_DEVICE_DFP1_SUPPORT, | ||
| 1417 | 0), | ||
| 1418 | ATOM_DEVICE_DFP1_SUPPORT); | ||
| 1419 | radeon_add_legacy_encoder(dev, | ||
| 1420 | radeon_get_encoder_id(dev, | ||
| 1421 | ATOM_DEVICE_CRT2_SUPPORT, | ||
| 1422 | 2), | ||
| 1423 | ATOM_DEVICE_CRT2_SUPPORT); | ||
| 1424 | radeon_add_legacy_connector(dev, 0, | ||
| 1425 | ATOM_DEVICE_DFP1_SUPPORT | | ||
| 1426 | ATOM_DEVICE_CRT2_SUPPORT, | ||
| 1427 | DRM_MODE_CONNECTOR_DVII, &ddc_i2c); | ||
| 1428 | /* TV - TV DAC */ | ||
| 1429 | radeon_add_legacy_encoder(dev, | ||
| 1430 | radeon_get_encoder_id(dev, | ||
| 1431 | ATOM_DEVICE_TV1_SUPPORT, | ||
| 1432 | 2), | ||
| 1433 | ATOM_DEVICE_TV1_SUPPORT); | ||
| 1434 | radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_TV1_SUPPORT, | ||
| 1435 | DRM_MODE_CONNECTOR_SVIDEO, | ||
| 1436 | &ddc_i2c); | ||
| 1437 | break; | ||
| 1438 | case CT_IMAC_G5_ISIGHT: | ||
| 1439 | DRM_INFO("Connector Table: %d (imac g5 isight)\n", | ||
| 1440 | rdev->mode_info.connector_table); | ||
| 1441 | /* DVI-D - int tmds */ | ||
| 1442 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID); | ||
| 1443 | radeon_add_legacy_encoder(dev, | ||
| 1444 | radeon_get_encoder_id(dev, | ||
| 1445 | ATOM_DEVICE_DFP1_SUPPORT, | ||
| 1446 | 0), | ||
| 1447 | ATOM_DEVICE_DFP1_SUPPORT); | ||
| 1448 | radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_DFP1_SUPPORT, | ||
| 1449 | DRM_MODE_CONNECTOR_DVID, &ddc_i2c); | ||
| 1450 | /* VGA - tv dac */ | ||
| 1451 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); | ||
| 1452 | radeon_add_legacy_encoder(dev, | ||
| 1453 | radeon_get_encoder_id(dev, | ||
| 1454 | ATOM_DEVICE_CRT2_SUPPORT, | ||
| 1455 | 2), | ||
| 1456 | ATOM_DEVICE_CRT2_SUPPORT); | ||
| 1457 | radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT, | ||
| 1458 | DRM_MODE_CONNECTOR_VGA, &ddc_i2c); | ||
| 1459 | /* TV - TV DAC */ | ||
| 1460 | radeon_add_legacy_encoder(dev, | ||
| 1461 | radeon_get_encoder_id(dev, | ||
| 1462 | ATOM_DEVICE_TV1_SUPPORT, | ||
| 1463 | 2), | ||
| 1464 | ATOM_DEVICE_TV1_SUPPORT); | ||
| 1465 | radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, | ||
| 1466 | DRM_MODE_CONNECTOR_SVIDEO, | ||
| 1467 | &ddc_i2c); | ||
| 1468 | break; | ||
| 1469 | case CT_EMAC: | ||
| 1470 | DRM_INFO("Connector Table: %d (emac)\n", | ||
| 1471 | rdev->mode_info.connector_table); | ||
| 1472 | /* VGA - primary dac */ | ||
| 1473 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); | ||
| 1474 | radeon_add_legacy_encoder(dev, | ||
| 1475 | radeon_get_encoder_id(dev, | ||
| 1476 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1477 | 1), | ||
| 1478 | ATOM_DEVICE_CRT1_SUPPORT); | ||
| 1479 | radeon_add_legacy_connector(dev, 0, ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1480 | DRM_MODE_CONNECTOR_VGA, &ddc_i2c); | ||
| 1481 | /* VGA - tv dac */ | ||
| 1482 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC); | ||
| 1483 | radeon_add_legacy_encoder(dev, | ||
| 1484 | radeon_get_encoder_id(dev, | ||
| 1485 | ATOM_DEVICE_CRT2_SUPPORT, | ||
| 1486 | 2), | ||
| 1487 | ATOM_DEVICE_CRT2_SUPPORT); | ||
| 1488 | radeon_add_legacy_connector(dev, 1, ATOM_DEVICE_CRT2_SUPPORT, | ||
| 1489 | DRM_MODE_CONNECTOR_VGA, &ddc_i2c); | ||
| 1490 | /* TV - TV DAC */ | ||
| 1491 | radeon_add_legacy_encoder(dev, | ||
| 1492 | radeon_get_encoder_id(dev, | ||
| 1493 | ATOM_DEVICE_TV1_SUPPORT, | ||
| 1494 | 2), | ||
| 1495 | ATOM_DEVICE_TV1_SUPPORT); | ||
| 1496 | radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, | ||
| 1497 | DRM_MODE_CONNECTOR_SVIDEO, | ||
| 1498 | &ddc_i2c); | ||
| 1499 | break; | ||
| 1500 | default: | ||
| 1501 | DRM_INFO("Connector table: %d (invalid)\n", | ||
| 1502 | rdev->mode_info.connector_table); | ||
| 1503 | return false; | ||
| 1504 | } | ||
| 1505 | |||
| 1506 | radeon_link_encoder_connector(dev); | ||
| 1507 | |||
| 1508 | return true; | ||
| 1509 | } | ||
| 1510 | |||
| 1511 | static bool radeon_apply_legacy_quirks(struct drm_device *dev, | ||
| 1512 | int bios_index, | ||
| 1513 | enum radeon_combios_connector | ||
| 1514 | *legacy_connector, | ||
| 1515 | struct radeon_i2c_bus_rec *ddc_i2c) | ||
| 1516 | { | ||
| 1517 | struct radeon_device *rdev = dev->dev_private; | ||
| 1518 | |||
| 1519 | /* XPRESS DDC quirks */ | ||
| 1520 | if ((rdev->family == CHIP_RS400 || | ||
| 1521 | rdev->family == CHIP_RS480) && | ||
| 1522 | ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC) | ||
| 1523 | *ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID); | ||
| 1524 | else if ((rdev->family == CHIP_RS400 || | ||
| 1525 | rdev->family == CHIP_RS480) && | ||
| 1526 | ddc_i2c->mask_clk_reg == RADEON_GPIO_MONID) { | ||
| 1527 | ddc_i2c->valid = true; | ||
| 1528 | ddc_i2c->mask_clk_mask = (0x20 << 8); | ||
| 1529 | ddc_i2c->mask_data_mask = 0x80; | ||
| 1530 | ddc_i2c->a_clk_mask = (0x20 << 8); | ||
| 1531 | ddc_i2c->a_data_mask = 0x80; | ||
| 1532 | ddc_i2c->put_clk_mask = (0x20 << 8); | ||
| 1533 | ddc_i2c->put_data_mask = 0x80; | ||
| 1534 | ddc_i2c->get_clk_mask = (0x20 << 8); | ||
| 1535 | ddc_i2c->get_data_mask = 0x80; | ||
| 1536 | ddc_i2c->mask_clk_reg = RADEON_GPIOPAD_MASK; | ||
| 1537 | ddc_i2c->mask_data_reg = RADEON_GPIOPAD_MASK; | ||
| 1538 | ddc_i2c->a_clk_reg = RADEON_GPIOPAD_A; | ||
| 1539 | ddc_i2c->a_data_reg = RADEON_GPIOPAD_A; | ||
| 1540 | ddc_i2c->put_clk_reg = RADEON_GPIOPAD_EN; | ||
| 1541 | ddc_i2c->put_data_reg = RADEON_GPIOPAD_EN; | ||
| 1542 | ddc_i2c->get_clk_reg = RADEON_LCD_GPIO_Y_REG; | ||
| 1543 | ddc_i2c->get_data_reg = RADEON_LCD_GPIO_Y_REG; | ||
| 1544 | } | ||
| 1545 | |||
| 1546 | /* Certain IBM chipset RN50s have a BIOS reporting two VGAs, | ||
| 1547 | one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */ | ||
| 1548 | if (dev->pdev->device == 0x515e && | ||
| 1549 | dev->pdev->subsystem_vendor == 0x1014) { | ||
| 1550 | if (*legacy_connector == CONNECTOR_CRT_LEGACY && | ||
| 1551 | ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC) | ||
| 1552 | return false; | ||
| 1553 | } | ||
| 1554 | |||
| 1555 | /* Some RV100 cards with 2 VGA ports show up with DVI+VGA */ | ||
| 1556 | if (dev->pdev->device == 0x5159 && | ||
| 1557 | dev->pdev->subsystem_vendor == 0x1002 && | ||
| 1558 | dev->pdev->subsystem_device == 0x013a) { | ||
| 1559 | if (*legacy_connector == CONNECTOR_DVI_I_LEGACY) | ||
| 1560 | *legacy_connector = CONNECTOR_CRT_LEGACY; | ||
| 1561 | |||
| 1562 | } | ||
| 1563 | |||
| 1564 | /* X300 card with extra non-existent DVI port */ | ||
| 1565 | if (dev->pdev->device == 0x5B60 && | ||
| 1566 | dev->pdev->subsystem_vendor == 0x17af && | ||
| 1567 | dev->pdev->subsystem_device == 0x201e && bios_index == 2) { | ||
| 1568 | if (*legacy_connector == CONNECTOR_DVI_I_LEGACY) | ||
| 1569 | return false; | ||
| 1570 | } | ||
| 1571 | |||
| 1572 | return true; | ||
| 1573 | } | ||
| 1574 | |||
| 1575 | bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) | ||
| 1576 | { | ||
| 1577 | struct radeon_device *rdev = dev->dev_private; | ||
| 1578 | uint32_t conn_info, entry, devices; | ||
| 1579 | uint16_t tmp; | ||
| 1580 | enum radeon_combios_ddc ddc_type; | ||
| 1581 | enum radeon_combios_connector connector; | ||
| 1582 | int i = 0; | ||
| 1583 | struct radeon_i2c_bus_rec ddc_i2c; | ||
| 1584 | |||
| 1585 | if (rdev->bios == NULL) | ||
| 1586 | return false; | ||
| 1587 | |||
| 1588 | conn_info = combios_get_table_offset(dev, COMBIOS_CONNECTOR_INFO_TABLE); | ||
| 1589 | if (conn_info) { | ||
| 1590 | for (i = 0; i < 4; i++) { | ||
| 1591 | entry = conn_info + 2 + i * 2; | ||
| 1592 | |||
| 1593 | if (!RBIOS16(entry)) | ||
| 1594 | break; | ||
| 1595 | |||
| 1596 | tmp = RBIOS16(entry); | ||
| 1597 | |||
| 1598 | connector = (tmp >> 12) & 0xf; | ||
| 1599 | |||
| 1600 | ddc_type = (tmp >> 8) & 0xf; | ||
| 1601 | switch (ddc_type) { | ||
| 1602 | case DDC_MONID: | ||
| 1603 | ddc_i2c = | ||
| 1604 | combios_setup_i2c_bus(RADEON_GPIO_MONID); | ||
| 1605 | break; | ||
| 1606 | case DDC_DVI: | ||
| 1607 | ddc_i2c = | ||
| 1608 | combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); | ||
| 1609 | break; | ||
| 1610 | case DDC_VGA: | ||
| 1611 | ddc_i2c = | ||
| 1612 | combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC); | ||
| 1613 | break; | ||
| 1614 | case DDC_CRT2: | ||
| 1615 | ddc_i2c = | ||
| 1616 | combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC); | ||
| 1617 | break; | ||
| 1618 | default: | ||
| 1619 | break; | ||
| 1620 | } | ||
| 1621 | |||
| 1622 | radeon_apply_legacy_quirks(dev, i, &connector, | ||
| 1623 | &ddc_i2c); | ||
| 1624 | |||
| 1625 | switch (connector) { | ||
| 1626 | case CONNECTOR_PROPRIETARY_LEGACY: | ||
| 1627 | if ((tmp >> 4) & 0x1) | ||
| 1628 | devices = ATOM_DEVICE_DFP2_SUPPORT; | ||
| 1629 | else | ||
| 1630 | devices = ATOM_DEVICE_DFP1_SUPPORT; | ||
| 1631 | radeon_add_legacy_encoder(dev, | ||
| 1632 | radeon_get_encoder_id | ||
| 1633 | (dev, devices, 0), | ||
| 1634 | devices); | ||
| 1635 | radeon_add_legacy_connector(dev, i, devices, | ||
| 1636 | legacy_connector_convert | ||
| 1637 | [connector], | ||
| 1638 | &ddc_i2c); | ||
| 1639 | break; | ||
| 1640 | case CONNECTOR_CRT_LEGACY: | ||
| 1641 | if (tmp & 0x1) { | ||
| 1642 | devices = ATOM_DEVICE_CRT2_SUPPORT; | ||
| 1643 | radeon_add_legacy_encoder(dev, | ||
| 1644 | radeon_get_encoder_id | ||
| 1645 | (dev, | ||
| 1646 | ATOM_DEVICE_CRT2_SUPPORT, | ||
| 1647 | 2), | ||
| 1648 | ATOM_DEVICE_CRT2_SUPPORT); | ||
| 1649 | } else { | ||
| 1650 | devices = ATOM_DEVICE_CRT1_SUPPORT; | ||
| 1651 | radeon_add_legacy_encoder(dev, | ||
| 1652 | radeon_get_encoder_id | ||
| 1653 | (dev, | ||
| 1654 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1655 | 1), | ||
| 1656 | ATOM_DEVICE_CRT1_SUPPORT); | ||
| 1657 | } | ||
| 1658 | radeon_add_legacy_connector(dev, | ||
| 1659 | i, | ||
| 1660 | devices, | ||
| 1661 | legacy_connector_convert | ||
| 1662 | [connector], | ||
| 1663 | &ddc_i2c); | ||
| 1664 | break; | ||
| 1665 | case CONNECTOR_DVI_I_LEGACY: | ||
| 1666 | devices = 0; | ||
| 1667 | if (tmp & 0x1) { | ||
| 1668 | devices |= ATOM_DEVICE_CRT2_SUPPORT; | ||
| 1669 | radeon_add_legacy_encoder(dev, | ||
| 1670 | radeon_get_encoder_id | ||
| 1671 | (dev, | ||
| 1672 | ATOM_DEVICE_CRT2_SUPPORT, | ||
| 1673 | 2), | ||
| 1674 | ATOM_DEVICE_CRT2_SUPPORT); | ||
| 1675 | } else { | ||
| 1676 | devices |= ATOM_DEVICE_CRT1_SUPPORT; | ||
| 1677 | radeon_add_legacy_encoder(dev, | ||
| 1678 | radeon_get_encoder_id | ||
| 1679 | (dev, | ||
| 1680 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1681 | 1), | ||
| 1682 | ATOM_DEVICE_CRT1_SUPPORT); | ||
| 1683 | } | ||
| 1684 | if ((tmp >> 4) & 0x1) { | ||
| 1685 | devices |= ATOM_DEVICE_DFP2_SUPPORT; | ||
| 1686 | radeon_add_legacy_encoder(dev, | ||
| 1687 | radeon_get_encoder_id | ||
| 1688 | (dev, | ||
| 1689 | ATOM_DEVICE_DFP2_SUPPORT, | ||
| 1690 | 0), | ||
| 1691 | ATOM_DEVICE_DFP2_SUPPORT); | ||
| 1692 | } else { | ||
| 1693 | devices |= ATOM_DEVICE_DFP1_SUPPORT; | ||
| 1694 | radeon_add_legacy_encoder(dev, | ||
| 1695 | radeon_get_encoder_id | ||
| 1696 | (dev, | ||
| 1697 | ATOM_DEVICE_DFP1_SUPPORT, | ||
| 1698 | 0), | ||
| 1699 | ATOM_DEVICE_DFP1_SUPPORT); | ||
| 1700 | } | ||
| 1701 | radeon_add_legacy_connector(dev, | ||
| 1702 | i, | ||
| 1703 | devices, | ||
| 1704 | legacy_connector_convert | ||
| 1705 | [connector], | ||
| 1706 | &ddc_i2c); | ||
| 1707 | break; | ||
| 1708 | case CONNECTOR_DVI_D_LEGACY: | ||
| 1709 | if ((tmp >> 4) & 0x1) | ||
| 1710 | devices = ATOM_DEVICE_DFP2_SUPPORT; | ||
| 1711 | else | ||
| 1712 | devices = ATOM_DEVICE_DFP1_SUPPORT; | ||
| 1713 | radeon_add_legacy_encoder(dev, | ||
| 1714 | radeon_get_encoder_id | ||
| 1715 | (dev, devices, 0), | ||
| 1716 | devices); | ||
| 1717 | radeon_add_legacy_connector(dev, i, devices, | ||
| 1718 | legacy_connector_convert | ||
| 1719 | [connector], | ||
| 1720 | &ddc_i2c); | ||
| 1721 | break; | ||
| 1722 | case CONNECTOR_CTV_LEGACY: | ||
| 1723 | case CONNECTOR_STV_LEGACY: | ||
| 1724 | radeon_add_legacy_encoder(dev, | ||
| 1725 | radeon_get_encoder_id | ||
| 1726 | (dev, | ||
| 1727 | ATOM_DEVICE_TV1_SUPPORT, | ||
| 1728 | 2), | ||
| 1729 | ATOM_DEVICE_TV1_SUPPORT); | ||
| 1730 | radeon_add_legacy_connector(dev, i, | ||
| 1731 | ATOM_DEVICE_TV1_SUPPORT, | ||
| 1732 | legacy_connector_convert | ||
| 1733 | [connector], | ||
| 1734 | &ddc_i2c); | ||
| 1735 | break; | ||
| 1736 | default: | ||
| 1737 | DRM_ERROR("Unknown connector type: %d\n", | ||
| 1738 | connector); | ||
| 1739 | continue; | ||
| 1740 | } | ||
| 1741 | |||
| 1742 | } | ||
| 1743 | } else { | ||
| 1744 | uint16_t tmds_info = | ||
| 1745 | combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE); | ||
| 1746 | if (tmds_info) { | ||
| 1747 | DRM_DEBUG("Found DFP table, assuming DVI connector\n"); | ||
| 1748 | |||
| 1749 | radeon_add_legacy_encoder(dev, | ||
| 1750 | radeon_get_encoder_id(dev, | ||
| 1751 | ATOM_DEVICE_CRT1_SUPPORT, | ||
| 1752 | 1), | ||
| 1753 | ATOM_DEVICE_CRT1_SUPPORT); | ||
| 1754 | radeon_add_legacy_encoder(dev, | ||
| 1755 | radeon_get_encoder_id(dev, | ||
| 1756 | ATOM_DEVICE_DFP1_SUPPORT, | ||
| 1757 | 0), | ||
| 1758 | ATOM_DEVICE_DFP1_SUPPORT); | ||
| 1759 | |||
| 1760 | ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC); | ||
| 1761 | radeon_add_legacy_connector(dev, | ||
| 1762 | 0, | ||
| 1763 | ATOM_DEVICE_CRT1_SUPPORT | | ||
| 1764 | ATOM_DEVICE_DFP1_SUPPORT, | ||
| 1765 | DRM_MODE_CONNECTOR_DVII, | ||
| 1766 | &ddc_i2c); | ||
| 1767 | } else { | ||
| 1768 | DRM_DEBUG("No connector info found\n"); | ||
| 1769 | return false; | ||
| 1770 | } | ||
| 1771 | } | ||
| 1772 | |||
| 1773 | if (rdev->flags & RADEON_IS_MOBILITY || rdev->flags & RADEON_IS_IGP) { | ||
| 1774 | uint16_t lcd_info = | ||
| 1775 | combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE); | ||
| 1776 | if (lcd_info) { | ||
| 1777 | uint16_t lcd_ddc_info = | ||
| 1778 | combios_get_table_offset(dev, | ||
| 1779 | COMBIOS_LCD_DDC_INFO_TABLE); | ||
| 1780 | |||
| 1781 | radeon_add_legacy_encoder(dev, | ||
| 1782 | radeon_get_encoder_id(dev, | ||
| 1783 | ATOM_DEVICE_LCD1_SUPPORT, | ||
| 1784 | 0), | ||
| 1785 | ATOM_DEVICE_LCD1_SUPPORT); | ||
| 1786 | |||
| 1787 | if (lcd_ddc_info) { | ||
| 1788 | ddc_type = RBIOS8(lcd_ddc_info + 2); | ||
| 1789 | switch (ddc_type) { | ||
| 1790 | case DDC_MONID: | ||
| 1791 | ddc_i2c = | ||
| 1792 | combios_setup_i2c_bus | ||
| 1793 | (RADEON_GPIO_MONID); | ||
| 1794 | break; | ||
| 1795 | case DDC_DVI: | ||
| 1796 | ddc_i2c = | ||
| 1797 | combios_setup_i2c_bus | ||
| 1798 | (RADEON_GPIO_DVI_DDC); | ||
| 1799 | break; | ||
| 1800 | case DDC_VGA: | ||
| 1801 | ddc_i2c = | ||
| 1802 | combios_setup_i2c_bus | ||
| 1803 | (RADEON_GPIO_VGA_DDC); | ||
| 1804 | break; | ||
| 1805 | case DDC_CRT2: | ||
| 1806 | ddc_i2c = | ||
| 1807 | combios_setup_i2c_bus | ||
| 1808 | (RADEON_GPIO_CRT2_DDC); | ||
| 1809 | break; | ||
| 1810 | case DDC_LCD: | ||
| 1811 | ddc_i2c = | ||
| 1812 | combios_setup_i2c_bus | ||
| 1813 | (RADEON_LCD_GPIO_MASK); | ||
| 1814 | ddc_i2c.mask_clk_mask = | ||
| 1815 | RBIOS32(lcd_ddc_info + 3); | ||
| 1816 | ddc_i2c.mask_data_mask = | ||
| 1817 | RBIOS32(lcd_ddc_info + 7); | ||
| 1818 | ddc_i2c.a_clk_mask = | ||
| 1819 | RBIOS32(lcd_ddc_info + 3); | ||
| 1820 | ddc_i2c.a_data_mask = | ||
| 1821 | RBIOS32(lcd_ddc_info + 7); | ||
| 1822 | ddc_i2c.put_clk_mask = | ||
| 1823 | RBIOS32(lcd_ddc_info + 3); | ||
| 1824 | ddc_i2c.put_data_mask = | ||
| 1825 | RBIOS32(lcd_ddc_info + 7); | ||
| 1826 | ddc_i2c.get_clk_mask = | ||
| 1827 | RBIOS32(lcd_ddc_info + 3); | ||
| 1828 | ddc_i2c.get_data_mask = | ||
| 1829 | RBIOS32(lcd_ddc_info + 7); | ||
| 1830 | break; | ||
| 1831 | case DDC_GPIO: | ||
| 1832 | ddc_i2c = | ||
| 1833 | combios_setup_i2c_bus | ||
| 1834 | (RADEON_MDGPIO_EN_REG); | ||
| 1835 | ddc_i2c.mask_clk_mask = | ||
| 1836 | RBIOS32(lcd_ddc_info + 3); | ||
| 1837 | ddc_i2c.mask_data_mask = | ||
| 1838 | RBIOS32(lcd_ddc_info + 7); | ||
| 1839 | ddc_i2c.a_clk_mask = | ||
| 1840 | RBIOS32(lcd_ddc_info + 3); | ||
| 1841 | ddc_i2c.a_data_mask = | ||
| 1842 | RBIOS32(lcd_ddc_info + 7); | ||
| 1843 | ddc_i2c.put_clk_mask = | ||
| 1844 | RBIOS32(lcd_ddc_info + 3); | ||
| 1845 | ddc_i2c.put_data_mask = | ||
| 1846 | RBIOS32(lcd_ddc_info + 7); | ||
| 1847 | ddc_i2c.get_clk_mask = | ||
| 1848 | RBIOS32(lcd_ddc_info + 3); | ||
| 1849 | ddc_i2c.get_data_mask = | ||
| 1850 | RBIOS32(lcd_ddc_info + 7); | ||
| 1851 | break; | ||
| 1852 | default: | ||
| 1853 | ddc_i2c.valid = false; | ||
| 1854 | break; | ||
| 1855 | } | ||
| 1856 | DRM_DEBUG("LCD DDC Info Table found!\n"); | ||
| 1857 | } else | ||
| 1858 | ddc_i2c.valid = false; | ||
| 1859 | |||
| 1860 | radeon_add_legacy_connector(dev, | ||
| 1861 | 5, | ||
| 1862 | ATOM_DEVICE_LCD1_SUPPORT, | ||
| 1863 | DRM_MODE_CONNECTOR_LVDS, | ||
| 1864 | &ddc_i2c); | ||
| 1865 | } | ||
| 1866 | } | ||
| 1867 | |||
| 1868 | /* check TV table */ | ||
| 1869 | if (rdev->family != CHIP_R100 && rdev->family != CHIP_R200) { | ||
| 1870 | uint32_t tv_info = | ||
| 1871 | combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE); | ||
| 1872 | if (tv_info) { | ||
| 1873 | if (RBIOS8(tv_info + 6) == 'T') { | ||
| 1874 | radeon_add_legacy_encoder(dev, | ||
| 1875 | radeon_get_encoder_id | ||
| 1876 | (dev, | ||
| 1877 | ATOM_DEVICE_TV1_SUPPORT, | ||
| 1878 | 2), | ||
| 1879 | ATOM_DEVICE_TV1_SUPPORT); | ||
| 1880 | radeon_add_legacy_connector(dev, 6, | ||
| 1881 | ATOM_DEVICE_TV1_SUPPORT, | ||
| 1882 | DRM_MODE_CONNECTOR_SVIDEO, | ||
| 1883 | &ddc_i2c); | ||
| 1884 | } | ||
| 1885 | } | ||
| 1886 | } | ||
| 1887 | |||
| 1888 | radeon_link_encoder_connector(dev); | ||
| 1889 | |||
| 1890 | return true; | ||
| 1891 | } | ||
| 1892 | |||
| 1893 | static void combios_parse_mmio_table(struct drm_device *dev, uint16_t offset) | ||
| 1894 | { | ||
| 1895 | struct radeon_device *rdev = dev->dev_private; | ||
| 1896 | |||
| 1897 | if (offset) { | ||
| 1898 | while (RBIOS16(offset)) { | ||
| 1899 | uint16_t cmd = ((RBIOS16(offset) & 0xe000) >> 13); | ||
| 1900 | uint32_t addr = (RBIOS16(offset) & 0x1fff); | ||
| 1901 | uint32_t val, and_mask, or_mask; | ||
| 1902 | uint32_t tmp; | ||
| 1903 | |||
| 1904 | offset += 2; | ||
| 1905 | switch (cmd) { | ||
| 1906 | case 0: | ||
| 1907 | val = RBIOS32(offset); | ||
| 1908 | offset += 4; | ||
| 1909 | WREG32(addr, val); | ||
| 1910 | break; | ||
| 1911 | case 1: | ||
| 1912 | val = RBIOS32(offset); | ||
| 1913 | offset += 4; | ||
| 1914 | WREG32(addr, val); | ||
| 1915 | break; | ||
| 1916 | case 2: | ||
| 1917 | and_mask = RBIOS32(offset); | ||
| 1918 | offset += 4; | ||
| 1919 | or_mask = RBIOS32(offset); | ||
| 1920 | offset += 4; | ||
| 1921 | tmp = RREG32(addr); | ||
| 1922 | tmp &= and_mask; | ||
| 1923 | tmp |= or_mask; | ||
| 1924 | WREG32(addr, tmp); | ||
| 1925 | break; | ||
| 1926 | case 3: | ||
| 1927 | and_mask = RBIOS32(offset); | ||
| 1928 | offset += 4; | ||
| 1929 | or_mask = RBIOS32(offset); | ||
| 1930 | offset += 4; | ||
| 1931 | tmp = RREG32(addr); | ||
| 1932 | tmp &= and_mask; | ||
| 1933 | tmp |= or_mask; | ||
| 1934 | WREG32(addr, tmp); | ||
| 1935 | break; | ||
| 1936 | case 4: | ||
| 1937 | val = RBIOS16(offset); | ||
| 1938 | offset += 2; | ||
| 1939 | udelay(val); | ||
| 1940 | break; | ||
| 1941 | case 5: | ||
| 1942 | val = RBIOS16(offset); | ||
| 1943 | offset += 2; | ||
| 1944 | switch (addr) { | ||
| 1945 | case 8: | ||
| 1946 | while (val--) { | ||
| 1947 | if (! | ||
| 1948 | (RREG32_PLL | ||
| 1949 | (RADEON_CLK_PWRMGT_CNTL) & | ||
| 1950 | RADEON_MC_BUSY)) | ||
| 1951 | break; | ||
| 1952 | } | ||
| 1953 | break; | ||
| 1954 | case 9: | ||
| 1955 | while (val--) { | ||
| 1956 | if ((RREG32(RADEON_MC_STATUS) & | ||
| 1957 | RADEON_MC_IDLE)) | ||
| 1958 | break; | ||
| 1959 | } | ||
| 1960 | break; | ||
| 1961 | default: | ||
| 1962 | break; | ||
| 1963 | } | ||
| 1964 | break; | ||
| 1965 | default: | ||
| 1966 | break; | ||
| 1967 | } | ||
| 1968 | } | ||
| 1969 | } | ||
| 1970 | } | ||
| 1971 | |||
| 1972 | static void combios_parse_pll_table(struct drm_device *dev, uint16_t offset) | ||
| 1973 | { | ||
| 1974 | struct radeon_device *rdev = dev->dev_private; | ||
| 1975 | |||
| 1976 | if (offset) { | ||
| 1977 | while (RBIOS8(offset)) { | ||
| 1978 | uint8_t cmd = ((RBIOS8(offset) & 0xc0) >> 6); | ||
| 1979 | uint8_t addr = (RBIOS8(offset) & 0x3f); | ||
| 1980 | uint32_t val, shift, tmp; | ||
| 1981 | uint32_t and_mask, or_mask; | ||
| 1982 | |||
| 1983 | offset++; | ||
| 1984 | switch (cmd) { | ||
| 1985 | case 0: | ||
| 1986 | val = RBIOS32(offset); | ||
| 1987 | offset += 4; | ||
| 1988 | WREG32_PLL(addr, val); | ||
| 1989 | break; | ||
| 1990 | case 1: | ||
| 1991 | shift = RBIOS8(offset) * 8; | ||
| 1992 | offset++; | ||
| 1993 | and_mask = RBIOS8(offset) << shift; | ||
| 1994 | and_mask |= ~(0xff << shift); | ||
| 1995 | offset++; | ||
| 1996 | or_mask = RBIOS8(offset) << shift; | ||
| 1997 | offset++; | ||
| 1998 | tmp = RREG32_PLL(addr); | ||
| 1999 | tmp &= and_mask; | ||
| 2000 | tmp |= or_mask; | ||
| 2001 | WREG32_PLL(addr, tmp); | ||
| 2002 | break; | ||
| 2003 | case 2: | ||
| 2004 | case 3: | ||
| 2005 | tmp = 1000; | ||
| 2006 | switch (addr) { | ||
| 2007 | case 1: | ||
| 2008 | udelay(150); | ||
| 2009 | break; | ||
| 2010 | case 2: | ||
| 2011 | udelay(1000); | ||
| 2012 | break; | ||
| 2013 | case 3: | ||
| 2014 | while (tmp--) { | ||
| 2015 | if (! | ||
| 2016 | (RREG32_PLL | ||
| 2017 | (RADEON_CLK_PWRMGT_CNTL) & | ||
| 2018 | RADEON_MC_BUSY)) | ||
| 2019 | break; | ||
| 2020 | } | ||
| 2021 | break; | ||
| 2022 | case 4: | ||
| 2023 | while (tmp--) { | ||
| 2024 | if (RREG32_PLL | ||
| 2025 | (RADEON_CLK_PWRMGT_CNTL) & | ||
| 2026 | RADEON_DLL_READY) | ||
| 2027 | break; | ||
| 2028 | } | ||
| 2029 | break; | ||
| 2030 | case 5: | ||
| 2031 | tmp = | ||
| 2032 | RREG32_PLL(RADEON_CLK_PWRMGT_CNTL); | ||
| 2033 | if (tmp & RADEON_CG_NO1_DEBUG_0) { | ||
| 2034 | #if 0 | ||
| 2035 | uint32_t mclk_cntl = | ||
| 2036 | RREG32_PLL | ||
| 2037 | (RADEON_MCLK_CNTL); | ||
| 2038 | mclk_cntl &= 0xffff0000; | ||
| 2039 | /*mclk_cntl |= 0x00001111;*//* ??? */ | ||
| 2040 | WREG32_PLL(RADEON_MCLK_CNTL, | ||
| 2041 | mclk_cntl); | ||
| 2042 | udelay(10000); | ||
| 2043 | #endif | ||
| 2044 | WREG32_PLL | ||
| 2045 | (RADEON_CLK_PWRMGT_CNTL, | ||
| 2046 | tmp & | ||
| 2047 | ~RADEON_CG_NO1_DEBUG_0); | ||
| 2048 | udelay(10000); | ||
| 2049 | } | ||
| 2050 | break; | ||
| 2051 | default: | ||
| 2052 | break; | ||
| 2053 | } | ||
| 2054 | break; | ||
| 2055 | default: | ||
| 2056 | break; | ||
| 2057 | } | ||
| 2058 | } | ||
| 2059 | } | ||
| 2060 | } | ||
| 2061 | |||
| 2062 | static void combios_parse_ram_reset_table(struct drm_device *dev, | ||
| 2063 | uint16_t offset) | ||
| 2064 | { | ||
| 2065 | struct radeon_device *rdev = dev->dev_private; | ||
| 2066 | uint32_t tmp; | ||
| 2067 | |||
| 2068 | if (offset) { | ||
| 2069 | uint8_t val = RBIOS8(offset); | ||
| 2070 | while (val != 0xff) { | ||
| 2071 | offset++; | ||
| 2072 | |||
| 2073 | if (val == 0x0f) { | ||
| 2074 | uint32_t channel_complete_mask; | ||
| 2075 | |||
| 2076 | if (ASIC_IS_R300(rdev)) | ||
| 2077 | channel_complete_mask = | ||
| 2078 | R300_MEM_PWRUP_COMPLETE; | ||
| 2079 | else | ||
| 2080 | channel_complete_mask = | ||
| 2081 | RADEON_MEM_PWRUP_COMPLETE; | ||
| 2082 | tmp = 20000; | ||
| 2083 | while (tmp--) { | ||
| 2084 | if ((RREG32(RADEON_MEM_STR_CNTL) & | ||
| 2085 | channel_complete_mask) == | ||
| 2086 | channel_complete_mask) | ||
| 2087 | break; | ||
| 2088 | } | ||
| 2089 | } else { | ||
| 2090 | uint32_t or_mask = RBIOS16(offset); | ||
| 2091 | offset += 2; | ||
| 2092 | |||
| 2093 | tmp = RREG32(RADEON_MEM_SDRAM_MODE_REG); | ||
| 2094 | tmp &= RADEON_SDRAM_MODE_MASK; | ||
| 2095 | tmp |= or_mask; | ||
| 2096 | WREG32(RADEON_MEM_SDRAM_MODE_REG, tmp); | ||
| 2097 | |||
| 2098 | or_mask = val << 24; | ||
| 2099 | tmp = RREG32(RADEON_MEM_SDRAM_MODE_REG); | ||
| 2100 | tmp &= RADEON_B3MEM_RESET_MASK; | ||
| 2101 | tmp |= or_mask; | ||
| 2102 | WREG32(RADEON_MEM_SDRAM_MODE_REG, tmp); | ||
| 2103 | } | ||
| 2104 | val = RBIOS8(offset); | ||
| 2105 | } | ||
| 2106 | } | ||
| 2107 | } | ||
| 2108 | |||
| 2109 | static uint32_t combios_detect_ram(struct drm_device *dev, int ram, | ||
| 2110 | int mem_addr_mapping) | ||
| 2111 | { | ||
| 2112 | struct radeon_device *rdev = dev->dev_private; | ||
| 2113 | uint32_t mem_cntl; | ||
| 2114 | uint32_t mem_size; | ||
| 2115 | uint32_t addr = 0; | ||
| 2116 | |||
| 2117 | mem_cntl = RREG32(RADEON_MEM_CNTL); | ||
| 2118 | if (mem_cntl & RV100_HALF_MODE) | ||
| 2119 | ram /= 2; | ||
| 2120 | mem_size = ram; | ||
| 2121 | mem_cntl &= ~(0xff << 8); | ||
| 2122 | mem_cntl |= (mem_addr_mapping & 0xff) << 8; | ||
| 2123 | WREG32(RADEON_MEM_CNTL, mem_cntl); | ||
| 2124 | RREG32(RADEON_MEM_CNTL); | ||
| 2125 | |||
| 2126 | /* sdram reset ? */ | ||
| 2127 | |||
| 2128 | /* something like this???? */ | ||
| 2129 | while (ram--) { | ||
| 2130 | addr = ram * 1024 * 1024; | ||
| 2131 | /* write to each page */ | ||
| 2132 | WREG32(RADEON_MM_INDEX, (addr) | RADEON_MM_APER); | ||
| 2133 | WREG32(RADEON_MM_DATA, 0xdeadbeef); | ||
| 2134 | /* read back and verify */ | ||
| 2135 | WREG32(RADEON_MM_INDEX, (addr) | RADEON_MM_APER); | ||
| 2136 | if (RREG32(RADEON_MM_DATA) != 0xdeadbeef) | ||
| 2137 | return 0; | ||
| 2138 | } | ||
| 2139 | |||
| 2140 | return mem_size; | ||
| 2141 | } | ||
| 2142 | |||
| 2143 | static void combios_write_ram_size(struct drm_device *dev) | ||
| 2144 | { | ||
| 2145 | struct radeon_device *rdev = dev->dev_private; | ||
| 2146 | uint8_t rev; | ||
| 2147 | uint16_t offset; | ||
| 2148 | uint32_t mem_size = 0; | ||
| 2149 | uint32_t mem_cntl = 0; | ||
| 2150 | |||
| 2151 | /* should do something smarter here I guess... */ | ||
| 2152 | if (rdev->flags & RADEON_IS_IGP) | ||
| 2153 | return; | ||
| 2154 | |||
| 2155 | /* first check detected mem table */ | ||
| 2156 | offset = combios_get_table_offset(dev, COMBIOS_DETECTED_MEM_TABLE); | ||
| 2157 | if (offset) { | ||
| 2158 | rev = RBIOS8(offset); | ||
| 2159 | if (rev < 3) { | ||
| 2160 | mem_cntl = RBIOS32(offset + 1); | ||
| 2161 | mem_size = RBIOS16(offset + 5); | ||
| 2162 | if (((rdev->flags & RADEON_FAMILY_MASK) < CHIP_R200) && | ||
| 2163 | ((dev->pdev->device != 0x515e) | ||
| 2164 | && (dev->pdev->device != 0x5969))) | ||
| 2165 | WREG32(RADEON_MEM_CNTL, mem_cntl); | ||
| 2166 | } | ||
| 2167 | } | ||
| 2168 | |||
| 2169 | if (!mem_size) { | ||
| 2170 | offset = | ||
| 2171 | combios_get_table_offset(dev, COMBIOS_MEM_CONFIG_TABLE); | ||
| 2172 | if (offset) { | ||
| 2173 | rev = RBIOS8(offset - 1); | ||
| 2174 | if (rev < 1) { | ||
| 2175 | if (((rdev->flags & RADEON_FAMILY_MASK) < | ||
| 2176 | CHIP_R200) | ||
| 2177 | && ((dev->pdev->device != 0x515e) | ||
| 2178 | && (dev->pdev->device != 0x5969))) { | ||
| 2179 | int ram = 0; | ||
| 2180 | int mem_addr_mapping = 0; | ||
| 2181 | |||
| 2182 | while (RBIOS8(offset)) { | ||
| 2183 | ram = RBIOS8(offset); | ||
| 2184 | mem_addr_mapping = | ||
| 2185 | RBIOS8(offset + 1); | ||
| 2186 | if (mem_addr_mapping != 0x25) | ||
| 2187 | ram *= 2; | ||
| 2188 | mem_size = | ||
| 2189 | combios_detect_ram(dev, ram, | ||
| 2190 | mem_addr_mapping); | ||
| 2191 | if (mem_size) | ||
| 2192 | break; | ||
| 2193 | offset += 2; | ||
| 2194 | } | ||
| 2195 | } else | ||
| 2196 | mem_size = RBIOS8(offset); | ||
| 2197 | } else { | ||
| 2198 | mem_size = RBIOS8(offset); | ||
| 2199 | mem_size *= 2; /* convert to MB */ | ||
| 2200 | } | ||
| 2201 | } | ||
| 2202 | } | ||
| 2203 | |||
| 2204 | mem_size *= (1024 * 1024); /* convert to bytes */ | ||
| 2205 | WREG32(RADEON_CONFIG_MEMSIZE, mem_size); | ||
| 2206 | } | ||
| 2207 | |||
| 2208 | void radeon_combios_dyn_clk_setup(struct drm_device *dev, int enable) | ||
| 2209 | { | ||
| 2210 | uint16_t dyn_clk_info = | ||
| 2211 | combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE); | ||
| 2212 | |||
| 2213 | if (dyn_clk_info) | ||
| 2214 | combios_parse_pll_table(dev, dyn_clk_info); | ||
| 2215 | } | ||
| 2216 | |||
| 2217 | void radeon_combios_asic_init(struct drm_device *dev) | ||
| 2218 | { | ||
| 2219 | struct radeon_device *rdev = dev->dev_private; | ||
| 2220 | uint16_t table; | ||
| 2221 | |||
| 2222 | /* port hardcoded mac stuff from radeonfb */ | ||
| 2223 | if (rdev->bios == NULL) | ||
| 2224 | return; | ||
| 2225 | |||
| 2226 | /* ASIC INIT 1 */ | ||
| 2227 | table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_1_TABLE); | ||
| 2228 | if (table) | ||
| 2229 | combios_parse_mmio_table(dev, table); | ||
| 2230 | |||
| 2231 | /* PLL INIT */ | ||
| 2232 | table = combios_get_table_offset(dev, COMBIOS_PLL_INIT_TABLE); | ||
| 2233 | if (table) | ||
| 2234 | combios_parse_pll_table(dev, table); | ||
| 2235 | |||
| 2236 | /* ASIC INIT 2 */ | ||
| 2237 | table = combios_get_table_offset(dev, COMBIOS_ASIC_INIT_2_TABLE); | ||
| 2238 | if (table) | ||
| 2239 | combios_parse_mmio_table(dev, table); | ||
| 2240 | |||
| 2241 | if (!(rdev->flags & RADEON_IS_IGP)) { | ||
| 2242 | /* ASIC INIT 4 */ | ||
| 2243 | table = | ||
| 2244 | combios_get_table_offset(dev, COMBIOS_ASIC_INIT_4_TABLE); | ||
| 2245 | if (table) | ||
| 2246 | combios_parse_mmio_table(dev, table); | ||
| 2247 | |||
| 2248 | /* RAM RESET */ | ||
| 2249 | table = combios_get_table_offset(dev, COMBIOS_RAM_RESET_TABLE); | ||
| 2250 | if (table) | ||
| 2251 | combios_parse_ram_reset_table(dev, table); | ||
| 2252 | |||
| 2253 | /* ASIC INIT 3 */ | ||
| 2254 | table = | ||
| 2255 | combios_get_table_offset(dev, COMBIOS_ASIC_INIT_3_TABLE); | ||
| 2256 | if (table) | ||
| 2257 | combios_parse_mmio_table(dev, table); | ||
| 2258 | |||
| 2259 | /* write CONFIG_MEMSIZE */ | ||
| 2260 | combios_write_ram_size(dev); | ||
| 2261 | } | ||
| 2262 | |||
| 2263 | /* DYN CLK 1 */ | ||
| 2264 | table = combios_get_table_offset(dev, COMBIOS_DYN_CLK_1_TABLE); | ||
| 2265 | if (table) | ||
| 2266 | combios_parse_pll_table(dev, table); | ||
| 2267 | |||
| 2268 | } | ||
| 2269 | |||
| 2270 | void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev) | ||
| 2271 | { | ||
| 2272 | struct radeon_device *rdev = dev->dev_private; | ||
| 2273 | uint32_t bios_0_scratch, bios_6_scratch, bios_7_scratch; | ||
| 2274 | |||
| 2275 | bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH); | ||
| 2276 | bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); | ||
| 2277 | bios_7_scratch = RREG32(RADEON_BIOS_7_SCRATCH); | ||
| 2278 | |||
| 2279 | /* let the bios control the backlight */ | ||
| 2280 | bios_0_scratch &= ~RADEON_DRIVER_BRIGHTNESS_EN; | ||
| 2281 | |||
| 2282 | /* tell the bios not to handle mode switching */ | ||
| 2283 | bios_6_scratch |= (RADEON_DISPLAY_SWITCHING_DIS | | ||
| 2284 | RADEON_ACC_MODE_CHANGE); | ||
| 2285 | |||
| 2286 | /* tell the bios a driver is loaded */ | ||
| 2287 | bios_7_scratch |= RADEON_DRV_LOADED; | ||
| 2288 | |||
| 2289 | WREG32(RADEON_BIOS_0_SCRATCH, bios_0_scratch); | ||
| 2290 | WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch); | ||
| 2291 | WREG32(RADEON_BIOS_7_SCRATCH, bios_7_scratch); | ||
| 2292 | } | ||
| 2293 | |||
| 2294 | void radeon_combios_output_lock(struct drm_encoder *encoder, bool lock) | ||
| 2295 | { | ||
| 2296 | struct drm_device *dev = encoder->dev; | ||
| 2297 | struct radeon_device *rdev = dev->dev_private; | ||
| 2298 | uint32_t bios_6_scratch; | ||
| 2299 | |||
| 2300 | bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); | ||
| 2301 | |||
| 2302 | if (lock) | ||
| 2303 | bios_6_scratch |= RADEON_DRIVER_CRITICAL; | ||
| 2304 | else | ||
| 2305 | bios_6_scratch &= ~RADEON_DRIVER_CRITICAL; | ||
| 2306 | |||
| 2307 | WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch); | ||
| 2308 | } | ||
| 2309 | |||
| 2310 | void | ||
| 2311 | radeon_combios_connected_scratch_regs(struct drm_connector *connector, | ||
| 2312 | struct drm_encoder *encoder, | ||
| 2313 | bool connected) | ||
| 2314 | { | ||
| 2315 | struct drm_device *dev = connector->dev; | ||
| 2316 | struct radeon_device *rdev = dev->dev_private; | ||
| 2317 | struct radeon_connector *radeon_connector = | ||
| 2318 | to_radeon_connector(connector); | ||
| 2319 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 2320 | uint32_t bios_4_scratch = RREG32(RADEON_BIOS_4_SCRATCH); | ||
| 2321 | uint32_t bios_5_scratch = RREG32(RADEON_BIOS_5_SCRATCH); | ||
| 2322 | |||
| 2323 | if ((radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) && | ||
| 2324 | (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT)) { | ||
| 2325 | if (connected) { | ||
| 2326 | DRM_DEBUG("TV1 connected\n"); | ||
| 2327 | /* fix me */ | ||
| 2328 | bios_4_scratch |= RADEON_TV1_ATTACHED_SVIDEO; | ||
| 2329 | /*save->bios_4_scratch |= RADEON_TV1_ATTACHED_COMP; */ | ||
| 2330 | bios_5_scratch |= RADEON_TV1_ON; | ||
| 2331 | bios_5_scratch |= RADEON_ACC_REQ_TV1; | ||
| 2332 | } else { | ||
| 2333 | DRM_DEBUG("TV1 disconnected\n"); | ||
| 2334 | bios_4_scratch &= ~RADEON_TV1_ATTACHED_MASK; | ||
| 2335 | bios_5_scratch &= ~RADEON_TV1_ON; | ||
| 2336 | bios_5_scratch &= ~RADEON_ACC_REQ_TV1; | ||
| 2337 | } | ||
| 2338 | } | ||
| 2339 | if ((radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) && | ||
| 2340 | (radeon_connector->devices & ATOM_DEVICE_LCD1_SUPPORT)) { | ||
| 2341 | if (connected) { | ||
| 2342 | DRM_DEBUG("LCD1 connected\n"); | ||
| 2343 | bios_4_scratch |= RADEON_LCD1_ATTACHED; | ||
| 2344 | bios_5_scratch |= RADEON_LCD1_ON; | ||
| 2345 | bios_5_scratch |= RADEON_ACC_REQ_LCD1; | ||
| 2346 | } else { | ||
| 2347 | DRM_DEBUG("LCD1 disconnected\n"); | ||
| 2348 | bios_4_scratch &= ~RADEON_LCD1_ATTACHED; | ||
| 2349 | bios_5_scratch &= ~RADEON_LCD1_ON; | ||
| 2350 | bios_5_scratch &= ~RADEON_ACC_REQ_LCD1; | ||
| 2351 | } | ||
| 2352 | } | ||
| 2353 | if ((radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) && | ||
| 2354 | (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)) { | ||
| 2355 | if (connected) { | ||
| 2356 | DRM_DEBUG("CRT1 connected\n"); | ||
| 2357 | bios_4_scratch |= RADEON_CRT1_ATTACHED_COLOR; | ||
| 2358 | bios_5_scratch |= RADEON_CRT1_ON; | ||
| 2359 | bios_5_scratch |= RADEON_ACC_REQ_CRT1; | ||
| 2360 | } else { | ||
| 2361 | DRM_DEBUG("CRT1 disconnected\n"); | ||
| 2362 | bios_4_scratch &= ~RADEON_CRT1_ATTACHED_MASK; | ||
| 2363 | bios_5_scratch &= ~RADEON_CRT1_ON; | ||
| 2364 | bios_5_scratch &= ~RADEON_ACC_REQ_CRT1; | ||
| 2365 | } | ||
| 2366 | } | ||
| 2367 | if ((radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) && | ||
| 2368 | (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)) { | ||
| 2369 | if (connected) { | ||
| 2370 | DRM_DEBUG("CRT2 connected\n"); | ||
| 2371 | bios_4_scratch |= RADEON_CRT2_ATTACHED_COLOR; | ||
| 2372 | bios_5_scratch |= RADEON_CRT2_ON; | ||
| 2373 | bios_5_scratch |= RADEON_ACC_REQ_CRT2; | ||
| 2374 | } else { | ||
| 2375 | DRM_DEBUG("CRT2 disconnected\n"); | ||
| 2376 | bios_4_scratch &= ~RADEON_CRT2_ATTACHED_MASK; | ||
| 2377 | bios_5_scratch &= ~RADEON_CRT2_ON; | ||
| 2378 | bios_5_scratch &= ~RADEON_ACC_REQ_CRT2; | ||
| 2379 | } | ||
| 2380 | } | ||
| 2381 | if ((radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) && | ||
| 2382 | (radeon_connector->devices & ATOM_DEVICE_DFP1_SUPPORT)) { | ||
| 2383 | if (connected) { | ||
| 2384 | DRM_DEBUG("DFP1 connected\n"); | ||
| 2385 | bios_4_scratch |= RADEON_DFP1_ATTACHED; | ||
| 2386 | bios_5_scratch |= RADEON_DFP1_ON; | ||
| 2387 | bios_5_scratch |= RADEON_ACC_REQ_DFP1; | ||
| 2388 | } else { | ||
| 2389 | DRM_DEBUG("DFP1 disconnected\n"); | ||
| 2390 | bios_4_scratch &= ~RADEON_DFP1_ATTACHED; | ||
| 2391 | bios_5_scratch &= ~RADEON_DFP1_ON; | ||
| 2392 | bios_5_scratch &= ~RADEON_ACC_REQ_DFP1; | ||
| 2393 | } | ||
| 2394 | } | ||
| 2395 | if ((radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) && | ||
| 2396 | (radeon_connector->devices & ATOM_DEVICE_DFP2_SUPPORT)) { | ||
| 2397 | if (connected) { | ||
| 2398 | DRM_DEBUG("DFP2 connected\n"); | ||
| 2399 | bios_4_scratch |= RADEON_DFP2_ATTACHED; | ||
| 2400 | bios_5_scratch |= RADEON_DFP2_ON; | ||
| 2401 | bios_5_scratch |= RADEON_ACC_REQ_DFP2; | ||
| 2402 | } else { | ||
| 2403 | DRM_DEBUG("DFP2 disconnected\n"); | ||
| 2404 | bios_4_scratch &= ~RADEON_DFP2_ATTACHED; | ||
| 2405 | bios_5_scratch &= ~RADEON_DFP2_ON; | ||
| 2406 | bios_5_scratch &= ~RADEON_ACC_REQ_DFP2; | ||
| 2407 | } | ||
| 2408 | } | ||
| 2409 | WREG32(RADEON_BIOS_4_SCRATCH, bios_4_scratch); | ||
| 2410 | WREG32(RADEON_BIOS_5_SCRATCH, bios_5_scratch); | ||
| 2411 | } | ||
| 2412 | |||
| 2413 | void | ||
| 2414 | radeon_combios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc) | ||
| 2415 | { | ||
| 2416 | struct drm_device *dev = encoder->dev; | ||
| 2417 | struct radeon_device *rdev = dev->dev_private; | ||
| 2418 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 2419 | uint32_t bios_5_scratch = RREG32(RADEON_BIOS_5_SCRATCH); | ||
| 2420 | |||
| 2421 | if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) { | ||
| 2422 | bios_5_scratch &= ~RADEON_TV1_CRTC_MASK; | ||
| 2423 | bios_5_scratch |= (crtc << RADEON_TV1_CRTC_SHIFT); | ||
| 2424 | } | ||
| 2425 | if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) { | ||
| 2426 | bios_5_scratch &= ~RADEON_CRT1_CRTC_MASK; | ||
| 2427 | bios_5_scratch |= (crtc << RADEON_CRT1_CRTC_SHIFT); | ||
| 2428 | } | ||
| 2429 | if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) { | ||
| 2430 | bios_5_scratch &= ~RADEON_CRT2_CRTC_MASK; | ||
| 2431 | bios_5_scratch |= (crtc << RADEON_CRT2_CRTC_SHIFT); | ||
| 2432 | } | ||
| 2433 | if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) { | ||
| 2434 | bios_5_scratch &= ~RADEON_LCD1_CRTC_MASK; | ||
| 2435 | bios_5_scratch |= (crtc << RADEON_LCD1_CRTC_SHIFT); | ||
| 2436 | } | ||
| 2437 | if (radeon_encoder->devices & ATOM_DEVICE_DFP1_SUPPORT) { | ||
| 2438 | bios_5_scratch &= ~RADEON_DFP1_CRTC_MASK; | ||
| 2439 | bios_5_scratch |= (crtc << RADEON_DFP1_CRTC_SHIFT); | ||
| 2440 | } | ||
| 2441 | if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT) { | ||
| 2442 | bios_5_scratch &= ~RADEON_DFP2_CRTC_MASK; | ||
| 2443 | bios_5_scratch |= (crtc << RADEON_DFP2_CRTC_SHIFT); | ||
| 2444 | } | ||
| 2445 | WREG32(RADEON_BIOS_5_SCRATCH, bios_5_scratch); | ||
| 2446 | } | ||
| 2447 | |||
| 2448 | void | ||
| 2449 | radeon_combios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on) | ||
| 2450 | { | ||
| 2451 | struct drm_device *dev = encoder->dev; | ||
| 2452 | struct radeon_device *rdev = dev->dev_private; | ||
| 2453 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 2454 | uint32_t bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH); | ||
| 2455 | |||
| 2456 | if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) { | ||
| 2457 | if (on) | ||
| 2458 | bios_6_scratch |= RADEON_TV_DPMS_ON; | ||
| 2459 | else | ||
| 2460 | bios_6_scratch &= ~RADEON_TV_DPMS_ON; | ||
| 2461 | } | ||
| 2462 | if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) { | ||
| 2463 | if (on) | ||
| 2464 | bios_6_scratch |= RADEON_CRT_DPMS_ON; | ||
| 2465 | else | ||
| 2466 | bios_6_scratch &= ~RADEON_CRT_DPMS_ON; | ||
| 2467 | } | ||
| 2468 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | ||
| 2469 | if (on) | ||
| 2470 | bios_6_scratch |= RADEON_LCD_DPMS_ON; | ||
| 2471 | else | ||
| 2472 | bios_6_scratch &= ~RADEON_LCD_DPMS_ON; | ||
| 2473 | } | ||
| 2474 | if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { | ||
| 2475 | if (on) | ||
| 2476 | bios_6_scratch |= RADEON_DFP_DPMS_ON; | ||
| 2477 | else | ||
| 2478 | bios_6_scratch &= ~RADEON_DFP_DPMS_ON; | ||
| 2479 | } | ||
| 2480 | WREG32(RADEON_BIOS_6_SCRATCH, bios_6_scratch); | ||
| 2481 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c new file mode 100644 index 000000000000..70ede6a52d4e --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
| @@ -0,0 +1,603 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2007-8 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * copy of this software and associated documentation files (the "Software"), | ||
| 7 | * to deal in the Software without restriction, including without limitation | ||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 10 | * Software is furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 21 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: Dave Airlie | ||
| 24 | * Alex Deucher | ||
| 25 | */ | ||
| 26 | #include "drmP.h" | ||
| 27 | #include "drm_edid.h" | ||
| 28 | #include "drm_crtc_helper.h" | ||
| 29 | #include "radeon_drm.h" | ||
| 30 | #include "radeon.h" | ||
| 31 | |||
| 32 | extern void | ||
| 33 | radeon_combios_connected_scratch_regs(struct drm_connector *connector, | ||
| 34 | struct drm_encoder *encoder, | ||
| 35 | bool connected); | ||
| 36 | extern void | ||
| 37 | radeon_atombios_connected_scratch_regs(struct drm_connector *connector, | ||
| 38 | struct drm_encoder *encoder, | ||
| 39 | bool connected); | ||
| 40 | |||
| 41 | static void | ||
| 42 | radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_connector_status status) | ||
| 43 | { | ||
| 44 | struct drm_device *dev = connector->dev; | ||
| 45 | struct radeon_device *rdev = dev->dev_private; | ||
| 46 | struct drm_encoder *best_encoder = NULL; | ||
| 47 | struct drm_encoder *encoder = NULL; | ||
| 48 | struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; | ||
| 49 | struct drm_mode_object *obj; | ||
| 50 | bool connected; | ||
| 51 | int i; | ||
| 52 | |||
| 53 | best_encoder = connector_funcs->best_encoder(connector); | ||
| 54 | |||
| 55 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | ||
| 56 | if (connector->encoder_ids[i] == 0) | ||
| 57 | break; | ||
| 58 | |||
| 59 | obj = drm_mode_object_find(connector->dev, | ||
| 60 | connector->encoder_ids[i], | ||
| 61 | DRM_MODE_OBJECT_ENCODER); | ||
| 62 | if (!obj) | ||
| 63 | continue; | ||
| 64 | |||
| 65 | encoder = obj_to_encoder(obj); | ||
| 66 | |||
| 67 | if ((encoder == best_encoder) && (status == connector_status_connected)) | ||
| 68 | connected = true; | ||
| 69 | else | ||
| 70 | connected = false; | ||
| 71 | |||
| 72 | if (rdev->is_atom_bios) | ||
| 73 | radeon_atombios_connected_scratch_regs(connector, encoder, connected); | ||
| 74 | else | ||
| 75 | radeon_combios_connected_scratch_regs(connector, encoder, connected); | ||
| 76 | |||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector) | ||
| 81 | { | ||
| 82 | int enc_id = connector->encoder_ids[0]; | ||
| 83 | struct drm_mode_object *obj; | ||
| 84 | struct drm_encoder *encoder; | ||
| 85 | |||
| 86 | /* pick the encoder ids */ | ||
| 87 | if (enc_id) { | ||
| 88 | obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); | ||
| 89 | if (!obj) | ||
| 90 | return NULL; | ||
| 91 | encoder = obj_to_encoder(obj); | ||
| 92 | return encoder; | ||
| 93 | } | ||
| 94 | return NULL; | ||
| 95 | } | ||
| 96 | |||
| 97 | static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encoder) | ||
| 98 | { | ||
| 99 | struct drm_device *dev = encoder->dev; | ||
| 100 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 101 | struct drm_display_mode *mode = NULL; | ||
| 102 | struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; | ||
| 103 | |||
| 104 | if (native_mode->panel_xres != 0 && | ||
| 105 | native_mode->panel_yres != 0 && | ||
| 106 | native_mode->dotclock != 0) { | ||
| 107 | mode = drm_mode_create(dev); | ||
| 108 | |||
| 109 | mode->hdisplay = native_mode->panel_xres; | ||
| 110 | mode->vdisplay = native_mode->panel_yres; | ||
| 111 | |||
| 112 | mode->htotal = mode->hdisplay + native_mode->hblank; | ||
| 113 | mode->hsync_start = mode->hdisplay + native_mode->hoverplus; | ||
| 114 | mode->hsync_end = mode->hsync_start + native_mode->hsync_width; | ||
| 115 | mode->vtotal = mode->vdisplay + native_mode->vblank; | ||
| 116 | mode->vsync_start = mode->vdisplay + native_mode->voverplus; | ||
| 117 | mode->vsync_end = mode->vsync_start + native_mode->vsync_width; | ||
| 118 | mode->clock = native_mode->dotclock; | ||
| 119 | mode->flags = 0; | ||
| 120 | |||
| 121 | mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; | ||
| 122 | drm_mode_set_name(mode); | ||
| 123 | |||
| 124 | DRM_DEBUG("Adding native panel mode %s\n", mode->name); | ||
| 125 | } | ||
| 126 | return mode; | ||
| 127 | } | ||
| 128 | |||
| 129 | int radeon_connector_set_property(struct drm_connector *connector, struct drm_property *property, | ||
| 130 | uint64_t val) | ||
| 131 | { | ||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | |||
| 136 | static int radeon_lvds_get_modes(struct drm_connector *connector) | ||
| 137 | { | ||
| 138 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 139 | struct drm_encoder *encoder; | ||
| 140 | int ret = 0; | ||
| 141 | struct drm_display_mode *mode; | ||
| 142 | |||
| 143 | if (radeon_connector->ddc_bus) { | ||
| 144 | ret = radeon_ddc_get_modes(radeon_connector); | ||
| 145 | if (ret > 0) { | ||
| 146 | return ret; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | encoder = radeon_best_single_encoder(connector); | ||
| 151 | if (!encoder) | ||
| 152 | return 0; | ||
| 153 | |||
| 154 | /* we have no EDID modes */ | ||
| 155 | mode = radeon_fp_native_mode(encoder); | ||
| 156 | if (mode) { | ||
| 157 | ret = 1; | ||
| 158 | drm_mode_probed_add(connector, mode); | ||
| 159 | } | ||
| 160 | return ret; | ||
| 161 | } | ||
| 162 | |||
| 163 | static int radeon_lvds_mode_valid(struct drm_connector *connector, | ||
| 164 | struct drm_display_mode *mode) | ||
| 165 | { | ||
| 166 | return MODE_OK; | ||
| 167 | } | ||
| 168 | |||
| 169 | static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector) | ||
| 170 | { | ||
| 171 | enum drm_connector_status ret = connector_status_connected; | ||
| 172 | /* check acpi lid status ??? */ | ||
| 173 | radeon_connector_update_scratch_regs(connector, ret); | ||
| 174 | return ret; | ||
| 175 | } | ||
| 176 | |||
| 177 | static void radeon_connector_destroy(struct drm_connector *connector) | ||
| 178 | { | ||
| 179 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 180 | |||
| 181 | if (radeon_connector->ddc_bus) | ||
| 182 | radeon_i2c_destroy(radeon_connector->ddc_bus); | ||
| 183 | kfree(radeon_connector->con_priv); | ||
| 184 | drm_sysfs_connector_remove(connector); | ||
| 185 | drm_connector_cleanup(connector); | ||
| 186 | kfree(connector); | ||
| 187 | } | ||
| 188 | |||
| 189 | struct drm_connector_helper_funcs radeon_lvds_connector_helper_funcs = { | ||
| 190 | .get_modes = radeon_lvds_get_modes, | ||
| 191 | .mode_valid = radeon_lvds_mode_valid, | ||
| 192 | .best_encoder = radeon_best_single_encoder, | ||
| 193 | }; | ||
| 194 | |||
| 195 | struct drm_connector_funcs radeon_lvds_connector_funcs = { | ||
| 196 | .dpms = drm_helper_connector_dpms, | ||
| 197 | .detect = radeon_lvds_detect, | ||
| 198 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
| 199 | .destroy = radeon_connector_destroy, | ||
| 200 | .set_property = radeon_connector_set_property, | ||
| 201 | }; | ||
| 202 | |||
| 203 | static int radeon_vga_get_modes(struct drm_connector *connector) | ||
| 204 | { | ||
| 205 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 206 | int ret; | ||
| 207 | |||
| 208 | ret = radeon_ddc_get_modes(radeon_connector); | ||
| 209 | |||
| 210 | return ret; | ||
| 211 | } | ||
| 212 | |||
| 213 | static int radeon_vga_mode_valid(struct drm_connector *connector, | ||
| 214 | struct drm_display_mode *mode) | ||
| 215 | { | ||
| 216 | |||
| 217 | return MODE_OK; | ||
| 218 | } | ||
| 219 | |||
| 220 | static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector) | ||
| 221 | { | ||
| 222 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 223 | struct drm_encoder *encoder; | ||
| 224 | struct drm_encoder_helper_funcs *encoder_funcs; | ||
| 225 | bool dret; | ||
| 226 | enum drm_connector_status ret = connector_status_disconnected; | ||
| 227 | |||
| 228 | radeon_i2c_do_lock(radeon_connector, 1); | ||
| 229 | dret = radeon_ddc_probe(radeon_connector); | ||
| 230 | radeon_i2c_do_lock(radeon_connector, 0); | ||
| 231 | if (dret) | ||
| 232 | ret = connector_status_connected; | ||
| 233 | else { | ||
| 234 | /* if EDID fails to a load detect */ | ||
| 235 | encoder = radeon_best_single_encoder(connector); | ||
| 236 | if (!encoder) | ||
| 237 | ret = connector_status_disconnected; | ||
| 238 | else { | ||
| 239 | encoder_funcs = encoder->helper_private; | ||
| 240 | ret = encoder_funcs->detect(encoder, connector); | ||
| 241 | } | ||
| 242 | } | ||
| 243 | |||
| 244 | radeon_connector_update_scratch_regs(connector, ret); | ||
| 245 | return ret; | ||
| 246 | } | ||
| 247 | |||
| 248 | struct drm_connector_helper_funcs radeon_vga_connector_helper_funcs = { | ||
| 249 | .get_modes = radeon_vga_get_modes, | ||
| 250 | .mode_valid = radeon_vga_mode_valid, | ||
| 251 | .best_encoder = radeon_best_single_encoder, | ||
| 252 | }; | ||
| 253 | |||
| 254 | struct drm_connector_funcs radeon_vga_connector_funcs = { | ||
| 255 | .dpms = drm_helper_connector_dpms, | ||
| 256 | .detect = radeon_vga_detect, | ||
| 257 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
| 258 | .destroy = radeon_connector_destroy, | ||
| 259 | .set_property = radeon_connector_set_property, | ||
| 260 | }; | ||
| 261 | |||
| 262 | static int radeon_dvi_get_modes(struct drm_connector *connector) | ||
| 263 | { | ||
| 264 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 265 | int ret; | ||
| 266 | |||
| 267 | ret = radeon_ddc_get_modes(radeon_connector); | ||
| 268 | /* reset scratch regs here since radeon_dvi_detect doesn't check digital bit */ | ||
| 269 | radeon_connector_update_scratch_regs(connector, connector_status_connected); | ||
| 270 | return ret; | ||
| 271 | } | ||
| 272 | |||
| 273 | static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector) | ||
| 274 | { | ||
| 275 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 276 | struct drm_encoder *encoder; | ||
| 277 | struct drm_encoder_helper_funcs *encoder_funcs; | ||
| 278 | struct drm_mode_object *obj; | ||
| 279 | int i; | ||
| 280 | enum drm_connector_status ret = connector_status_disconnected; | ||
| 281 | bool dret; | ||
| 282 | |||
| 283 | radeon_i2c_do_lock(radeon_connector, 1); | ||
| 284 | dret = radeon_ddc_probe(radeon_connector); | ||
| 285 | radeon_i2c_do_lock(radeon_connector, 0); | ||
| 286 | if (dret) | ||
| 287 | ret = connector_status_connected; | ||
| 288 | else { | ||
| 289 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | ||
| 290 | if (connector->encoder_ids[i] == 0) | ||
| 291 | break; | ||
| 292 | |||
| 293 | obj = drm_mode_object_find(connector->dev, | ||
| 294 | connector->encoder_ids[i], | ||
| 295 | DRM_MODE_OBJECT_ENCODER); | ||
| 296 | if (!obj) | ||
| 297 | continue; | ||
| 298 | |||
| 299 | encoder = obj_to_encoder(obj); | ||
| 300 | |||
| 301 | encoder_funcs = encoder->helper_private; | ||
| 302 | if (encoder_funcs->detect) { | ||
| 303 | ret = encoder_funcs->detect(encoder, connector); | ||
| 304 | if (ret == connector_status_connected) { | ||
| 305 | radeon_connector->use_digital = 0; | ||
| 306 | break; | ||
| 307 | } | ||
| 308 | } | ||
| 309 | } | ||
| 310 | } | ||
| 311 | |||
| 312 | /* updated in get modes as well since we need to know if it's analog or digital */ | ||
| 313 | radeon_connector_update_scratch_regs(connector, ret); | ||
| 314 | return ret; | ||
| 315 | } | ||
| 316 | |||
| 317 | /* okay need to be smart in here about which encoder to pick */ | ||
| 318 | struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector) | ||
| 319 | { | ||
| 320 | int enc_id = connector->encoder_ids[0]; | ||
| 321 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 322 | struct drm_mode_object *obj; | ||
| 323 | struct drm_encoder *encoder; | ||
| 324 | int i; | ||
| 325 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | ||
| 326 | if (connector->encoder_ids[i] == 0) | ||
| 327 | break; | ||
| 328 | |||
| 329 | obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER); | ||
| 330 | if (!obj) | ||
| 331 | continue; | ||
| 332 | |||
| 333 | encoder = obj_to_encoder(obj); | ||
| 334 | |||
| 335 | if (radeon_connector->use_digital) { | ||
| 336 | if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS) | ||
| 337 | return encoder; | ||
| 338 | } else { | ||
| 339 | if (encoder->encoder_type == DRM_MODE_ENCODER_DAC || | ||
| 340 | encoder->encoder_type == DRM_MODE_ENCODER_TVDAC) | ||
| 341 | return encoder; | ||
| 342 | } | ||
| 343 | } | ||
| 344 | |||
| 345 | /* see if we have a default encoder TODO */ | ||
| 346 | |||
| 347 | /* then check use digitial */ | ||
| 348 | /* pick the first one */ | ||
| 349 | if (enc_id) { | ||
| 350 | obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER); | ||
| 351 | if (!obj) | ||
| 352 | return NULL; | ||
| 353 | encoder = obj_to_encoder(obj); | ||
| 354 | return encoder; | ||
| 355 | } | ||
| 356 | return NULL; | ||
| 357 | } | ||
| 358 | |||
| 359 | struct drm_connector_helper_funcs radeon_dvi_connector_helper_funcs = { | ||
| 360 | .get_modes = radeon_dvi_get_modes, | ||
| 361 | .mode_valid = radeon_vga_mode_valid, | ||
| 362 | .best_encoder = radeon_dvi_encoder, | ||
| 363 | }; | ||
| 364 | |||
| 365 | struct drm_connector_funcs radeon_dvi_connector_funcs = { | ||
| 366 | .dpms = drm_helper_connector_dpms, | ||
| 367 | .detect = radeon_dvi_detect, | ||
| 368 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
| 369 | .set_property = radeon_connector_set_property, | ||
| 370 | .destroy = radeon_connector_destroy, | ||
| 371 | }; | ||
| 372 | |||
| 373 | void | ||
| 374 | radeon_add_atom_connector(struct drm_device *dev, | ||
| 375 | uint32_t connector_id, | ||
| 376 | uint32_t supported_device, | ||
| 377 | int connector_type, | ||
| 378 | struct radeon_i2c_bus_rec *i2c_bus, | ||
| 379 | bool linkb, | ||
| 380 | uint32_t igp_lane_info) | ||
| 381 | { | ||
| 382 | struct drm_connector *connector; | ||
| 383 | struct radeon_connector *radeon_connector; | ||
| 384 | struct radeon_connector_atom_dig *radeon_dig_connector; | ||
| 385 | uint32_t subpixel_order = SubPixelNone; | ||
| 386 | |||
| 387 | /* fixme - tv/cv/din */ | ||
| 388 | if ((connector_type == DRM_MODE_CONNECTOR_Unknown) || | ||
| 389 | (connector_type == DRM_MODE_CONNECTOR_SVIDEO) || | ||
| 390 | (connector_type == DRM_MODE_CONNECTOR_Composite) || | ||
| 391 | (connector_type == DRM_MODE_CONNECTOR_9PinDIN)) | ||
| 392 | return; | ||
| 393 | |||
| 394 | /* see if we already added it */ | ||
| 395 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 396 | radeon_connector = to_radeon_connector(connector); | ||
| 397 | if (radeon_connector->connector_id == connector_id) { | ||
| 398 | radeon_connector->devices |= supported_device; | ||
| 399 | return; | ||
| 400 | } | ||
| 401 | } | ||
| 402 | |||
| 403 | radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL); | ||
| 404 | if (!radeon_connector) | ||
| 405 | return; | ||
| 406 | |||
| 407 | connector = &radeon_connector->base; | ||
| 408 | |||
| 409 | radeon_connector->connector_id = connector_id; | ||
| 410 | radeon_connector->devices = supported_device; | ||
| 411 | switch (connector_type) { | ||
| 412 | case DRM_MODE_CONNECTOR_VGA: | ||
| 413 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | ||
| 414 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); | ||
| 415 | if (i2c_bus->valid) { | ||
| 416 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); | ||
| 417 | if (!radeon_connector->ddc_bus) | ||
| 418 | goto failed; | ||
| 419 | } | ||
| 420 | break; | ||
| 421 | case DRM_MODE_CONNECTOR_DVIA: | ||
| 422 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | ||
| 423 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); | ||
| 424 | if (i2c_bus->valid) { | ||
| 425 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); | ||
| 426 | if (!radeon_connector->ddc_bus) | ||
| 427 | goto failed; | ||
| 428 | } | ||
| 429 | break; | ||
| 430 | case DRM_MODE_CONNECTOR_DVII: | ||
| 431 | case DRM_MODE_CONNECTOR_DVID: | ||
| 432 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); | ||
| 433 | if (!radeon_dig_connector) | ||
| 434 | goto failed; | ||
| 435 | radeon_dig_connector->linkb = linkb; | ||
| 436 | radeon_dig_connector->igp_lane_info = igp_lane_info; | ||
| 437 | radeon_connector->con_priv = radeon_dig_connector; | ||
| 438 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); | ||
| 439 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); | ||
| 440 | if (i2c_bus->valid) { | ||
| 441 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); | ||
| 442 | if (!radeon_connector->ddc_bus) | ||
| 443 | goto failed; | ||
| 444 | } | ||
| 445 | subpixel_order = SubPixelHorizontalRGB; | ||
| 446 | break; | ||
| 447 | case DRM_MODE_CONNECTOR_HDMIA: | ||
| 448 | case DRM_MODE_CONNECTOR_HDMIB: | ||
| 449 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); | ||
| 450 | if (!radeon_dig_connector) | ||
| 451 | goto failed; | ||
| 452 | radeon_dig_connector->linkb = linkb; | ||
| 453 | radeon_dig_connector->igp_lane_info = igp_lane_info; | ||
| 454 | radeon_connector->con_priv = radeon_dig_connector; | ||
| 455 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); | ||
| 456 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); | ||
| 457 | if (i2c_bus->valid) { | ||
| 458 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "HDMI"); | ||
| 459 | if (!radeon_connector->ddc_bus) | ||
| 460 | goto failed; | ||
| 461 | } | ||
| 462 | subpixel_order = SubPixelHorizontalRGB; | ||
| 463 | break; | ||
| 464 | case DRM_MODE_CONNECTOR_DisplayPort: | ||
| 465 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); | ||
| 466 | if (!radeon_dig_connector) | ||
| 467 | goto failed; | ||
| 468 | radeon_dig_connector->linkb = linkb; | ||
| 469 | radeon_dig_connector->igp_lane_info = igp_lane_info; | ||
| 470 | radeon_connector->con_priv = radeon_dig_connector; | ||
| 471 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); | ||
| 472 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); | ||
| 473 | if (i2c_bus->valid) { | ||
| 474 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DP"); | ||
| 475 | if (!radeon_connector->ddc_bus) | ||
| 476 | goto failed; | ||
| 477 | } | ||
| 478 | subpixel_order = SubPixelHorizontalRGB; | ||
| 479 | break; | ||
| 480 | case DRM_MODE_CONNECTOR_SVIDEO: | ||
| 481 | case DRM_MODE_CONNECTOR_Composite: | ||
| 482 | case DRM_MODE_CONNECTOR_9PinDIN: | ||
| 483 | break; | ||
| 484 | case DRM_MODE_CONNECTOR_LVDS: | ||
| 485 | radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL); | ||
| 486 | if (!radeon_dig_connector) | ||
| 487 | goto failed; | ||
| 488 | radeon_dig_connector->linkb = linkb; | ||
| 489 | radeon_dig_connector->igp_lane_info = igp_lane_info; | ||
| 490 | radeon_connector->con_priv = radeon_dig_connector; | ||
| 491 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); | ||
| 492 | drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); | ||
| 493 | if (i2c_bus->valid) { | ||
| 494 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); | ||
| 495 | if (!radeon_connector->ddc_bus) | ||
| 496 | goto failed; | ||
| 497 | } | ||
| 498 | subpixel_order = SubPixelHorizontalRGB; | ||
| 499 | break; | ||
| 500 | } | ||
| 501 | |||
| 502 | connector->display_info.subpixel_order = subpixel_order; | ||
| 503 | drm_sysfs_connector_add(connector); | ||
| 504 | return; | ||
| 505 | |||
| 506 | failed: | ||
| 507 | if (radeon_connector->ddc_bus) | ||
| 508 | radeon_i2c_destroy(radeon_connector->ddc_bus); | ||
| 509 | drm_connector_cleanup(connector); | ||
| 510 | kfree(connector); | ||
| 511 | } | ||
| 512 | |||
| 513 | void | ||
| 514 | radeon_add_legacy_connector(struct drm_device *dev, | ||
| 515 | uint32_t connector_id, | ||
| 516 | uint32_t supported_device, | ||
| 517 | int connector_type, | ||
| 518 | struct radeon_i2c_bus_rec *i2c_bus) | ||
| 519 | { | ||
| 520 | struct drm_connector *connector; | ||
| 521 | struct radeon_connector *radeon_connector; | ||
| 522 | uint32_t subpixel_order = SubPixelNone; | ||
| 523 | |||
| 524 | /* fixme - tv/cv/din */ | ||
| 525 | if ((connector_type == DRM_MODE_CONNECTOR_Unknown) || | ||
| 526 | (connector_type == DRM_MODE_CONNECTOR_SVIDEO) || | ||
| 527 | (connector_type == DRM_MODE_CONNECTOR_Composite) || | ||
| 528 | (connector_type == DRM_MODE_CONNECTOR_9PinDIN)) | ||
| 529 | return; | ||
| 530 | |||
| 531 | /* see if we already added it */ | ||
| 532 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 533 | radeon_connector = to_radeon_connector(connector); | ||
| 534 | if (radeon_connector->connector_id == connector_id) { | ||
| 535 | radeon_connector->devices |= supported_device; | ||
| 536 | return; | ||
| 537 | } | ||
| 538 | } | ||
| 539 | |||
| 540 | radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL); | ||
| 541 | if (!radeon_connector) | ||
| 542 | return; | ||
| 543 | |||
| 544 | connector = &radeon_connector->base; | ||
| 545 | |||
| 546 | radeon_connector->connector_id = connector_id; | ||
| 547 | radeon_connector->devices = supported_device; | ||
| 548 | switch (connector_type) { | ||
| 549 | case DRM_MODE_CONNECTOR_VGA: | ||
| 550 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | ||
| 551 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); | ||
| 552 | if (i2c_bus->valid) { | ||
| 553 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "VGA"); | ||
| 554 | if (!radeon_connector->ddc_bus) | ||
| 555 | goto failed; | ||
| 556 | } | ||
| 557 | break; | ||
| 558 | case DRM_MODE_CONNECTOR_DVIA: | ||
| 559 | drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type); | ||
| 560 | drm_connector_helper_add(&radeon_connector->base, &radeon_vga_connector_helper_funcs); | ||
| 561 | if (i2c_bus->valid) { | ||
| 562 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); | ||
| 563 | if (!radeon_connector->ddc_bus) | ||
| 564 | goto failed; | ||
| 565 | } | ||
| 566 | break; | ||
| 567 | case DRM_MODE_CONNECTOR_DVII: | ||
| 568 | case DRM_MODE_CONNECTOR_DVID: | ||
| 569 | drm_connector_init(dev, &radeon_connector->base, &radeon_dvi_connector_funcs, connector_type); | ||
| 570 | drm_connector_helper_add(&radeon_connector->base, &radeon_dvi_connector_helper_funcs); | ||
| 571 | if (i2c_bus->valid) { | ||
| 572 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI"); | ||
| 573 | if (!radeon_connector->ddc_bus) | ||
| 574 | goto failed; | ||
| 575 | } | ||
| 576 | subpixel_order = SubPixelHorizontalRGB; | ||
| 577 | break; | ||
| 578 | case DRM_MODE_CONNECTOR_SVIDEO: | ||
| 579 | case DRM_MODE_CONNECTOR_Composite: | ||
| 580 | case DRM_MODE_CONNECTOR_9PinDIN: | ||
| 581 | break; | ||
| 582 | case DRM_MODE_CONNECTOR_LVDS: | ||
| 583 | drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type); | ||
| 584 | drm_connector_helper_add(&radeon_connector->base, &radeon_lvds_connector_helper_funcs); | ||
| 585 | if (i2c_bus->valid) { | ||
| 586 | radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "LVDS"); | ||
| 587 | if (!radeon_connector->ddc_bus) | ||
| 588 | goto failed; | ||
| 589 | } | ||
| 590 | subpixel_order = SubPixelHorizontalRGB; | ||
| 591 | break; | ||
| 592 | } | ||
| 593 | |||
| 594 | connector->display_info.subpixel_order = subpixel_order; | ||
| 595 | drm_sysfs_connector_add(connector); | ||
| 596 | return; | ||
| 597 | |||
| 598 | failed: | ||
| 599 | if (radeon_connector->ddc_bus) | ||
| 600 | radeon_i2c_destroy(radeon_connector->ddc_bus); | ||
| 601 | drm_connector_cleanup(connector); | ||
| 602 | kfree(connector); | ||
| 603 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c new file mode 100644 index 000000000000..b843f9bdfb14 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_cs.c | |||
| @@ -0,0 +1,249 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Jerome Glisse. | ||
| 3 | * All Rights Reserved. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * copy of this software and associated documentation files (the "Software"), | ||
| 7 | * to deal in the Software without restriction, including without limitation | ||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 10 | * Software is furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice (including the next | ||
| 13 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 14 | * Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 22 | * DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: | ||
| 25 | * Jerome Glisse <glisse@freedesktop.org> | ||
| 26 | */ | ||
| 27 | #include "drmP.h" | ||
| 28 | #include "radeon_drm.h" | ||
| 29 | #include "radeon_reg.h" | ||
| 30 | #include "radeon.h" | ||
| 31 | |||
| 32 | void r100_cs_dump_packet(struct radeon_cs_parser *p, | ||
| 33 | struct radeon_cs_packet *pkt); | ||
| 34 | |||
| 35 | int radeon_cs_parser_relocs(struct radeon_cs_parser *p) | ||
| 36 | { | ||
| 37 | struct drm_device *ddev = p->rdev->ddev; | ||
| 38 | struct radeon_cs_chunk *chunk; | ||
| 39 | unsigned i, j; | ||
| 40 | bool duplicate; | ||
| 41 | |||
| 42 | if (p->chunk_relocs_idx == -1) { | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | chunk = &p->chunks[p->chunk_relocs_idx]; | ||
| 46 | /* FIXME: we assume that each relocs use 4 dwords */ | ||
| 47 | p->nrelocs = chunk->length_dw / 4; | ||
| 48 | p->relocs_ptr = kcalloc(p->nrelocs, sizeof(void *), GFP_KERNEL); | ||
| 49 | if (p->relocs_ptr == NULL) { | ||
| 50 | return -ENOMEM; | ||
| 51 | } | ||
| 52 | p->relocs = kcalloc(p->nrelocs, sizeof(struct radeon_cs_reloc), GFP_KERNEL); | ||
| 53 | if (p->relocs == NULL) { | ||
| 54 | return -ENOMEM; | ||
| 55 | } | ||
| 56 | for (i = 0; i < p->nrelocs; i++) { | ||
| 57 | struct drm_radeon_cs_reloc *r; | ||
| 58 | |||
| 59 | duplicate = false; | ||
| 60 | r = (struct drm_radeon_cs_reloc *)&chunk->kdata[i*4]; | ||
| 61 | for (j = 0; j < p->nrelocs; j++) { | ||
| 62 | if (r->handle == p->relocs[j].handle) { | ||
| 63 | p->relocs_ptr[i] = &p->relocs[j]; | ||
| 64 | duplicate = true; | ||
| 65 | break; | ||
| 66 | } | ||
| 67 | } | ||
| 68 | if (!duplicate) { | ||
| 69 | p->relocs[i].gobj = drm_gem_object_lookup(ddev, | ||
| 70 | p->filp, | ||
| 71 | r->handle); | ||
| 72 | if (p->relocs[i].gobj == NULL) { | ||
| 73 | DRM_ERROR("gem object lookup failed 0x%x\n", | ||
| 74 | r->handle); | ||
| 75 | return -EINVAL; | ||
| 76 | } | ||
| 77 | p->relocs_ptr[i] = &p->relocs[i]; | ||
| 78 | p->relocs[i].robj = p->relocs[i].gobj->driver_private; | ||
| 79 | p->relocs[i].lobj.robj = p->relocs[i].robj; | ||
| 80 | p->relocs[i].lobj.rdomain = r->read_domains; | ||
| 81 | p->relocs[i].lobj.wdomain = r->write_domain; | ||
| 82 | p->relocs[i].handle = r->handle; | ||
| 83 | p->relocs[i].flags = r->flags; | ||
| 84 | INIT_LIST_HEAD(&p->relocs[i].lobj.list); | ||
| 85 | radeon_object_list_add_object(&p->relocs[i].lobj, | ||
| 86 | &p->validated); | ||
| 87 | } | ||
| 88 | } | ||
| 89 | return radeon_object_list_validate(&p->validated, p->ib->fence); | ||
| 90 | } | ||
| 91 | |||
| 92 | int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) | ||
| 93 | { | ||
| 94 | struct drm_radeon_cs *cs = data; | ||
| 95 | uint64_t *chunk_array_ptr; | ||
| 96 | unsigned size, i; | ||
| 97 | |||
| 98 | if (!cs->num_chunks) { | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | /* get chunks */ | ||
| 102 | INIT_LIST_HEAD(&p->validated); | ||
| 103 | p->idx = 0; | ||
| 104 | p->chunk_ib_idx = -1; | ||
| 105 | p->chunk_relocs_idx = -1; | ||
| 106 | p->chunks_array = kcalloc(cs->num_chunks, sizeof(uint64_t), GFP_KERNEL); | ||
| 107 | if (p->chunks_array == NULL) { | ||
| 108 | return -ENOMEM; | ||
| 109 | } | ||
| 110 | chunk_array_ptr = (uint64_t *)(unsigned long)(cs->chunks); | ||
| 111 | if (DRM_COPY_FROM_USER(p->chunks_array, chunk_array_ptr, | ||
| 112 | sizeof(uint64_t)*cs->num_chunks)) { | ||
| 113 | return -EFAULT; | ||
| 114 | } | ||
| 115 | p->nchunks = cs->num_chunks; | ||
| 116 | p->chunks = kcalloc(p->nchunks, sizeof(struct radeon_cs_chunk), GFP_KERNEL); | ||
| 117 | if (p->chunks == NULL) { | ||
| 118 | return -ENOMEM; | ||
| 119 | } | ||
| 120 | for (i = 0; i < p->nchunks; i++) { | ||
| 121 | struct drm_radeon_cs_chunk __user **chunk_ptr = NULL; | ||
| 122 | struct drm_radeon_cs_chunk user_chunk; | ||
| 123 | uint32_t __user *cdata; | ||
| 124 | |||
| 125 | chunk_ptr = (void __user*)(unsigned long)p->chunks_array[i]; | ||
| 126 | if (DRM_COPY_FROM_USER(&user_chunk, chunk_ptr, | ||
| 127 | sizeof(struct drm_radeon_cs_chunk))) { | ||
| 128 | return -EFAULT; | ||
| 129 | } | ||
| 130 | p->chunks[i].chunk_id = user_chunk.chunk_id; | ||
| 131 | if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS) { | ||
| 132 | p->chunk_relocs_idx = i; | ||
| 133 | } | ||
| 134 | if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_IB) { | ||
| 135 | p->chunk_ib_idx = i; | ||
| 136 | } | ||
| 137 | p->chunks[i].length_dw = user_chunk.length_dw; | ||
| 138 | cdata = (uint32_t *)(unsigned long)user_chunk.chunk_data; | ||
| 139 | |||
| 140 | p->chunks[i].kdata = NULL; | ||
| 141 | size = p->chunks[i].length_dw * sizeof(uint32_t); | ||
| 142 | p->chunks[i].kdata = kzalloc(size, GFP_KERNEL); | ||
| 143 | if (p->chunks[i].kdata == NULL) { | ||
| 144 | return -ENOMEM; | ||
| 145 | } | ||
| 146 | if (DRM_COPY_FROM_USER(p->chunks[i].kdata, cdata, size)) { | ||
| 147 | return -EFAULT; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | if (p->chunks[p->chunk_ib_idx].length_dw > (16 * 1024)) { | ||
| 151 | DRM_ERROR("cs IB too big: %d\n", | ||
| 152 | p->chunks[p->chunk_ib_idx].length_dw); | ||
| 153 | return -EINVAL; | ||
| 154 | } | ||
| 155 | return 0; | ||
| 156 | } | ||
| 157 | |||
| 158 | /** | ||
| 159 | * cs_parser_fini() - clean parser states | ||
| 160 | * @parser: parser structure holding parsing context. | ||
| 161 | * @error: error number | ||
| 162 | * | ||
| 163 | * If error is set than unvalidate buffer, otherwise just free memory | ||
| 164 | * used by parsing context. | ||
| 165 | **/ | ||
| 166 | static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error) | ||
| 167 | { | ||
| 168 | unsigned i; | ||
| 169 | |||
| 170 | if (error) { | ||
| 171 | radeon_object_list_unvalidate(&parser->validated); | ||
| 172 | } else { | ||
| 173 | radeon_object_list_clean(&parser->validated); | ||
| 174 | } | ||
| 175 | for (i = 0; i < parser->nrelocs; i++) { | ||
| 176 | if (parser->relocs[i].gobj) { | ||
| 177 | mutex_lock(&parser->rdev->ddev->struct_mutex); | ||
| 178 | drm_gem_object_unreference(parser->relocs[i].gobj); | ||
| 179 | mutex_unlock(&parser->rdev->ddev->struct_mutex); | ||
| 180 | } | ||
| 181 | } | ||
| 182 | kfree(parser->relocs); | ||
| 183 | kfree(parser->relocs_ptr); | ||
| 184 | for (i = 0; i < parser->nchunks; i++) { | ||
| 185 | kfree(parser->chunks[i].kdata); | ||
| 186 | } | ||
| 187 | kfree(parser->chunks); | ||
| 188 | kfree(parser->chunks_array); | ||
| 189 | radeon_ib_free(parser->rdev, &parser->ib); | ||
| 190 | } | ||
| 191 | |||
| 192 | int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | ||
| 193 | { | ||
| 194 | struct radeon_device *rdev = dev->dev_private; | ||
| 195 | struct radeon_cs_parser parser; | ||
| 196 | struct radeon_cs_chunk *ib_chunk; | ||
| 197 | int r; | ||
| 198 | |||
| 199 | mutex_lock(&rdev->cs_mutex); | ||
| 200 | if (rdev->gpu_lockup) { | ||
| 201 | mutex_unlock(&rdev->cs_mutex); | ||
| 202 | return -EINVAL; | ||
| 203 | } | ||
| 204 | /* initialize parser */ | ||
| 205 | memset(&parser, 0, sizeof(struct radeon_cs_parser)); | ||
| 206 | parser.filp = filp; | ||
| 207 | parser.rdev = rdev; | ||
| 208 | r = radeon_cs_parser_init(&parser, data); | ||
| 209 | if (r) { | ||
| 210 | DRM_ERROR("Failed to initialize parser !\n"); | ||
| 211 | radeon_cs_parser_fini(&parser, r); | ||
| 212 | mutex_unlock(&rdev->cs_mutex); | ||
| 213 | return r; | ||
| 214 | } | ||
| 215 | r = radeon_ib_get(rdev, &parser.ib); | ||
| 216 | if (r) { | ||
| 217 | DRM_ERROR("Failed to get ib !\n"); | ||
| 218 | radeon_cs_parser_fini(&parser, r); | ||
| 219 | mutex_unlock(&rdev->cs_mutex); | ||
| 220 | return r; | ||
| 221 | } | ||
| 222 | r = radeon_cs_parser_relocs(&parser); | ||
| 223 | if (r) { | ||
| 224 | DRM_ERROR("Failed to parse relocation !\n"); | ||
| 225 | radeon_cs_parser_fini(&parser, r); | ||
| 226 | mutex_unlock(&rdev->cs_mutex); | ||
| 227 | return r; | ||
| 228 | } | ||
| 229 | /* Copy the packet into the IB, the parser will read from the | ||
| 230 | * input memory (cached) and write to the IB (which can be | ||
| 231 | * uncached). */ | ||
| 232 | ib_chunk = &parser.chunks[parser.chunk_ib_idx]; | ||
| 233 | parser.ib->length_dw = ib_chunk->length_dw; | ||
| 234 | memcpy((void *)parser.ib->ptr, ib_chunk->kdata, ib_chunk->length_dw*4); | ||
| 235 | r = radeon_cs_parse(&parser); | ||
| 236 | if (r) { | ||
| 237 | DRM_ERROR("Invalid command stream !\n"); | ||
| 238 | radeon_cs_parser_fini(&parser, r); | ||
| 239 | mutex_unlock(&rdev->cs_mutex); | ||
| 240 | return r; | ||
| 241 | } | ||
| 242 | r = radeon_ib_schedule(rdev, parser.ib); | ||
| 243 | if (r) { | ||
| 244 | DRM_ERROR("Faild to schedule IB !\n"); | ||
| 245 | } | ||
| 246 | radeon_cs_parser_fini(&parser, r); | ||
| 247 | mutex_unlock(&rdev->cs_mutex); | ||
| 248 | return r; | ||
| 249 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c new file mode 100644 index 000000000000..5232441f119b --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_cursor.c | |||
| @@ -0,0 +1,252 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2007-8 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * copy of this software and associated documentation files (the "Software"), | ||
| 7 | * to deal in the Software without restriction, including without limitation | ||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 10 | * Software is furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 21 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: Dave Airlie | ||
| 24 | * Alex Deucher | ||
| 25 | */ | ||
| 26 | #include "drmP.h" | ||
| 27 | #include "radeon_drm.h" | ||
| 28 | #include "radeon.h" | ||
| 29 | |||
| 30 | #define CURSOR_WIDTH 64 | ||
| 31 | #define CURSOR_HEIGHT 64 | ||
| 32 | |||
| 33 | static void radeon_lock_cursor(struct drm_crtc *crtc, bool lock) | ||
| 34 | { | ||
| 35 | struct radeon_device *rdev = crtc->dev->dev_private; | ||
| 36 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 37 | uint32_t cur_lock; | ||
| 38 | |||
| 39 | if (ASIC_IS_AVIVO(rdev)) { | ||
| 40 | cur_lock = RREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset); | ||
| 41 | if (lock) | ||
| 42 | cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK; | ||
| 43 | else | ||
| 44 | cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK; | ||
| 45 | WREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock); | ||
| 46 | } else { | ||
| 47 | cur_lock = RREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset); | ||
| 48 | if (lock) | ||
| 49 | cur_lock |= RADEON_CUR_LOCK; | ||
| 50 | else | ||
| 51 | cur_lock &= ~RADEON_CUR_LOCK; | ||
| 52 | WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, cur_lock); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | static void radeon_hide_cursor(struct drm_crtc *crtc) | ||
| 57 | { | ||
| 58 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 59 | struct radeon_device *rdev = crtc->dev->dev_private; | ||
| 60 | |||
| 61 | if (ASIC_IS_AVIVO(rdev)) { | ||
| 62 | WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); | ||
| 63 | WREG32(RADEON_MM_DATA, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); | ||
| 64 | } else { | ||
| 65 | switch (radeon_crtc->crtc_id) { | ||
| 66 | case 0: | ||
| 67 | WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); | ||
| 68 | break; | ||
| 69 | case 1: | ||
| 70 | WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL); | ||
| 71 | break; | ||
| 72 | default: | ||
| 73 | return; | ||
| 74 | } | ||
| 75 | WREG32_P(RADEON_MM_DATA, 0, ~RADEON_CRTC_CUR_EN); | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | static void radeon_show_cursor(struct drm_crtc *crtc) | ||
| 80 | { | ||
| 81 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 82 | struct radeon_device *rdev = crtc->dev->dev_private; | ||
| 83 | |||
| 84 | if (ASIC_IS_AVIVO(rdev)) { | ||
| 85 | WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); | ||
| 86 | WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN | | ||
| 87 | (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); | ||
| 88 | } else { | ||
| 89 | switch (radeon_crtc->crtc_id) { | ||
| 90 | case 0: | ||
| 91 | WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); | ||
| 92 | break; | ||
| 93 | case 1: | ||
| 94 | WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL); | ||
| 95 | break; | ||
| 96 | default: | ||
| 97 | return; | ||
| 98 | } | ||
| 99 | |||
| 100 | WREG32_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN | | ||
| 101 | (RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)), | ||
| 102 | ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK)); | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj, | ||
| 107 | uint32_t gpu_addr) | ||
| 108 | { | ||
| 109 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 110 | struct radeon_device *rdev = crtc->dev->dev_private; | ||
| 111 | |||
| 112 | if (ASIC_IS_AVIVO(rdev)) | ||
| 113 | WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr); | ||
| 114 | else | ||
| 115 | /* offset is from DISP(2)_BASE_ADDRESS */ | ||
| 116 | WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, gpu_addr); | ||
| 117 | } | ||
| 118 | |||
| 119 | int radeon_crtc_cursor_set(struct drm_crtc *crtc, | ||
| 120 | struct drm_file *file_priv, | ||
| 121 | uint32_t handle, | ||
| 122 | uint32_t width, | ||
| 123 | uint32_t height) | ||
| 124 | { | ||
| 125 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 126 | struct drm_gem_object *obj; | ||
| 127 | uint64_t gpu_addr; | ||
| 128 | int ret; | ||
| 129 | |||
| 130 | if (!handle) { | ||
| 131 | /* turn off cursor */ | ||
| 132 | radeon_hide_cursor(crtc); | ||
| 133 | obj = NULL; | ||
| 134 | goto unpin; | ||
| 135 | } | ||
| 136 | |||
| 137 | if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) { | ||
| 138 | DRM_ERROR("bad cursor width or height %d x %d\n", width, height); | ||
| 139 | return -EINVAL; | ||
| 140 | } | ||
| 141 | |||
| 142 | radeon_crtc->cursor_width = width; | ||
| 143 | radeon_crtc->cursor_height = height; | ||
| 144 | |||
| 145 | obj = drm_gem_object_lookup(crtc->dev, file_priv, handle); | ||
| 146 | if (!obj) { | ||
| 147 | DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id); | ||
| 148 | return -EINVAL; | ||
| 149 | } | ||
| 150 | |||
| 151 | ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr); | ||
| 152 | if (ret) | ||
| 153 | goto fail; | ||
| 154 | |||
| 155 | radeon_lock_cursor(crtc, true); | ||
| 156 | /* XXX only 27 bit offset for legacy cursor */ | ||
| 157 | radeon_set_cursor(crtc, obj, gpu_addr); | ||
| 158 | radeon_show_cursor(crtc); | ||
| 159 | radeon_lock_cursor(crtc, false); | ||
| 160 | |||
| 161 | unpin: | ||
| 162 | if (radeon_crtc->cursor_bo) { | ||
| 163 | radeon_gem_object_unpin(radeon_crtc->cursor_bo); | ||
| 164 | mutex_lock(&crtc->dev->struct_mutex); | ||
| 165 | drm_gem_object_unreference(radeon_crtc->cursor_bo); | ||
| 166 | mutex_unlock(&crtc->dev->struct_mutex); | ||
| 167 | } | ||
| 168 | |||
| 169 | radeon_crtc->cursor_bo = obj; | ||
| 170 | return 0; | ||
| 171 | fail: | ||
| 172 | mutex_lock(&crtc->dev->struct_mutex); | ||
| 173 | drm_gem_object_unreference(obj); | ||
| 174 | mutex_unlock(&crtc->dev->struct_mutex); | ||
| 175 | |||
| 176 | return 0; | ||
| 177 | } | ||
| 178 | |||
| 179 | int radeon_crtc_cursor_move(struct drm_crtc *crtc, | ||
| 180 | int x, int y) | ||
| 181 | { | ||
| 182 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 183 | struct radeon_device *rdev = crtc->dev->dev_private; | ||
| 184 | int xorigin = 0, yorigin = 0; | ||
| 185 | |||
| 186 | if (x < 0) | ||
| 187 | xorigin = -x + 1; | ||
| 188 | if (y < 0) | ||
| 189 | yorigin = -y + 1; | ||
| 190 | if (xorigin >= CURSOR_WIDTH) | ||
| 191 | xorigin = CURSOR_WIDTH - 1; | ||
| 192 | if (yorigin >= CURSOR_HEIGHT) | ||
| 193 | yorigin = CURSOR_HEIGHT - 1; | ||
| 194 | |||
| 195 | radeon_lock_cursor(crtc, true); | ||
| 196 | if (ASIC_IS_AVIVO(rdev)) { | ||
| 197 | int w = radeon_crtc->cursor_width; | ||
| 198 | int i = 0; | ||
| 199 | struct drm_crtc *crtc_p; | ||
| 200 | |||
| 201 | /* avivo cursor are offset into the total surface */ | ||
| 202 | x += crtc->x; | ||
| 203 | y += crtc->y; | ||
| 204 | DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y); | ||
| 205 | |||
| 206 | /* avivo cursor image can't end on 128 pixel boundry or | ||
| 207 | * go past the end of the frame if both crtcs are enabled | ||
| 208 | */ | ||
| 209 | list_for_each_entry(crtc_p, &crtc->dev->mode_config.crtc_list, head) { | ||
| 210 | if (crtc_p->enabled) | ||
| 211 | i++; | ||
| 212 | } | ||
| 213 | if (i > 1) { | ||
| 214 | int cursor_end, frame_end; | ||
| 215 | |||
| 216 | cursor_end = x - xorigin + w; | ||
| 217 | frame_end = crtc->x + crtc->mode.crtc_hdisplay; | ||
| 218 | if (cursor_end >= frame_end) { | ||
| 219 | w = w - (cursor_end - frame_end); | ||
| 220 | if (!(frame_end & 0x7f)) | ||
| 221 | w--; | ||
| 222 | } else { | ||
| 223 | if (!(cursor_end & 0x7f)) | ||
| 224 | w--; | ||
| 225 | } | ||
| 226 | if (w <= 0) | ||
| 227 | w = 1; | ||
| 228 | } | ||
| 229 | |||
| 230 | WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset, | ||
| 231 | ((xorigin ? 0 : x) << 16) | | ||
| 232 | (yorigin ? 0 : y)); | ||
| 233 | WREG32(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin); | ||
| 234 | WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset, | ||
| 235 | ((w - 1) << 16) | (radeon_crtc->cursor_height - 1)); | ||
| 236 | } else { | ||
| 237 | if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN) | ||
| 238 | y *= 2; | ||
| 239 | |||
| 240 | WREG32(RADEON_CUR_HORZ_VERT_OFF + radeon_crtc->crtc_offset, | ||
| 241 | (RADEON_CUR_LOCK | ||
| 242 | | (xorigin << 16) | ||
| 243 | | yorigin)); | ||
| 244 | WREG32(RADEON_CUR_HORZ_VERT_POSN + radeon_crtc->crtc_offset, | ||
| 245 | (RADEON_CUR_LOCK | ||
| 246 | | ((xorigin ? 0 : x) << 16) | ||
| 247 | | (yorigin ? 0 : y))); | ||
| 248 | } | ||
| 249 | radeon_lock_cursor(crtc, false); | ||
| 250 | |||
| 251 | return 0; | ||
| 252 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c new file mode 100644 index 000000000000..5fd2b639bf66 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
| @@ -0,0 +1,813 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include <linux/console.h> | ||
| 29 | #include <drm/drmP.h> | ||
| 30 | #include <drm/drm_crtc_helper.h> | ||
| 31 | #include <drm/radeon_drm.h> | ||
| 32 | #include "radeon_reg.h" | ||
| 33 | #include "radeon.h" | ||
| 34 | #include "radeon_asic.h" | ||
| 35 | #include "atom.h" | ||
| 36 | |||
| 37 | /* | ||
| 38 | * GPU scratch registers helpers function. | ||
| 39 | */ | ||
| 40 | static void radeon_scratch_init(struct radeon_device *rdev) | ||
| 41 | { | ||
| 42 | int i; | ||
| 43 | |||
| 44 | /* FIXME: check this out */ | ||
| 45 | if (rdev->family < CHIP_R300) { | ||
| 46 | rdev->scratch.num_reg = 5; | ||
| 47 | } else { | ||
| 48 | rdev->scratch.num_reg = 7; | ||
| 49 | } | ||
| 50 | for (i = 0; i < rdev->scratch.num_reg; i++) { | ||
| 51 | rdev->scratch.free[i] = true; | ||
| 52 | rdev->scratch.reg[i] = RADEON_SCRATCH_REG0 + (i * 4); | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | int radeon_scratch_get(struct radeon_device *rdev, uint32_t *reg) | ||
| 57 | { | ||
| 58 | int i; | ||
| 59 | |||
| 60 | for (i = 0; i < rdev->scratch.num_reg; i++) { | ||
| 61 | if (rdev->scratch.free[i]) { | ||
| 62 | rdev->scratch.free[i] = false; | ||
| 63 | *reg = rdev->scratch.reg[i]; | ||
| 64 | return 0; | ||
| 65 | } | ||
| 66 | } | ||
| 67 | return -EINVAL; | ||
| 68 | } | ||
| 69 | |||
| 70 | void radeon_scratch_free(struct radeon_device *rdev, uint32_t reg) | ||
| 71 | { | ||
| 72 | int i; | ||
| 73 | |||
| 74 | for (i = 0; i < rdev->scratch.num_reg; i++) { | ||
| 75 | if (rdev->scratch.reg[i] == reg) { | ||
| 76 | rdev->scratch.free[i] = true; | ||
| 77 | return; | ||
| 78 | } | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | /* | ||
| 83 | * MC common functions | ||
| 84 | */ | ||
| 85 | int radeon_mc_setup(struct radeon_device *rdev) | ||
| 86 | { | ||
| 87 | uint32_t tmp; | ||
| 88 | |||
| 89 | /* Some chips have an "issue" with the memory controller, the | ||
| 90 | * location must be aligned to the size. We just align it down, | ||
| 91 | * too bad if we walk over the top of system memory, we don't | ||
| 92 | * use DMA without a remapped anyway. | ||
| 93 | * Affected chips are rv280, all r3xx, and all r4xx, but not IGP | ||
| 94 | */ | ||
| 95 | /* FGLRX seems to setup like this, VRAM a 0, then GART. | ||
| 96 | */ | ||
| 97 | /* | ||
| 98 | * Note: from R6xx the address space is 40bits but here we only | ||
| 99 | * use 32bits (still have to see a card which would exhaust 4G | ||
| 100 | * address space). | ||
| 101 | */ | ||
| 102 | if (rdev->mc.vram_location != 0xFFFFFFFFUL) { | ||
| 103 | /* vram location was already setup try to put gtt after | ||
| 104 | * if it fits */ | ||
| 105 | tmp = rdev->mc.vram_location + rdev->mc.vram_size; | ||
| 106 | tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1); | ||
| 107 | if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) { | ||
| 108 | rdev->mc.gtt_location = tmp; | ||
| 109 | } else { | ||
| 110 | if (rdev->mc.gtt_size >= rdev->mc.vram_location) { | ||
| 111 | printk(KERN_ERR "[drm] GTT too big to fit " | ||
| 112 | "before or after vram location.\n"); | ||
| 113 | return -EINVAL; | ||
| 114 | } | ||
| 115 | rdev->mc.gtt_location = 0; | ||
| 116 | } | ||
| 117 | } else if (rdev->mc.gtt_location != 0xFFFFFFFFUL) { | ||
| 118 | /* gtt location was already setup try to put vram before | ||
| 119 | * if it fits */ | ||
| 120 | if (rdev->mc.vram_size < rdev->mc.gtt_location) { | ||
| 121 | rdev->mc.vram_location = 0; | ||
| 122 | } else { | ||
| 123 | tmp = rdev->mc.gtt_location + rdev->mc.gtt_size; | ||
| 124 | tmp += (rdev->mc.vram_size - 1); | ||
| 125 | tmp &= ~(rdev->mc.vram_size - 1); | ||
| 126 | if ((0xFFFFFFFFUL - tmp) >= rdev->mc.vram_size) { | ||
| 127 | rdev->mc.vram_location = tmp; | ||
| 128 | } else { | ||
| 129 | printk(KERN_ERR "[drm] vram too big to fit " | ||
| 130 | "before or after GTT location.\n"); | ||
| 131 | return -EINVAL; | ||
| 132 | } | ||
| 133 | } | ||
| 134 | } else { | ||
| 135 | rdev->mc.vram_location = 0; | ||
| 136 | rdev->mc.gtt_location = rdev->mc.vram_size; | ||
| 137 | } | ||
| 138 | DRM_INFO("radeon: VRAM %uM\n", rdev->mc.vram_size >> 20); | ||
| 139 | DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n", | ||
| 140 | rdev->mc.vram_location, | ||
| 141 | rdev->mc.vram_location + rdev->mc.vram_size - 1); | ||
| 142 | DRM_INFO("radeon: GTT %uM\n", rdev->mc.gtt_size >> 20); | ||
| 143 | DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n", | ||
| 144 | rdev->mc.gtt_location, | ||
| 145 | rdev->mc.gtt_location + rdev->mc.gtt_size - 1); | ||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | |||
| 150 | /* | ||
| 151 | * GPU helpers function. | ||
| 152 | */ | ||
| 153 | static bool radeon_card_posted(struct radeon_device *rdev) | ||
| 154 | { | ||
| 155 | uint32_t reg; | ||
| 156 | |||
| 157 | /* first check CRTCs */ | ||
| 158 | if (ASIC_IS_AVIVO(rdev)) { | ||
| 159 | reg = RREG32(AVIVO_D1CRTC_CONTROL) | | ||
| 160 | RREG32(AVIVO_D2CRTC_CONTROL); | ||
| 161 | if (reg & AVIVO_CRTC_EN) { | ||
| 162 | return true; | ||
| 163 | } | ||
| 164 | } else { | ||
| 165 | reg = RREG32(RADEON_CRTC_GEN_CNTL) | | ||
| 166 | RREG32(RADEON_CRTC2_GEN_CNTL); | ||
| 167 | if (reg & RADEON_CRTC_EN) { | ||
| 168 | return true; | ||
| 169 | } | ||
| 170 | } | ||
| 171 | |||
| 172 | /* then check MEM_SIZE, in case the crtcs are off */ | ||
| 173 | if (rdev->family >= CHIP_R600) | ||
| 174 | reg = RREG32(R600_CONFIG_MEMSIZE); | ||
| 175 | else | ||
| 176 | reg = RREG32(RADEON_CONFIG_MEMSIZE); | ||
| 177 | |||
| 178 | if (reg) | ||
| 179 | return true; | ||
| 180 | |||
| 181 | return false; | ||
| 182 | |||
| 183 | } | ||
| 184 | |||
| 185 | |||
| 186 | /* | ||
| 187 | * Registers accessors functions. | ||
| 188 | */ | ||
| 189 | uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg) | ||
| 190 | { | ||
| 191 | DRM_ERROR("Invalid callback to read register 0x%04X\n", reg); | ||
| 192 | BUG_ON(1); | ||
| 193 | return 0; | ||
| 194 | } | ||
| 195 | |||
| 196 | void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | ||
| 197 | { | ||
| 198 | DRM_ERROR("Invalid callback to write register 0x%04X with 0x%08X\n", | ||
| 199 | reg, v); | ||
| 200 | BUG_ON(1); | ||
| 201 | } | ||
| 202 | |||
| 203 | void radeon_register_accessor_init(struct radeon_device *rdev) | ||
| 204 | { | ||
| 205 | rdev->mm_rreg = &r100_mm_rreg; | ||
| 206 | rdev->mm_wreg = &r100_mm_wreg; | ||
| 207 | rdev->mc_rreg = &radeon_invalid_rreg; | ||
| 208 | rdev->mc_wreg = &radeon_invalid_wreg; | ||
| 209 | rdev->pll_rreg = &radeon_invalid_rreg; | ||
| 210 | rdev->pll_wreg = &radeon_invalid_wreg; | ||
| 211 | rdev->pcie_rreg = &radeon_invalid_rreg; | ||
| 212 | rdev->pcie_wreg = &radeon_invalid_wreg; | ||
| 213 | rdev->pciep_rreg = &radeon_invalid_rreg; | ||
| 214 | rdev->pciep_wreg = &radeon_invalid_wreg; | ||
| 215 | |||
| 216 | /* Don't change order as we are overridding accessor. */ | ||
| 217 | if (rdev->family < CHIP_RV515) { | ||
| 218 | rdev->pcie_rreg = &rv370_pcie_rreg; | ||
| 219 | rdev->pcie_wreg = &rv370_pcie_wreg; | ||
| 220 | } | ||
| 221 | if (rdev->family >= CHIP_RV515) { | ||
| 222 | rdev->pcie_rreg = &rv515_pcie_rreg; | ||
| 223 | rdev->pcie_wreg = &rv515_pcie_wreg; | ||
| 224 | } | ||
| 225 | /* FIXME: not sure here */ | ||
| 226 | if (rdev->family <= CHIP_R580) { | ||
| 227 | rdev->pll_rreg = &r100_pll_rreg; | ||
| 228 | rdev->pll_wreg = &r100_pll_wreg; | ||
| 229 | } | ||
| 230 | if (rdev->family >= CHIP_RV515) { | ||
| 231 | rdev->mc_rreg = &rv515_mc_rreg; | ||
| 232 | rdev->mc_wreg = &rv515_mc_wreg; | ||
| 233 | } | ||
| 234 | if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) { | ||
| 235 | rdev->mc_rreg = &rs400_mc_rreg; | ||
| 236 | rdev->mc_wreg = &rs400_mc_wreg; | ||
| 237 | } | ||
| 238 | if (rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { | ||
| 239 | rdev->mc_rreg = &rs690_mc_rreg; | ||
| 240 | rdev->mc_wreg = &rs690_mc_wreg; | ||
| 241 | } | ||
| 242 | if (rdev->family == CHIP_RS600) { | ||
| 243 | rdev->mc_rreg = &rs600_mc_rreg; | ||
| 244 | rdev->mc_wreg = &rs600_mc_wreg; | ||
| 245 | } | ||
| 246 | if (rdev->family >= CHIP_R600) { | ||
| 247 | rdev->pciep_rreg = &r600_pciep_rreg; | ||
| 248 | rdev->pciep_wreg = &r600_pciep_wreg; | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | |||
| 253 | /* | ||
| 254 | * ASIC | ||
| 255 | */ | ||
| 256 | int radeon_asic_init(struct radeon_device *rdev) | ||
| 257 | { | ||
| 258 | radeon_register_accessor_init(rdev); | ||
| 259 | switch (rdev->family) { | ||
| 260 | case CHIP_R100: | ||
| 261 | case CHIP_RV100: | ||
| 262 | case CHIP_RS100: | ||
| 263 | case CHIP_RV200: | ||
| 264 | case CHIP_RS200: | ||
| 265 | case CHIP_R200: | ||
| 266 | case CHIP_RV250: | ||
| 267 | case CHIP_RS300: | ||
| 268 | case CHIP_RV280: | ||
| 269 | rdev->asic = &r100_asic; | ||
| 270 | break; | ||
| 271 | case CHIP_R300: | ||
| 272 | case CHIP_R350: | ||
| 273 | case CHIP_RV350: | ||
| 274 | case CHIP_RV380: | ||
| 275 | rdev->asic = &r300_asic; | ||
| 276 | break; | ||
| 277 | case CHIP_R420: | ||
| 278 | case CHIP_R423: | ||
| 279 | case CHIP_RV410: | ||
| 280 | rdev->asic = &r420_asic; | ||
| 281 | break; | ||
| 282 | case CHIP_RS400: | ||
| 283 | case CHIP_RS480: | ||
| 284 | rdev->asic = &rs400_asic; | ||
| 285 | break; | ||
| 286 | case CHIP_RS600: | ||
| 287 | rdev->asic = &rs600_asic; | ||
| 288 | break; | ||
| 289 | case CHIP_RS690: | ||
| 290 | case CHIP_RS740: | ||
| 291 | rdev->asic = &rs690_asic; | ||
| 292 | break; | ||
| 293 | case CHIP_RV515: | ||
| 294 | rdev->asic = &rv515_asic; | ||
| 295 | break; | ||
| 296 | case CHIP_R520: | ||
| 297 | case CHIP_RV530: | ||
| 298 | case CHIP_RV560: | ||
| 299 | case CHIP_RV570: | ||
| 300 | case CHIP_R580: | ||
| 301 | rdev->asic = &r520_asic; | ||
| 302 | break; | ||
| 303 | case CHIP_R600: | ||
| 304 | case CHIP_RV610: | ||
| 305 | case CHIP_RV630: | ||
| 306 | case CHIP_RV620: | ||
| 307 | case CHIP_RV635: | ||
| 308 | case CHIP_RV670: | ||
| 309 | case CHIP_RS780: | ||
| 310 | case CHIP_RV770: | ||
| 311 | case CHIP_RV730: | ||
| 312 | case CHIP_RV710: | ||
| 313 | default: | ||
| 314 | /* FIXME: not supported yet */ | ||
| 315 | return -EINVAL; | ||
| 316 | } | ||
| 317 | return 0; | ||
| 318 | } | ||
| 319 | |||
| 320 | |||
| 321 | /* | ||
| 322 | * Wrapper around modesetting bits. | ||
| 323 | */ | ||
| 324 | int radeon_clocks_init(struct radeon_device *rdev) | ||
| 325 | { | ||
| 326 | int r; | ||
| 327 | |||
| 328 | radeon_get_clock_info(rdev->ddev); | ||
| 329 | r = radeon_static_clocks_init(rdev->ddev); | ||
| 330 | if (r) { | ||
| 331 | return r; | ||
| 332 | } | ||
| 333 | DRM_INFO("Clocks initialized !\n"); | ||
| 334 | return 0; | ||
| 335 | } | ||
| 336 | |||
| 337 | void radeon_clocks_fini(struct radeon_device *rdev) | ||
| 338 | { | ||
| 339 | } | ||
| 340 | |||
| 341 | /* ATOM accessor methods */ | ||
| 342 | static uint32_t cail_pll_read(struct card_info *info, uint32_t reg) | ||
| 343 | { | ||
| 344 | struct radeon_device *rdev = info->dev->dev_private; | ||
| 345 | uint32_t r; | ||
| 346 | |||
| 347 | r = rdev->pll_rreg(rdev, reg); | ||
| 348 | return r; | ||
| 349 | } | ||
| 350 | |||
| 351 | static void cail_pll_write(struct card_info *info, uint32_t reg, uint32_t val) | ||
| 352 | { | ||
| 353 | struct radeon_device *rdev = info->dev->dev_private; | ||
| 354 | |||
| 355 | rdev->pll_wreg(rdev, reg, val); | ||
| 356 | } | ||
| 357 | |||
| 358 | static uint32_t cail_mc_read(struct card_info *info, uint32_t reg) | ||
| 359 | { | ||
| 360 | struct radeon_device *rdev = info->dev->dev_private; | ||
| 361 | uint32_t r; | ||
| 362 | |||
| 363 | r = rdev->mc_rreg(rdev, reg); | ||
| 364 | return r; | ||
| 365 | } | ||
| 366 | |||
| 367 | static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val) | ||
| 368 | { | ||
| 369 | struct radeon_device *rdev = info->dev->dev_private; | ||
| 370 | |||
| 371 | rdev->mc_wreg(rdev, reg, val); | ||
| 372 | } | ||
| 373 | |||
| 374 | static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val) | ||
| 375 | { | ||
| 376 | struct radeon_device *rdev = info->dev->dev_private; | ||
| 377 | |||
| 378 | WREG32(reg*4, val); | ||
| 379 | } | ||
| 380 | |||
| 381 | static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) | ||
| 382 | { | ||
| 383 | struct radeon_device *rdev = info->dev->dev_private; | ||
| 384 | uint32_t r; | ||
| 385 | |||
| 386 | r = RREG32(reg*4); | ||
| 387 | return r; | ||
| 388 | } | ||
| 389 | |||
| 390 | static struct card_info atom_card_info = { | ||
| 391 | .dev = NULL, | ||
| 392 | .reg_read = cail_reg_read, | ||
| 393 | .reg_write = cail_reg_write, | ||
| 394 | .mc_read = cail_mc_read, | ||
| 395 | .mc_write = cail_mc_write, | ||
| 396 | .pll_read = cail_pll_read, | ||
| 397 | .pll_write = cail_pll_write, | ||
| 398 | }; | ||
| 399 | |||
| 400 | int radeon_atombios_init(struct radeon_device *rdev) | ||
| 401 | { | ||
| 402 | atom_card_info.dev = rdev->ddev; | ||
| 403 | rdev->mode_info.atom_context = atom_parse(&atom_card_info, rdev->bios); | ||
| 404 | radeon_atom_initialize_bios_scratch_regs(rdev->ddev); | ||
| 405 | return 0; | ||
| 406 | } | ||
| 407 | |||
| 408 | void radeon_atombios_fini(struct radeon_device *rdev) | ||
| 409 | { | ||
| 410 | kfree(rdev->mode_info.atom_context); | ||
| 411 | } | ||
| 412 | |||
| 413 | int radeon_combios_init(struct radeon_device *rdev) | ||
| 414 | { | ||
| 415 | radeon_combios_initialize_bios_scratch_regs(rdev->ddev); | ||
| 416 | return 0; | ||
| 417 | } | ||
| 418 | |||
| 419 | void radeon_combios_fini(struct radeon_device *rdev) | ||
| 420 | { | ||
| 421 | } | ||
| 422 | |||
| 423 | int radeon_modeset_init(struct radeon_device *rdev); | ||
| 424 | void radeon_modeset_fini(struct radeon_device *rdev); | ||
| 425 | |||
| 426 | |||
| 427 | /* | ||
| 428 | * Radeon device. | ||
| 429 | */ | ||
| 430 | int radeon_device_init(struct radeon_device *rdev, | ||
| 431 | struct drm_device *ddev, | ||
| 432 | struct pci_dev *pdev, | ||
| 433 | uint32_t flags) | ||
| 434 | { | ||
| 435 | int r, ret; | ||
| 436 | |||
| 437 | DRM_INFO("radeon: Initializing kernel modesetting.\n"); | ||
| 438 | rdev->shutdown = false; | ||
| 439 | rdev->ddev = ddev; | ||
| 440 | rdev->pdev = pdev; | ||
| 441 | rdev->flags = flags; | ||
| 442 | rdev->family = flags & RADEON_FAMILY_MASK; | ||
| 443 | rdev->is_atom_bios = false; | ||
| 444 | rdev->usec_timeout = RADEON_MAX_USEC_TIMEOUT; | ||
| 445 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; | ||
| 446 | rdev->gpu_lockup = false; | ||
| 447 | /* mutex initialization are all done here so we | ||
| 448 | * can recall function without having locking issues */ | ||
| 449 | mutex_init(&rdev->cs_mutex); | ||
| 450 | mutex_init(&rdev->ib_pool.mutex); | ||
| 451 | mutex_init(&rdev->cp.mutex); | ||
| 452 | rwlock_init(&rdev->fence_drv.lock); | ||
| 453 | |||
| 454 | if (radeon_agpmode == -1) { | ||
| 455 | rdev->flags &= ~RADEON_IS_AGP; | ||
| 456 | if (rdev->family > CHIP_RV515 || | ||
| 457 | rdev->family == CHIP_RV380 || | ||
| 458 | rdev->family == CHIP_RV410 || | ||
| 459 | rdev->family == CHIP_R423) { | ||
| 460 | DRM_INFO("Forcing AGP to PCIE mode\n"); | ||
| 461 | rdev->flags |= RADEON_IS_PCIE; | ||
| 462 | } else { | ||
| 463 | DRM_INFO("Forcing AGP to PCI mode\n"); | ||
| 464 | rdev->flags |= RADEON_IS_PCI; | ||
| 465 | } | ||
| 466 | } | ||
| 467 | |||
| 468 | /* Set asic functions */ | ||
| 469 | r = radeon_asic_init(rdev); | ||
| 470 | if (r) { | ||
| 471 | return r; | ||
| 472 | } | ||
| 473 | |||
| 474 | /* Report DMA addressing limitation */ | ||
| 475 | r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(32)); | ||
| 476 | if (r) { | ||
| 477 | printk(KERN_WARNING "radeon: No suitable DMA available.\n"); | ||
| 478 | } | ||
| 479 | |||
| 480 | /* Registers mapping */ | ||
| 481 | /* TODO: block userspace mapping of io register */ | ||
| 482 | rdev->rmmio_base = drm_get_resource_start(rdev->ddev, 2); | ||
| 483 | rdev->rmmio_size = drm_get_resource_len(rdev->ddev, 2); | ||
| 484 | rdev->rmmio = ioremap(rdev->rmmio_base, rdev->rmmio_size); | ||
| 485 | if (rdev->rmmio == NULL) { | ||
| 486 | return -ENOMEM; | ||
| 487 | } | ||
| 488 | DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)rdev->rmmio_base); | ||
| 489 | DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size); | ||
| 490 | |||
| 491 | /* Setup errata flags */ | ||
| 492 | radeon_errata(rdev); | ||
| 493 | /* Initialize scratch registers */ | ||
| 494 | radeon_scratch_init(rdev); | ||
| 495 | |||
| 496 | /* TODO: disable VGA need to use VGA request */ | ||
| 497 | /* BIOS*/ | ||
| 498 | if (!radeon_get_bios(rdev)) { | ||
| 499 | if (ASIC_IS_AVIVO(rdev)) | ||
| 500 | return -EINVAL; | ||
| 501 | } | ||
| 502 | if (rdev->is_atom_bios) { | ||
| 503 | r = radeon_atombios_init(rdev); | ||
| 504 | if (r) { | ||
| 505 | return r; | ||
| 506 | } | ||
| 507 | } else { | ||
| 508 | r = radeon_combios_init(rdev); | ||
| 509 | if (r) { | ||
| 510 | return r; | ||
| 511 | } | ||
| 512 | } | ||
| 513 | /* Reset gpu before posting otherwise ATOM will enter infinite loop */ | ||
| 514 | if (radeon_gpu_reset(rdev)) { | ||
| 515 | /* FIXME: what do we want to do here ? */ | ||
| 516 | } | ||
| 517 | /* check if cards are posted or not */ | ||
| 518 | if (!radeon_card_posted(rdev) && rdev->bios) { | ||
| 519 | DRM_INFO("GPU not posted. posting now...\n"); | ||
| 520 | if (rdev->is_atom_bios) { | ||
| 521 | atom_asic_init(rdev->mode_info.atom_context); | ||
| 522 | } else { | ||
| 523 | radeon_combios_asic_init(rdev->ddev); | ||
| 524 | } | ||
| 525 | } | ||
| 526 | /* Get vram informations */ | ||
| 527 | radeon_vram_info(rdev); | ||
| 528 | /* Device is severly broken if aper size > vram size. | ||
| 529 | * for RN50/M6/M7 - Novell bug 204882 ? | ||
| 530 | */ | ||
| 531 | if (rdev->mc.vram_size < rdev->mc.aper_size) { | ||
| 532 | rdev->mc.aper_size = rdev->mc.vram_size; | ||
| 533 | } | ||
| 534 | /* Add an MTRR for the VRAM */ | ||
| 535 | rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size, | ||
| 536 | MTRR_TYPE_WRCOMB, 1); | ||
| 537 | DRM_INFO("Detected VRAM RAM=%uM, BAR=%uM\n", | ||
| 538 | rdev->mc.vram_size >> 20, | ||
| 539 | (unsigned)rdev->mc.aper_size >> 20); | ||
| 540 | DRM_INFO("RAM width %dbits %cDR\n", | ||
| 541 | rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S'); | ||
| 542 | /* Initialize clocks */ | ||
| 543 | r = radeon_clocks_init(rdev); | ||
| 544 | if (r) { | ||
| 545 | return r; | ||
| 546 | } | ||
| 547 | /* Initialize memory controller (also test AGP) */ | ||
| 548 | r = radeon_mc_init(rdev); | ||
| 549 | if (r) { | ||
| 550 | return r; | ||
| 551 | } | ||
| 552 | /* Fence driver */ | ||
| 553 | r = radeon_fence_driver_init(rdev); | ||
| 554 | if (r) { | ||
| 555 | return r; | ||
| 556 | } | ||
| 557 | r = radeon_irq_kms_init(rdev); | ||
| 558 | if (r) { | ||
| 559 | return r; | ||
| 560 | } | ||
| 561 | /* Memory manager */ | ||
| 562 | r = radeon_object_init(rdev); | ||
| 563 | if (r) { | ||
| 564 | return r; | ||
| 565 | } | ||
| 566 | /* Initialize GART (initialize after TTM so we can allocate | ||
| 567 | * memory through TTM but finalize after TTM) */ | ||
| 568 | r = radeon_gart_enable(rdev); | ||
| 569 | if (!r) { | ||
| 570 | r = radeon_gem_init(rdev); | ||
| 571 | } | ||
| 572 | |||
| 573 | /* 1M ring buffer */ | ||
| 574 | if (!r) { | ||
| 575 | r = radeon_cp_init(rdev, 1024 * 1024); | ||
| 576 | } | ||
| 577 | if (!r) { | ||
| 578 | r = radeon_wb_init(rdev); | ||
| 579 | if (r) { | ||
| 580 | DRM_ERROR("radeon: failled initializing WB (%d).\n", r); | ||
| 581 | return r; | ||
| 582 | } | ||
| 583 | } | ||
| 584 | if (!r) { | ||
| 585 | r = radeon_ib_pool_init(rdev); | ||
| 586 | if (r) { | ||
| 587 | DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r); | ||
| 588 | return r; | ||
| 589 | } | ||
| 590 | } | ||
| 591 | if (!r) { | ||
| 592 | r = radeon_ib_test(rdev); | ||
| 593 | if (r) { | ||
| 594 | DRM_ERROR("radeon: failled testing IB (%d).\n", r); | ||
| 595 | return r; | ||
| 596 | } | ||
| 597 | } | ||
| 598 | ret = r; | ||
| 599 | r = radeon_modeset_init(rdev); | ||
| 600 | if (r) { | ||
| 601 | return r; | ||
| 602 | } | ||
| 603 | if (rdev->fbdev_rfb && rdev->fbdev_rfb->obj) { | ||
| 604 | rdev->fbdev_robj = rdev->fbdev_rfb->obj->driver_private; | ||
| 605 | } | ||
| 606 | if (!ret) { | ||
| 607 | DRM_INFO("radeon: kernel modesetting successfully initialized.\n"); | ||
| 608 | } | ||
| 609 | if (radeon_benchmarking) { | ||
| 610 | radeon_benchmark(rdev); | ||
| 611 | } | ||
| 612 | return ret; | ||
| 613 | } | ||
| 614 | |||
| 615 | void radeon_device_fini(struct radeon_device *rdev) | ||
| 616 | { | ||
| 617 | if (rdev == NULL || rdev->rmmio == NULL) { | ||
| 618 | return; | ||
| 619 | } | ||
| 620 | DRM_INFO("radeon: finishing device.\n"); | ||
| 621 | rdev->shutdown = true; | ||
| 622 | /* Order matter so becarefull if you rearrange anythings */ | ||
| 623 | radeon_modeset_fini(rdev); | ||
| 624 | radeon_ib_pool_fini(rdev); | ||
| 625 | radeon_cp_fini(rdev); | ||
| 626 | radeon_wb_fini(rdev); | ||
| 627 | radeon_gem_fini(rdev); | ||
| 628 | radeon_object_fini(rdev); | ||
| 629 | /* mc_fini must be after object_fini */ | ||
| 630 | radeon_mc_fini(rdev); | ||
| 631 | #if __OS_HAS_AGP | ||
| 632 | radeon_agp_fini(rdev); | ||
| 633 | #endif | ||
| 634 | radeon_irq_kms_fini(rdev); | ||
| 635 | radeon_fence_driver_fini(rdev); | ||
| 636 | radeon_clocks_fini(rdev); | ||
| 637 | if (rdev->is_atom_bios) { | ||
| 638 | radeon_atombios_fini(rdev); | ||
| 639 | } else { | ||
| 640 | radeon_combios_fini(rdev); | ||
| 641 | } | ||
| 642 | kfree(rdev->bios); | ||
| 643 | rdev->bios = NULL; | ||
| 644 | iounmap(rdev->rmmio); | ||
| 645 | rdev->rmmio = NULL; | ||
| 646 | } | ||
| 647 | |||
| 648 | |||
| 649 | /* | ||
| 650 | * Suspend & resume. | ||
| 651 | */ | ||
| 652 | int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | ||
| 653 | { | ||
| 654 | struct radeon_device *rdev = dev->dev_private; | ||
| 655 | struct drm_crtc *crtc; | ||
| 656 | |||
| 657 | if (dev == NULL || rdev == NULL) { | ||
| 658 | return -ENODEV; | ||
| 659 | } | ||
| 660 | if (state.event == PM_EVENT_PRETHAW) { | ||
| 661 | return 0; | ||
| 662 | } | ||
| 663 | /* unpin the front buffers */ | ||
| 664 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
| 665 | struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb); | ||
| 666 | struct radeon_object *robj; | ||
| 667 | |||
| 668 | if (rfb == NULL || rfb->obj == NULL) { | ||
| 669 | continue; | ||
| 670 | } | ||
| 671 | robj = rfb->obj->driver_private; | ||
| 672 | if (robj != rdev->fbdev_robj) { | ||
| 673 | radeon_object_unpin(robj); | ||
| 674 | } | ||
| 675 | } | ||
| 676 | /* evict vram memory */ | ||
| 677 | radeon_object_evict_vram(rdev); | ||
| 678 | /* wait for gpu to finish processing current batch */ | ||
| 679 | radeon_fence_wait_last(rdev); | ||
| 680 | |||
| 681 | radeon_cp_disable(rdev); | ||
| 682 | radeon_gart_disable(rdev); | ||
| 683 | |||
| 684 | /* evict remaining vram memory */ | ||
| 685 | radeon_object_evict_vram(rdev); | ||
| 686 | |||
| 687 | rdev->irq.sw_int = false; | ||
| 688 | radeon_irq_set(rdev); | ||
| 689 | |||
| 690 | pci_save_state(dev->pdev); | ||
| 691 | if (state.event == PM_EVENT_SUSPEND) { | ||
| 692 | /* Shut down the device */ | ||
| 693 | pci_disable_device(dev->pdev); | ||
| 694 | pci_set_power_state(dev->pdev, PCI_D3hot); | ||
| 695 | } | ||
| 696 | acquire_console_sem(); | ||
| 697 | fb_set_suspend(rdev->fbdev_info, 1); | ||
| 698 | release_console_sem(); | ||
| 699 | return 0; | ||
| 700 | } | ||
| 701 | |||
| 702 | int radeon_resume_kms(struct drm_device *dev) | ||
| 703 | { | ||
| 704 | struct radeon_device *rdev = dev->dev_private; | ||
| 705 | int r; | ||
| 706 | |||
| 707 | acquire_console_sem(); | ||
| 708 | pci_set_power_state(dev->pdev, PCI_D0); | ||
| 709 | pci_restore_state(dev->pdev); | ||
| 710 | if (pci_enable_device(dev->pdev)) { | ||
| 711 | release_console_sem(); | ||
| 712 | return -1; | ||
| 713 | } | ||
| 714 | pci_set_master(dev->pdev); | ||
| 715 | /* Reset gpu before posting otherwise ATOM will enter infinite loop */ | ||
| 716 | if (radeon_gpu_reset(rdev)) { | ||
| 717 | /* FIXME: what do we want to do here ? */ | ||
| 718 | } | ||
| 719 | /* post card */ | ||
| 720 | if (rdev->is_atom_bios) { | ||
| 721 | atom_asic_init(rdev->mode_info.atom_context); | ||
| 722 | } else { | ||
| 723 | radeon_combios_asic_init(rdev->ddev); | ||
| 724 | } | ||
| 725 | /* Initialize clocks */ | ||
| 726 | r = radeon_clocks_init(rdev); | ||
| 727 | if (r) { | ||
| 728 | release_console_sem(); | ||
| 729 | return r; | ||
| 730 | } | ||
| 731 | /* Enable IRQ */ | ||
| 732 | rdev->irq.sw_int = true; | ||
| 733 | radeon_irq_set(rdev); | ||
| 734 | /* Initialize GPU Memory Controller */ | ||
| 735 | r = radeon_mc_init(rdev); | ||
| 736 | if (r) { | ||
| 737 | goto out; | ||
| 738 | } | ||
| 739 | r = radeon_gart_enable(rdev); | ||
| 740 | if (r) { | ||
| 741 | goto out; | ||
| 742 | } | ||
| 743 | r = radeon_cp_init(rdev, rdev->cp.ring_size); | ||
| 744 | if (r) { | ||
| 745 | goto out; | ||
| 746 | } | ||
| 747 | out: | ||
| 748 | fb_set_suspend(rdev->fbdev_info, 0); | ||
| 749 | release_console_sem(); | ||
| 750 | |||
| 751 | /* blat the mode back in */ | ||
| 752 | drm_helper_resume_force_mode(dev); | ||
| 753 | return 0; | ||
| 754 | } | ||
| 755 | |||
| 756 | |||
| 757 | /* | ||
| 758 | * Debugfs | ||
| 759 | */ | ||
| 760 | struct radeon_debugfs { | ||
| 761 | struct drm_info_list *files; | ||
| 762 | unsigned num_files; | ||
| 763 | }; | ||
| 764 | static struct radeon_debugfs _radeon_debugfs[RADEON_DEBUGFS_MAX_NUM_FILES]; | ||
| 765 | static unsigned _radeon_debugfs_count = 0; | ||
| 766 | |||
| 767 | int radeon_debugfs_add_files(struct radeon_device *rdev, | ||
| 768 | struct drm_info_list *files, | ||
| 769 | unsigned nfiles) | ||
| 770 | { | ||
| 771 | unsigned i; | ||
| 772 | |||
| 773 | for (i = 0; i < _radeon_debugfs_count; i++) { | ||
| 774 | if (_radeon_debugfs[i].files == files) { | ||
| 775 | /* Already registered */ | ||
| 776 | return 0; | ||
| 777 | } | ||
| 778 | } | ||
| 779 | if ((_radeon_debugfs_count + nfiles) > RADEON_DEBUGFS_MAX_NUM_FILES) { | ||
| 780 | DRM_ERROR("Reached maximum number of debugfs files.\n"); | ||
| 781 | DRM_ERROR("Report so we increase RADEON_DEBUGFS_MAX_NUM_FILES.\n"); | ||
| 782 | return -EINVAL; | ||
| 783 | } | ||
| 784 | _radeon_debugfs[_radeon_debugfs_count].files = files; | ||
| 785 | _radeon_debugfs[_radeon_debugfs_count].num_files = nfiles; | ||
| 786 | _radeon_debugfs_count++; | ||
| 787 | #if defined(CONFIG_DEBUG_FS) | ||
| 788 | drm_debugfs_create_files(files, nfiles, | ||
| 789 | rdev->ddev->control->debugfs_root, | ||
| 790 | rdev->ddev->control); | ||
| 791 | drm_debugfs_create_files(files, nfiles, | ||
| 792 | rdev->ddev->primary->debugfs_root, | ||
| 793 | rdev->ddev->primary); | ||
| 794 | #endif | ||
| 795 | return 0; | ||
| 796 | } | ||
| 797 | |||
| 798 | #if defined(CONFIG_DEBUG_FS) | ||
| 799 | int radeon_debugfs_init(struct drm_minor *minor) | ||
| 800 | { | ||
| 801 | return 0; | ||
| 802 | } | ||
| 803 | |||
| 804 | void radeon_debugfs_cleanup(struct drm_minor *minor) | ||
| 805 | { | ||
| 806 | unsigned i; | ||
| 807 | |||
| 808 | for (i = 0; i < _radeon_debugfs_count; i++) { | ||
| 809 | drm_debugfs_remove_files(_radeon_debugfs[i].files, | ||
| 810 | _radeon_debugfs[i].num_files, minor); | ||
| 811 | } | ||
| 812 | } | ||
| 813 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c new file mode 100644 index 000000000000..5452bb9d925e --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
| @@ -0,0 +1,692 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2007-8 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * copy of this software and associated documentation files (the "Software"), | ||
| 7 | * to deal in the Software without restriction, including without limitation | ||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 10 | * Software is furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 21 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: Dave Airlie | ||
| 24 | * Alex Deucher | ||
| 25 | */ | ||
| 26 | #include "drmP.h" | ||
| 27 | #include "radeon_drm.h" | ||
| 28 | #include "radeon.h" | ||
| 29 | |||
| 30 | #include "atom.h" | ||
| 31 | #include <asm/div64.h> | ||
| 32 | |||
| 33 | #include "drm_crtc_helper.h" | ||
| 34 | #include "drm_edid.h" | ||
| 35 | |||
| 36 | static int radeon_ddc_dump(struct drm_connector *connector); | ||
| 37 | |||
| 38 | static void avivo_crtc_load_lut(struct drm_crtc *crtc) | ||
| 39 | { | ||
| 40 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 41 | struct drm_device *dev = crtc->dev; | ||
| 42 | struct radeon_device *rdev = dev->dev_private; | ||
| 43 | int i; | ||
| 44 | |||
| 45 | DRM_DEBUG("%d\n", radeon_crtc->crtc_id); | ||
| 46 | WREG32(AVIVO_DC_LUTA_CONTROL + radeon_crtc->crtc_offset, 0); | ||
| 47 | |||
| 48 | WREG32(AVIVO_DC_LUTA_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0); | ||
| 49 | WREG32(AVIVO_DC_LUTA_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0); | ||
| 50 | WREG32(AVIVO_DC_LUTA_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0); | ||
| 51 | |||
| 52 | WREG32(AVIVO_DC_LUTA_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0xffff); | ||
| 53 | WREG32(AVIVO_DC_LUTA_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0xffff); | ||
| 54 | WREG32(AVIVO_DC_LUTA_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0xffff); | ||
| 55 | |||
| 56 | WREG32(AVIVO_DC_LUT_RW_SELECT, radeon_crtc->crtc_id); | ||
| 57 | WREG32(AVIVO_DC_LUT_RW_MODE, 0); | ||
| 58 | WREG32(AVIVO_DC_LUT_WRITE_EN_MASK, 0x0000003f); | ||
| 59 | |||
| 60 | WREG8(AVIVO_DC_LUT_RW_INDEX, 0); | ||
| 61 | for (i = 0; i < 256; i++) { | ||
| 62 | WREG32(AVIVO_DC_LUT_30_COLOR, | ||
| 63 | (radeon_crtc->lut_r[i] << 20) | | ||
| 64 | (radeon_crtc->lut_g[i] << 10) | | ||
| 65 | (radeon_crtc->lut_b[i] << 0)); | ||
| 66 | } | ||
| 67 | |||
| 68 | WREG32(AVIVO_D1GRPH_LUT_SEL + radeon_crtc->crtc_offset, radeon_crtc->crtc_id); | ||
| 69 | } | ||
| 70 | |||
| 71 | static void legacy_crtc_load_lut(struct drm_crtc *crtc) | ||
| 72 | { | ||
| 73 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 74 | struct drm_device *dev = crtc->dev; | ||
| 75 | struct radeon_device *rdev = dev->dev_private; | ||
| 76 | int i; | ||
| 77 | uint32_t dac2_cntl; | ||
| 78 | |||
| 79 | dac2_cntl = RREG32(RADEON_DAC_CNTL2); | ||
| 80 | if (radeon_crtc->crtc_id == 0) | ||
| 81 | dac2_cntl &= (uint32_t)~RADEON_DAC2_PALETTE_ACC_CTL; | ||
| 82 | else | ||
| 83 | dac2_cntl |= RADEON_DAC2_PALETTE_ACC_CTL; | ||
| 84 | WREG32(RADEON_DAC_CNTL2, dac2_cntl); | ||
| 85 | |||
| 86 | WREG8(RADEON_PALETTE_INDEX, 0); | ||
| 87 | for (i = 0; i < 256; i++) { | ||
| 88 | WREG32(RADEON_PALETTE_30_DATA, | ||
| 89 | (radeon_crtc->lut_r[i] << 20) | | ||
| 90 | (radeon_crtc->lut_g[i] << 10) | | ||
| 91 | (radeon_crtc->lut_b[i] << 0)); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | void radeon_crtc_load_lut(struct drm_crtc *crtc) | ||
| 96 | { | ||
| 97 | struct drm_device *dev = crtc->dev; | ||
| 98 | struct radeon_device *rdev = dev->dev_private; | ||
| 99 | |||
| 100 | if (!crtc->enabled) | ||
| 101 | return; | ||
| 102 | |||
| 103 | if (ASIC_IS_AVIVO(rdev)) | ||
| 104 | avivo_crtc_load_lut(crtc); | ||
| 105 | else | ||
| 106 | legacy_crtc_load_lut(crtc); | ||
| 107 | } | ||
| 108 | |||
| 109 | /** Sets the color ramps on behalf of RandR */ | ||
| 110 | void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, | ||
| 111 | u16 blue, int regno) | ||
| 112 | { | ||
| 113 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 114 | |||
| 115 | if (regno == 0) | ||
| 116 | DRM_DEBUG("gamma set %d\n", radeon_crtc->crtc_id); | ||
| 117 | radeon_crtc->lut_r[regno] = red >> 6; | ||
| 118 | radeon_crtc->lut_g[regno] = green >> 6; | ||
| 119 | radeon_crtc->lut_b[regno] = blue >> 6; | ||
| 120 | } | ||
| 121 | |||
| 122 | static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, | ||
| 123 | u16 *blue, uint32_t size) | ||
| 124 | { | ||
| 125 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 126 | int i, j; | ||
| 127 | |||
| 128 | if (size != 256) { | ||
| 129 | return; | ||
| 130 | } | ||
| 131 | if (crtc->fb == NULL) { | ||
| 132 | return; | ||
| 133 | } | ||
| 134 | |||
| 135 | if (crtc->fb->depth == 16) { | ||
| 136 | for (i = 0; i < 64; i++) { | ||
| 137 | if (i <= 31) { | ||
| 138 | for (j = 0; j < 8; j++) { | ||
| 139 | radeon_crtc->lut_r[i * 8 + j] = red[i] >> 6; | ||
| 140 | radeon_crtc->lut_b[i * 8 + j] = blue[i] >> 6; | ||
| 141 | } | ||
| 142 | } | ||
| 143 | for (j = 0; j < 4; j++) | ||
| 144 | radeon_crtc->lut_g[i * 4 + j] = green[i] >> 6; | ||
| 145 | } | ||
| 146 | } else { | ||
| 147 | for (i = 0; i < 256; i++) { | ||
| 148 | radeon_crtc->lut_r[i] = red[i] >> 6; | ||
| 149 | radeon_crtc->lut_g[i] = green[i] >> 6; | ||
| 150 | radeon_crtc->lut_b[i] = blue[i] >> 6; | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | radeon_crtc_load_lut(crtc); | ||
| 155 | } | ||
| 156 | |||
| 157 | static void radeon_crtc_destroy(struct drm_crtc *crtc) | ||
| 158 | { | ||
| 159 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 160 | |||
| 161 | if (radeon_crtc->mode_set.mode) { | ||
| 162 | drm_mode_destroy(crtc->dev, radeon_crtc->mode_set.mode); | ||
| 163 | } | ||
| 164 | drm_crtc_cleanup(crtc); | ||
| 165 | kfree(radeon_crtc); | ||
| 166 | } | ||
| 167 | |||
| 168 | static const struct drm_crtc_funcs radeon_crtc_funcs = { | ||
| 169 | .cursor_set = radeon_crtc_cursor_set, | ||
| 170 | .cursor_move = radeon_crtc_cursor_move, | ||
| 171 | .gamma_set = radeon_crtc_gamma_set, | ||
| 172 | .set_config = drm_crtc_helper_set_config, | ||
| 173 | .destroy = radeon_crtc_destroy, | ||
| 174 | }; | ||
| 175 | |||
| 176 | static void radeon_crtc_init(struct drm_device *dev, int index) | ||
| 177 | { | ||
| 178 | struct radeon_device *rdev = dev->dev_private; | ||
| 179 | struct radeon_crtc *radeon_crtc; | ||
| 180 | int i; | ||
| 181 | |||
| 182 | radeon_crtc = kzalloc(sizeof(struct radeon_crtc) + (RADEONFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL); | ||
| 183 | if (radeon_crtc == NULL) | ||
| 184 | return; | ||
| 185 | |||
| 186 | drm_crtc_init(dev, &radeon_crtc->base, &radeon_crtc_funcs); | ||
| 187 | |||
| 188 | drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); | ||
| 189 | radeon_crtc->crtc_id = index; | ||
| 190 | |||
| 191 | radeon_crtc->mode_set.crtc = &radeon_crtc->base; | ||
| 192 | radeon_crtc->mode_set.connectors = (struct drm_connector **)(radeon_crtc + 1); | ||
| 193 | radeon_crtc->mode_set.num_connectors = 0; | ||
| 194 | |||
| 195 | for (i = 0; i < 256; i++) { | ||
| 196 | radeon_crtc->lut_r[i] = i << 2; | ||
| 197 | radeon_crtc->lut_g[i] = i << 2; | ||
| 198 | radeon_crtc->lut_b[i] = i << 2; | ||
| 199 | } | ||
| 200 | |||
| 201 | if (rdev->is_atom_bios && (ASIC_IS_AVIVO(rdev) || radeon_r4xx_atom)) | ||
| 202 | radeon_atombios_init_crtc(dev, radeon_crtc); | ||
| 203 | else | ||
| 204 | radeon_legacy_init_crtc(dev, radeon_crtc); | ||
| 205 | } | ||
| 206 | |||
| 207 | static const char *encoder_names[34] = { | ||
| 208 | "NONE", | ||
| 209 | "INTERNAL_LVDS", | ||
| 210 | "INTERNAL_TMDS1", | ||
| 211 | "INTERNAL_TMDS2", | ||
| 212 | "INTERNAL_DAC1", | ||
| 213 | "INTERNAL_DAC2", | ||
| 214 | "INTERNAL_SDVOA", | ||
| 215 | "INTERNAL_SDVOB", | ||
| 216 | "SI170B", | ||
| 217 | "CH7303", | ||
| 218 | "CH7301", | ||
| 219 | "INTERNAL_DVO1", | ||
| 220 | "EXTERNAL_SDVOA", | ||
| 221 | "EXTERNAL_SDVOB", | ||
| 222 | "TITFP513", | ||
| 223 | "INTERNAL_LVTM1", | ||
| 224 | "VT1623", | ||
| 225 | "HDMI_SI1930", | ||
| 226 | "HDMI_INTERNAL", | ||
| 227 | "INTERNAL_KLDSCP_TMDS1", | ||
| 228 | "INTERNAL_KLDSCP_DVO1", | ||
| 229 | "INTERNAL_KLDSCP_DAC1", | ||
| 230 | "INTERNAL_KLDSCP_DAC2", | ||
| 231 | "SI178", | ||
| 232 | "MVPU_FPGA", | ||
| 233 | "INTERNAL_DDI", | ||
| 234 | "VT1625", | ||
| 235 | "HDMI_SI1932", | ||
| 236 | "DP_AN9801", | ||
| 237 | "DP_DP501", | ||
| 238 | "INTERNAL_UNIPHY", | ||
| 239 | "INTERNAL_KLDSCP_LVTMA", | ||
| 240 | "INTERNAL_UNIPHY1", | ||
| 241 | "INTERNAL_UNIPHY2", | ||
| 242 | }; | ||
| 243 | |||
| 244 | static const char *connector_names[13] = { | ||
| 245 | "Unknown", | ||
| 246 | "VGA", | ||
| 247 | "DVI-I", | ||
| 248 | "DVI-D", | ||
| 249 | "DVI-A", | ||
| 250 | "Composite", | ||
| 251 | "S-video", | ||
| 252 | "LVDS", | ||
| 253 | "Component", | ||
| 254 | "DIN", | ||
| 255 | "DisplayPort", | ||
| 256 | "HDMI-A", | ||
| 257 | "HDMI-B", | ||
| 258 | }; | ||
| 259 | |||
| 260 | static void radeon_print_display_setup(struct drm_device *dev) | ||
| 261 | { | ||
| 262 | struct drm_connector *connector; | ||
| 263 | struct radeon_connector *radeon_connector; | ||
| 264 | struct drm_encoder *encoder; | ||
| 265 | struct radeon_encoder *radeon_encoder; | ||
| 266 | uint32_t devices; | ||
| 267 | int i = 0; | ||
| 268 | |||
| 269 | DRM_INFO("Radeon Display Connectors\n"); | ||
| 270 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 271 | radeon_connector = to_radeon_connector(connector); | ||
| 272 | DRM_INFO("Connector %d:\n", i); | ||
| 273 | DRM_INFO(" %s\n", connector_names[connector->connector_type]); | ||
| 274 | if (radeon_connector->ddc_bus) | ||
| 275 | DRM_INFO(" DDC: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", | ||
| 276 | radeon_connector->ddc_bus->rec.mask_clk_reg, | ||
| 277 | radeon_connector->ddc_bus->rec.mask_data_reg, | ||
| 278 | radeon_connector->ddc_bus->rec.a_clk_reg, | ||
| 279 | radeon_connector->ddc_bus->rec.a_data_reg, | ||
| 280 | radeon_connector->ddc_bus->rec.put_clk_reg, | ||
| 281 | radeon_connector->ddc_bus->rec.put_data_reg, | ||
| 282 | radeon_connector->ddc_bus->rec.get_clk_reg, | ||
| 283 | radeon_connector->ddc_bus->rec.get_data_reg); | ||
| 284 | DRM_INFO(" Encoders:\n"); | ||
| 285 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 286 | radeon_encoder = to_radeon_encoder(encoder); | ||
| 287 | devices = radeon_encoder->devices & radeon_connector->devices; | ||
| 288 | if (devices) { | ||
| 289 | if (devices & ATOM_DEVICE_CRT1_SUPPORT) | ||
| 290 | DRM_INFO(" CRT1: %s\n", encoder_names[radeon_encoder->encoder_id]); | ||
| 291 | if (devices & ATOM_DEVICE_CRT2_SUPPORT) | ||
| 292 | DRM_INFO(" CRT2: %s\n", encoder_names[radeon_encoder->encoder_id]); | ||
| 293 | if (devices & ATOM_DEVICE_LCD1_SUPPORT) | ||
| 294 | DRM_INFO(" LCD1: %s\n", encoder_names[radeon_encoder->encoder_id]); | ||
| 295 | if (devices & ATOM_DEVICE_DFP1_SUPPORT) | ||
| 296 | DRM_INFO(" DFP1: %s\n", encoder_names[radeon_encoder->encoder_id]); | ||
| 297 | if (devices & ATOM_DEVICE_DFP2_SUPPORT) | ||
| 298 | DRM_INFO(" DFP2: %s\n", encoder_names[radeon_encoder->encoder_id]); | ||
| 299 | if (devices & ATOM_DEVICE_DFP3_SUPPORT) | ||
| 300 | DRM_INFO(" DFP3: %s\n", encoder_names[radeon_encoder->encoder_id]); | ||
| 301 | if (devices & ATOM_DEVICE_DFP4_SUPPORT) | ||
| 302 | DRM_INFO(" DFP4: %s\n", encoder_names[radeon_encoder->encoder_id]); | ||
| 303 | if (devices & ATOM_DEVICE_DFP5_SUPPORT) | ||
| 304 | DRM_INFO(" DFP5: %s\n", encoder_names[radeon_encoder->encoder_id]); | ||
| 305 | if (devices & ATOM_DEVICE_TV1_SUPPORT) | ||
| 306 | DRM_INFO(" TV1: %s\n", encoder_names[radeon_encoder->encoder_id]); | ||
| 307 | if (devices & ATOM_DEVICE_CV_SUPPORT) | ||
| 308 | DRM_INFO(" CV: %s\n", encoder_names[radeon_encoder->encoder_id]); | ||
| 309 | } | ||
| 310 | } | ||
| 311 | i++; | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | bool radeon_setup_enc_conn(struct drm_device *dev) | ||
| 316 | { | ||
| 317 | struct radeon_device *rdev = dev->dev_private; | ||
| 318 | struct drm_connector *drm_connector; | ||
| 319 | bool ret = false; | ||
| 320 | |||
| 321 | if (rdev->bios) { | ||
| 322 | if (rdev->is_atom_bios) { | ||
| 323 | if (rdev->family >= CHIP_R600) | ||
| 324 | ret = radeon_get_atom_connector_info_from_object_table(dev); | ||
| 325 | else | ||
| 326 | ret = radeon_get_atom_connector_info_from_supported_devices_table(dev); | ||
| 327 | } else | ||
| 328 | ret = radeon_get_legacy_connector_info_from_bios(dev); | ||
| 329 | } else { | ||
| 330 | if (!ASIC_IS_AVIVO(rdev)) | ||
| 331 | ret = radeon_get_legacy_connector_info_from_table(dev); | ||
| 332 | } | ||
| 333 | if (ret) { | ||
| 334 | radeon_print_display_setup(dev); | ||
| 335 | list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) | ||
| 336 | radeon_ddc_dump(drm_connector); | ||
| 337 | } | ||
| 338 | |||
| 339 | return ret; | ||
| 340 | } | ||
| 341 | |||
| 342 | int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) | ||
| 343 | { | ||
| 344 | struct edid *edid; | ||
| 345 | int ret = 0; | ||
| 346 | |||
| 347 | if (!radeon_connector->ddc_bus) | ||
| 348 | return -1; | ||
| 349 | radeon_i2c_do_lock(radeon_connector, 1); | ||
| 350 | edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); | ||
| 351 | radeon_i2c_do_lock(radeon_connector, 0); | ||
| 352 | if (edid) { | ||
| 353 | /* update digital bits here */ | ||
| 354 | if (edid->digital) | ||
| 355 | radeon_connector->use_digital = 1; | ||
| 356 | else | ||
| 357 | radeon_connector->use_digital = 0; | ||
| 358 | drm_mode_connector_update_edid_property(&radeon_connector->base, edid); | ||
| 359 | ret = drm_add_edid_modes(&radeon_connector->base, edid); | ||
| 360 | kfree(edid); | ||
| 361 | return ret; | ||
| 362 | } | ||
| 363 | drm_mode_connector_update_edid_property(&radeon_connector->base, NULL); | ||
| 364 | return -1; | ||
| 365 | } | ||
| 366 | |||
| 367 | static int radeon_ddc_dump(struct drm_connector *connector) | ||
| 368 | { | ||
| 369 | struct edid *edid; | ||
| 370 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 371 | int ret = 0; | ||
| 372 | |||
| 373 | if (!radeon_connector->ddc_bus) | ||
| 374 | return -1; | ||
| 375 | radeon_i2c_do_lock(radeon_connector, 1); | ||
| 376 | edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter); | ||
| 377 | radeon_i2c_do_lock(radeon_connector, 0); | ||
| 378 | if (edid) { | ||
| 379 | kfree(edid); | ||
| 380 | } | ||
| 381 | return ret; | ||
| 382 | } | ||
| 383 | |||
| 384 | static inline uint32_t radeon_div(uint64_t n, uint32_t d) | ||
| 385 | { | ||
| 386 | uint64_t mod; | ||
| 387 | |||
| 388 | n += d / 2; | ||
| 389 | |||
| 390 | mod = do_div(n, d); | ||
| 391 | return n; | ||
| 392 | } | ||
| 393 | |||
| 394 | void radeon_compute_pll(struct radeon_pll *pll, | ||
| 395 | uint64_t freq, | ||
| 396 | uint32_t *dot_clock_p, | ||
| 397 | uint32_t *fb_div_p, | ||
| 398 | uint32_t *frac_fb_div_p, | ||
| 399 | uint32_t *ref_div_p, | ||
| 400 | uint32_t *post_div_p, | ||
| 401 | int flags) | ||
| 402 | { | ||
| 403 | uint32_t min_ref_div = pll->min_ref_div; | ||
| 404 | uint32_t max_ref_div = pll->max_ref_div; | ||
| 405 | uint32_t min_fractional_feed_div = 0; | ||
| 406 | uint32_t max_fractional_feed_div = 0; | ||
| 407 | uint32_t best_vco = pll->best_vco; | ||
| 408 | uint32_t best_post_div = 1; | ||
| 409 | uint32_t best_ref_div = 1; | ||
| 410 | uint32_t best_feedback_div = 1; | ||
| 411 | uint32_t best_frac_feedback_div = 0; | ||
| 412 | uint32_t best_freq = -1; | ||
| 413 | uint32_t best_error = 0xffffffff; | ||
| 414 | uint32_t best_vco_diff = 1; | ||
| 415 | uint32_t post_div; | ||
| 416 | |||
| 417 | DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div); | ||
| 418 | freq = freq * 1000; | ||
| 419 | |||
| 420 | if (flags & RADEON_PLL_USE_REF_DIV) | ||
| 421 | min_ref_div = max_ref_div = pll->reference_div; | ||
| 422 | else { | ||
| 423 | while (min_ref_div < max_ref_div-1) { | ||
| 424 | uint32_t mid = (min_ref_div + max_ref_div) / 2; | ||
| 425 | uint32_t pll_in = pll->reference_freq / mid; | ||
| 426 | if (pll_in < pll->pll_in_min) | ||
| 427 | max_ref_div = mid; | ||
| 428 | else if (pll_in > pll->pll_in_max) | ||
| 429 | min_ref_div = mid; | ||
| 430 | else | ||
| 431 | break; | ||
| 432 | } | ||
| 433 | } | ||
| 434 | |||
| 435 | if (flags & RADEON_PLL_USE_FRAC_FB_DIV) { | ||
| 436 | min_fractional_feed_div = pll->min_frac_feedback_div; | ||
| 437 | max_fractional_feed_div = pll->max_frac_feedback_div; | ||
| 438 | } | ||
| 439 | |||
| 440 | for (post_div = pll->min_post_div; post_div <= pll->max_post_div; ++post_div) { | ||
| 441 | uint32_t ref_div; | ||
| 442 | |||
| 443 | if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1)) | ||
| 444 | continue; | ||
| 445 | |||
| 446 | /* legacy radeons only have a few post_divs */ | ||
| 447 | if (flags & RADEON_PLL_LEGACY) { | ||
| 448 | if ((post_div == 5) || | ||
| 449 | (post_div == 7) || | ||
| 450 | (post_div == 9) || | ||
| 451 | (post_div == 10) || | ||
| 452 | (post_div == 11) || | ||
| 453 | (post_div == 13) || | ||
| 454 | (post_div == 14) || | ||
| 455 | (post_div == 15)) | ||
| 456 | continue; | ||
| 457 | } | ||
| 458 | |||
| 459 | for (ref_div = min_ref_div; ref_div <= max_ref_div; ++ref_div) { | ||
| 460 | uint32_t feedback_div, current_freq = 0, error, vco_diff; | ||
| 461 | uint32_t pll_in = pll->reference_freq / ref_div; | ||
| 462 | uint32_t min_feed_div = pll->min_feedback_div; | ||
| 463 | uint32_t max_feed_div = pll->max_feedback_div + 1; | ||
| 464 | |||
| 465 | if (pll_in < pll->pll_in_min || pll_in > pll->pll_in_max) | ||
| 466 | continue; | ||
| 467 | |||
| 468 | while (min_feed_div < max_feed_div) { | ||
| 469 | uint32_t vco; | ||
| 470 | uint32_t min_frac_feed_div = min_fractional_feed_div; | ||
| 471 | uint32_t max_frac_feed_div = max_fractional_feed_div + 1; | ||
| 472 | uint32_t frac_feedback_div; | ||
| 473 | uint64_t tmp; | ||
| 474 | |||
| 475 | feedback_div = (min_feed_div + max_feed_div) / 2; | ||
| 476 | |||
| 477 | tmp = (uint64_t)pll->reference_freq * feedback_div; | ||
| 478 | vco = radeon_div(tmp, ref_div); | ||
| 479 | |||
| 480 | if (vco < pll->pll_out_min) { | ||
| 481 | min_feed_div = feedback_div + 1; | ||
| 482 | continue; | ||
| 483 | } else if (vco > pll->pll_out_max) { | ||
| 484 | max_feed_div = feedback_div; | ||
| 485 | continue; | ||
| 486 | } | ||
| 487 | |||
| 488 | while (min_frac_feed_div < max_frac_feed_div) { | ||
| 489 | frac_feedback_div = (min_frac_feed_div + max_frac_feed_div) / 2; | ||
| 490 | tmp = (uint64_t)pll->reference_freq * 10000 * feedback_div; | ||
| 491 | tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div; | ||
| 492 | current_freq = radeon_div(tmp, ref_div * post_div); | ||
| 493 | |||
| 494 | error = abs(current_freq - freq); | ||
| 495 | vco_diff = abs(vco - best_vco); | ||
| 496 | |||
| 497 | if ((best_vco == 0 && error < best_error) || | ||
| 498 | (best_vco != 0 && | ||
| 499 | (error < best_error - 100 || | ||
| 500 | (abs(error - best_error) < 100 && vco_diff < best_vco_diff)))) { | ||
| 501 | best_post_div = post_div; | ||
| 502 | best_ref_div = ref_div; | ||
| 503 | best_feedback_div = feedback_div; | ||
| 504 | best_frac_feedback_div = frac_feedback_div; | ||
| 505 | best_freq = current_freq; | ||
| 506 | best_error = error; | ||
| 507 | best_vco_diff = vco_diff; | ||
| 508 | } else if (current_freq == freq) { | ||
| 509 | if (best_freq == -1) { | ||
| 510 | best_post_div = post_div; | ||
| 511 | best_ref_div = ref_div; | ||
| 512 | best_feedback_div = feedback_div; | ||
| 513 | best_frac_feedback_div = frac_feedback_div; | ||
| 514 | best_freq = current_freq; | ||
| 515 | best_error = error; | ||
| 516 | best_vco_diff = vco_diff; | ||
| 517 | } else if (((flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) || | ||
| 518 | ((flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) || | ||
| 519 | ((flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) || | ||
| 520 | ((flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) || | ||
| 521 | ((flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) || | ||
| 522 | ((flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) { | ||
| 523 | best_post_div = post_div; | ||
| 524 | best_ref_div = ref_div; | ||
| 525 | best_feedback_div = feedback_div; | ||
| 526 | best_frac_feedback_div = frac_feedback_div; | ||
| 527 | best_freq = current_freq; | ||
| 528 | best_error = error; | ||
| 529 | best_vco_diff = vco_diff; | ||
| 530 | } | ||
| 531 | } | ||
| 532 | if (current_freq < freq) | ||
| 533 | min_frac_feed_div = frac_feedback_div + 1; | ||
| 534 | else | ||
| 535 | max_frac_feed_div = frac_feedback_div; | ||
| 536 | } | ||
| 537 | if (current_freq < freq) | ||
| 538 | min_feed_div = feedback_div + 1; | ||
| 539 | else | ||
| 540 | max_feed_div = feedback_div; | ||
| 541 | } | ||
| 542 | } | ||
| 543 | } | ||
| 544 | |||
| 545 | *dot_clock_p = best_freq / 10000; | ||
| 546 | *fb_div_p = best_feedback_div; | ||
| 547 | *frac_fb_div_p = best_frac_feedback_div; | ||
| 548 | *ref_div_p = best_ref_div; | ||
| 549 | *post_div_p = best_post_div; | ||
| 550 | } | ||
| 551 | |||
| 552 | static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) | ||
| 553 | { | ||
| 554 | struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); | ||
| 555 | struct drm_device *dev = fb->dev; | ||
| 556 | |||
| 557 | if (fb->fbdev) | ||
| 558 | radeonfb_remove(dev, fb); | ||
| 559 | |||
| 560 | if (radeon_fb->obj) { | ||
| 561 | radeon_gem_object_unpin(radeon_fb->obj); | ||
| 562 | mutex_lock(&dev->struct_mutex); | ||
| 563 | drm_gem_object_unreference(radeon_fb->obj); | ||
| 564 | mutex_unlock(&dev->struct_mutex); | ||
| 565 | } | ||
| 566 | drm_framebuffer_cleanup(fb); | ||
| 567 | kfree(radeon_fb); | ||
| 568 | } | ||
| 569 | |||
| 570 | static int radeon_user_framebuffer_create_handle(struct drm_framebuffer *fb, | ||
| 571 | struct drm_file *file_priv, | ||
| 572 | unsigned int *handle) | ||
| 573 | { | ||
| 574 | struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb); | ||
| 575 | |||
| 576 | return drm_gem_handle_create(file_priv, radeon_fb->obj, handle); | ||
| 577 | } | ||
| 578 | |||
| 579 | static const struct drm_framebuffer_funcs radeon_fb_funcs = { | ||
| 580 | .destroy = radeon_user_framebuffer_destroy, | ||
| 581 | .create_handle = radeon_user_framebuffer_create_handle, | ||
| 582 | }; | ||
| 583 | |||
| 584 | struct drm_framebuffer * | ||
| 585 | radeon_framebuffer_create(struct drm_device *dev, | ||
| 586 | struct drm_mode_fb_cmd *mode_cmd, | ||
| 587 | struct drm_gem_object *obj) | ||
| 588 | { | ||
| 589 | struct radeon_framebuffer *radeon_fb; | ||
| 590 | |||
| 591 | radeon_fb = kzalloc(sizeof(*radeon_fb), GFP_KERNEL); | ||
| 592 | if (radeon_fb == NULL) { | ||
| 593 | return NULL; | ||
| 594 | } | ||
| 595 | drm_framebuffer_init(dev, &radeon_fb->base, &radeon_fb_funcs); | ||
| 596 | drm_helper_mode_fill_fb_struct(&radeon_fb->base, mode_cmd); | ||
| 597 | radeon_fb->obj = obj; | ||
| 598 | return &radeon_fb->base; | ||
| 599 | } | ||
| 600 | |||
| 601 | static struct drm_framebuffer * | ||
| 602 | radeon_user_framebuffer_create(struct drm_device *dev, | ||
| 603 | struct drm_file *file_priv, | ||
| 604 | struct drm_mode_fb_cmd *mode_cmd) | ||
| 605 | { | ||
| 606 | struct drm_gem_object *obj; | ||
| 607 | |||
| 608 | obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); | ||
| 609 | |||
| 610 | return radeon_framebuffer_create(dev, mode_cmd, obj); | ||
| 611 | } | ||
| 612 | |||
| 613 | static const struct drm_mode_config_funcs radeon_mode_funcs = { | ||
| 614 | .fb_create = radeon_user_framebuffer_create, | ||
| 615 | .fb_changed = radeonfb_probe, | ||
| 616 | }; | ||
| 617 | |||
| 618 | int radeon_modeset_init(struct radeon_device *rdev) | ||
| 619 | { | ||
| 620 | int num_crtc = 2, i; | ||
| 621 | int ret; | ||
| 622 | |||
| 623 | drm_mode_config_init(rdev->ddev); | ||
| 624 | rdev->mode_info.mode_config_initialized = true; | ||
| 625 | |||
| 626 | rdev->ddev->mode_config.funcs = (void *)&radeon_mode_funcs; | ||
| 627 | |||
| 628 | if (ASIC_IS_AVIVO(rdev)) { | ||
| 629 | rdev->ddev->mode_config.max_width = 8192; | ||
| 630 | rdev->ddev->mode_config.max_height = 8192; | ||
| 631 | } else { | ||
| 632 | rdev->ddev->mode_config.max_width = 4096; | ||
| 633 | rdev->ddev->mode_config.max_height = 4096; | ||
| 634 | } | ||
| 635 | |||
| 636 | rdev->ddev->mode_config.fb_base = rdev->mc.aper_base; | ||
| 637 | |||
| 638 | /* allocate crtcs - TODO single crtc */ | ||
| 639 | for (i = 0; i < num_crtc; i++) { | ||
| 640 | radeon_crtc_init(rdev->ddev, i); | ||
| 641 | } | ||
| 642 | |||
| 643 | /* okay we should have all the bios connectors */ | ||
| 644 | ret = radeon_setup_enc_conn(rdev->ddev); | ||
| 645 | if (!ret) { | ||
| 646 | return ret; | ||
| 647 | } | ||
| 648 | drm_helper_initial_config(rdev->ddev); | ||
| 649 | return 0; | ||
| 650 | } | ||
| 651 | |||
| 652 | void radeon_modeset_fini(struct radeon_device *rdev) | ||
| 653 | { | ||
| 654 | if (rdev->mode_info.mode_config_initialized) { | ||
| 655 | drm_mode_config_cleanup(rdev->ddev); | ||
| 656 | rdev->mode_info.mode_config_initialized = false; | ||
| 657 | } | ||
| 658 | } | ||
| 659 | |||
| 660 | void radeon_init_disp_bandwidth(struct drm_device *dev) | ||
| 661 | { | ||
| 662 | struct radeon_device *rdev = dev->dev_private; | ||
| 663 | struct drm_display_mode *modes[2]; | ||
| 664 | int pixel_bytes[2]; | ||
| 665 | struct drm_crtc *crtc; | ||
| 666 | |||
| 667 | pixel_bytes[0] = pixel_bytes[1] = 0; | ||
| 668 | modes[0] = modes[1] = NULL; | ||
| 669 | |||
| 670 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
| 671 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 672 | |||
| 673 | if (crtc->enabled && crtc->fb) { | ||
| 674 | modes[radeon_crtc->crtc_id] = &crtc->mode; | ||
| 675 | pixel_bytes[radeon_crtc->crtc_id] = crtc->fb->bits_per_pixel / 8; | ||
| 676 | } | ||
| 677 | } | ||
| 678 | |||
| 679 | if (ASIC_IS_AVIVO(rdev)) { | ||
| 680 | radeon_init_disp_bw_avivo(dev, | ||
| 681 | modes[0], | ||
| 682 | pixel_bytes[0], | ||
| 683 | modes[1], | ||
| 684 | pixel_bytes[1]); | ||
| 685 | } else { | ||
| 686 | radeon_init_disp_bw_legacy(dev, | ||
| 687 | modes[0], | ||
| 688 | pixel_bytes[0], | ||
| 689 | modes[1], | ||
| 690 | pixel_bytes[1]); | ||
| 691 | } | ||
| 692 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 13a60f4d4227..c815a2cbf7b3 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
| @@ -35,12 +35,92 @@ | |||
| 35 | #include "radeon_drv.h" | 35 | #include "radeon_drv.h" |
| 36 | 36 | ||
| 37 | #include "drm_pciids.h" | 37 | #include "drm_pciids.h" |
| 38 | #include <linux/console.h> | ||
| 39 | |||
| 40 | |||
| 41 | #if defined(CONFIG_DRM_RADEON_KMS) | ||
| 42 | /* | ||
| 43 | * KMS wrapper. | ||
| 44 | */ | ||
| 45 | #define KMS_DRIVER_MAJOR 2 | ||
| 46 | #define KMS_DRIVER_MINOR 0 | ||
| 47 | #define KMS_DRIVER_PATCHLEVEL 0 | ||
| 48 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); | ||
| 49 | int radeon_driver_unload_kms(struct drm_device *dev); | ||
| 50 | int radeon_driver_firstopen_kms(struct drm_device *dev); | ||
| 51 | void radeon_driver_lastclose_kms(struct drm_device *dev); | ||
| 52 | int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv); | ||
| 53 | void radeon_driver_postclose_kms(struct drm_device *dev, | ||
| 54 | struct drm_file *file_priv); | ||
| 55 | void radeon_driver_preclose_kms(struct drm_device *dev, | ||
| 56 | struct drm_file *file_priv); | ||
| 57 | int radeon_suspend_kms(struct drm_device *dev, pm_message_t state); | ||
| 58 | int radeon_resume_kms(struct drm_device *dev); | ||
| 59 | u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc); | ||
| 60 | int radeon_enable_vblank_kms(struct drm_device *dev, int crtc); | ||
| 61 | void radeon_disable_vblank_kms(struct drm_device *dev, int crtc); | ||
| 62 | void radeon_driver_irq_preinstall_kms(struct drm_device *dev); | ||
| 63 | int radeon_driver_irq_postinstall_kms(struct drm_device *dev); | ||
| 64 | void radeon_driver_irq_uninstall_kms(struct drm_device *dev); | ||
| 65 | irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS); | ||
| 66 | int radeon_master_create_kms(struct drm_device *dev, struct drm_master *master); | ||
| 67 | void radeon_master_destroy_kms(struct drm_device *dev, | ||
| 68 | struct drm_master *master); | ||
| 69 | int radeon_dma_ioctl_kms(struct drm_device *dev, void *data, | ||
| 70 | struct drm_file *file_priv); | ||
| 71 | int radeon_gem_object_init(struct drm_gem_object *obj); | ||
| 72 | void radeon_gem_object_free(struct drm_gem_object *obj); | ||
| 73 | extern struct drm_ioctl_desc radeon_ioctls_kms[]; | ||
| 74 | extern int radeon_max_kms_ioctl; | ||
| 75 | int radeon_mmap(struct file *filp, struct vm_area_struct *vma); | ||
| 76 | #if defined(CONFIG_DEBUG_FS) | ||
| 77 | int radeon_debugfs_init(struct drm_minor *minor); | ||
| 78 | void radeon_debugfs_cleanup(struct drm_minor *minor); | ||
| 79 | #endif | ||
| 80 | #endif | ||
| 81 | |||
| 38 | 82 | ||
| 39 | int radeon_no_wb; | 83 | int radeon_no_wb; |
| 84 | #if defined(CONFIG_DRM_RADEON_KMS) | ||
| 85 | int radeon_modeset = -1; | ||
| 86 | int radeon_dynclks = -1; | ||
| 87 | int radeon_r4xx_atom = 0; | ||
| 88 | int radeon_agpmode = 0; | ||
| 89 | int radeon_vram_limit = 0; | ||
| 90 | int radeon_gart_size = 512; /* default gart size */ | ||
| 91 | int radeon_benchmarking = 0; | ||
| 92 | int radeon_connector_table = 0; | ||
| 93 | #endif | ||
| 40 | 94 | ||
| 41 | MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); | 95 | MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers"); |
| 42 | module_param_named(no_wb, radeon_no_wb, int, 0444); | 96 | module_param_named(no_wb, radeon_no_wb, int, 0444); |
| 43 | 97 | ||
| 98 | #if defined(CONFIG_DRM_RADEON_KMS) | ||
| 99 | MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); | ||
| 100 | module_param_named(modeset, radeon_modeset, int, 0400); | ||
| 101 | |||
| 102 | MODULE_PARM_DESC(dynclks, "Disable/Enable dynamic clocks"); | ||
| 103 | module_param_named(dynclks, radeon_dynclks, int, 0444); | ||
| 104 | |||
| 105 | MODULE_PARM_DESC(r4xx_atom, "Enable ATOMBIOS modesetting for R4xx"); | ||
| 106 | module_param_named(r4xx_atom, radeon_r4xx_atom, int, 0444); | ||
| 107 | |||
| 108 | MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing"); | ||
| 109 | module_param_named(vramlimit, radeon_vram_limit, int, 0600); | ||
| 110 | |||
| 111 | MODULE_PARM_DESC(agpmode, "AGP Mode (-1 == PCI)"); | ||
| 112 | module_param_named(agpmode, radeon_agpmode, int, 0444); | ||
| 113 | |||
| 114 | MODULE_PARM_DESC(gartsize, "Size of PCIE/IGP gart to setup in megabytes (32,64, etc)\n"); | ||
| 115 | module_param_named(gartsize, radeon_gart_size, int, 0600); | ||
| 116 | |||
| 117 | MODULE_PARM_DESC(benchmark, "Run benchmark"); | ||
| 118 | module_param_named(benchmark, radeon_benchmarking, int, 0444); | ||
| 119 | |||
| 120 | MODULE_PARM_DESC(connector_table, "Force connector table"); | ||
| 121 | module_param_named(connector_table, radeon_connector_table, int, 0444); | ||
| 122 | #endif | ||
| 123 | |||
| 44 | static int radeon_suspend(struct drm_device *dev, pm_message_t state) | 124 | static int radeon_suspend(struct drm_device *dev, pm_message_t state) |
| 45 | { | 125 | { |
| 46 | drm_radeon_private_t *dev_priv = dev->dev_private; | 126 | drm_radeon_private_t *dev_priv = dev->dev_private; |
| @@ -73,7 +153,11 @@ static struct pci_device_id pciidlist[] = { | |||
| 73 | radeon_PCI_IDS | 153 | radeon_PCI_IDS |
| 74 | }; | 154 | }; |
| 75 | 155 | ||
| 76 | static struct drm_driver driver = { | 156 | #if defined(CONFIG_DRM_RADEON_KMS) |
| 157 | MODULE_DEVICE_TABLE(pci, pciidlist); | ||
| 158 | #endif | ||
| 159 | |||
| 160 | static struct drm_driver driver_old = { | ||
| 77 | .driver_features = | 161 | .driver_features = |
| 78 | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | | 162 | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | |
| 79 | DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED, | 163 | DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED, |
| @@ -127,18 +211,141 @@ static struct drm_driver driver = { | |||
| 127 | .patchlevel = DRIVER_PATCHLEVEL, | 211 | .patchlevel = DRIVER_PATCHLEVEL, |
| 128 | }; | 212 | }; |
| 129 | 213 | ||
| 214 | #if defined(CONFIG_DRM_RADEON_KMS) | ||
| 215 | static struct drm_driver kms_driver; | ||
| 216 | |||
| 217 | static int __devinit | ||
| 218 | radeon_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | ||
| 219 | { | ||
| 220 | return drm_get_dev(pdev, ent, &kms_driver); | ||
| 221 | } | ||
| 222 | |||
| 223 | static void | ||
| 224 | radeon_pci_remove(struct pci_dev *pdev) | ||
| 225 | { | ||
| 226 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
| 227 | |||
| 228 | drm_put_dev(dev); | ||
| 229 | } | ||
| 230 | |||
| 231 | static int | ||
| 232 | radeon_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
| 233 | { | ||
| 234 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
| 235 | return radeon_suspend_kms(dev, state); | ||
| 236 | } | ||
| 237 | |||
| 238 | static int | ||
| 239 | radeon_pci_resume(struct pci_dev *pdev) | ||
| 240 | { | ||
| 241 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
| 242 | return radeon_resume_kms(dev); | ||
| 243 | } | ||
| 244 | |||
| 245 | static struct drm_driver kms_driver = { | ||
| 246 | .driver_features = | ||
| 247 | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG | | ||
| 248 | DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | DRIVER_GEM, | ||
| 249 | .dev_priv_size = 0, | ||
| 250 | .load = radeon_driver_load_kms, | ||
| 251 | .firstopen = radeon_driver_firstopen_kms, | ||
| 252 | .open = radeon_driver_open_kms, | ||
| 253 | .preclose = radeon_driver_preclose_kms, | ||
| 254 | .postclose = radeon_driver_postclose_kms, | ||
| 255 | .lastclose = radeon_driver_lastclose_kms, | ||
| 256 | .unload = radeon_driver_unload_kms, | ||
| 257 | .suspend = radeon_suspend_kms, | ||
| 258 | .resume = radeon_resume_kms, | ||
| 259 | .get_vblank_counter = radeon_get_vblank_counter_kms, | ||
| 260 | .enable_vblank = radeon_enable_vblank_kms, | ||
| 261 | .disable_vblank = radeon_disable_vblank_kms, | ||
| 262 | .master_create = radeon_master_create_kms, | ||
| 263 | .master_destroy = radeon_master_destroy_kms, | ||
| 264 | #if defined(CONFIG_DEBUG_FS) | ||
| 265 | .debugfs_init = radeon_debugfs_init, | ||
| 266 | .debugfs_cleanup = radeon_debugfs_cleanup, | ||
| 267 | #endif | ||
| 268 | .irq_preinstall = radeon_driver_irq_preinstall_kms, | ||
| 269 | .irq_postinstall = radeon_driver_irq_postinstall_kms, | ||
| 270 | .irq_uninstall = radeon_driver_irq_uninstall_kms, | ||
| 271 | .irq_handler = radeon_driver_irq_handler_kms, | ||
| 272 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
| 273 | .get_map_ofs = drm_core_get_map_ofs, | ||
| 274 | .get_reg_ofs = drm_core_get_reg_ofs, | ||
| 275 | .ioctls = radeon_ioctls_kms, | ||
| 276 | .gem_init_object = radeon_gem_object_init, | ||
| 277 | .gem_free_object = radeon_gem_object_free, | ||
| 278 | .dma_ioctl = radeon_dma_ioctl_kms, | ||
| 279 | .fops = { | ||
| 280 | .owner = THIS_MODULE, | ||
| 281 | .open = drm_open, | ||
| 282 | .release = drm_release, | ||
| 283 | .ioctl = drm_ioctl, | ||
| 284 | .mmap = radeon_mmap, | ||
| 285 | .poll = drm_poll, | ||
| 286 | .fasync = drm_fasync, | ||
| 287 | #ifdef CONFIG_COMPAT | ||
| 288 | .compat_ioctl = NULL, | ||
| 289 | #endif | ||
| 290 | }, | ||
| 291 | |||
| 292 | .pci_driver = { | ||
| 293 | .name = DRIVER_NAME, | ||
| 294 | .id_table = pciidlist, | ||
| 295 | .probe = radeon_pci_probe, | ||
| 296 | .remove = radeon_pci_remove, | ||
| 297 | .suspend = radeon_pci_suspend, | ||
| 298 | .resume = radeon_pci_resume, | ||
| 299 | }, | ||
| 300 | |||
| 301 | .name = DRIVER_NAME, | ||
| 302 | .desc = DRIVER_DESC, | ||
| 303 | .date = DRIVER_DATE, | ||
| 304 | .major = KMS_DRIVER_MAJOR, | ||
| 305 | .minor = KMS_DRIVER_MINOR, | ||
| 306 | .patchlevel = KMS_DRIVER_PATCHLEVEL, | ||
| 307 | }; | ||
| 308 | #endif | ||
| 309 | |||
| 310 | static struct drm_driver *driver; | ||
| 311 | |||
| 130 | static int __init radeon_init(void) | 312 | static int __init radeon_init(void) |
| 131 | { | 313 | { |
| 132 | driver.num_ioctls = radeon_max_ioctl; | 314 | driver = &driver_old; |
| 133 | return drm_init(&driver); | 315 | driver->num_ioctls = radeon_max_ioctl; |
| 316 | #if defined(CONFIG_DRM_RADEON_KMS) && defined(CONFIG_X86) | ||
| 317 | /* if enabled by default */ | ||
| 318 | if (radeon_modeset == -1) { | ||
| 319 | DRM_INFO("radeon default to kernel modesetting.\n"); | ||
| 320 | radeon_modeset = 1; | ||
| 321 | } | ||
| 322 | if (radeon_modeset == 1) { | ||
| 323 | DRM_INFO("radeon kernel modesetting enabled.\n"); | ||
| 324 | driver = &kms_driver; | ||
| 325 | driver->driver_features |= DRIVER_MODESET; | ||
| 326 | driver->num_ioctls = radeon_max_kms_ioctl; | ||
| 327 | } | ||
| 328 | |||
| 329 | /* if the vga console setting is enabled still | ||
| 330 | * let modprobe override it */ | ||
| 331 | #ifdef CONFIG_VGA_CONSOLE | ||
| 332 | if (vgacon_text_force() && radeon_modeset == -1) { | ||
| 333 | DRM_INFO("VGACON disable radeon kernel modesetting.\n"); | ||
| 334 | driver = &driver_old; | ||
| 335 | driver->driver_features &= ~DRIVER_MODESET; | ||
| 336 | radeon_modeset = 0; | ||
| 337 | } | ||
| 338 | #endif | ||
| 339 | #endif | ||
| 340 | return drm_init(driver); | ||
| 134 | } | 341 | } |
| 135 | 342 | ||
| 136 | static void __exit radeon_exit(void) | 343 | static void __exit radeon_exit(void) |
| 137 | { | 344 | { |
| 138 | drm_exit(&driver); | 345 | drm_exit(driver); |
| 139 | } | 346 | } |
| 140 | 347 | ||
| 141 | module_init(radeon_init); | 348 | late_initcall(radeon_init); |
| 142 | module_exit(radeon_exit); | 349 | module_exit(radeon_exit); |
| 143 | 350 | ||
| 144 | MODULE_AUTHOR(DRIVER_AUTHOR); | 351 | MODULE_AUTHOR(DRIVER_AUTHOR); |
diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c new file mode 100644 index 000000000000..c8ef0d14ffab --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_encoders.c | |||
| @@ -0,0 +1,1708 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2007-8 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * copy of this software and associated documentation files (the "Software"), | ||
| 7 | * to deal in the Software without restriction, including without limitation | ||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 10 | * Software is furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 21 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: Dave Airlie | ||
| 24 | * Alex Deucher | ||
| 25 | */ | ||
| 26 | #include "drmP.h" | ||
| 27 | #include "drm_crtc_helper.h" | ||
| 28 | #include "radeon_drm.h" | ||
| 29 | #include "radeon.h" | ||
| 30 | #include "atom.h" | ||
| 31 | |||
| 32 | extern int atom_debug; | ||
| 33 | |||
| 34 | uint32_t | ||
| 35 | radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, uint8_t dac) | ||
| 36 | { | ||
| 37 | struct radeon_device *rdev = dev->dev_private; | ||
| 38 | uint32_t ret = 0; | ||
| 39 | |||
| 40 | switch (supported_device) { | ||
| 41 | case ATOM_DEVICE_CRT1_SUPPORT: | ||
| 42 | case ATOM_DEVICE_TV1_SUPPORT: | ||
| 43 | case ATOM_DEVICE_TV2_SUPPORT: | ||
| 44 | case ATOM_DEVICE_CRT2_SUPPORT: | ||
| 45 | case ATOM_DEVICE_CV_SUPPORT: | ||
| 46 | switch (dac) { | ||
| 47 | case 1: /* dac a */ | ||
| 48 | if ((rdev->family == CHIP_RS300) || | ||
| 49 | (rdev->family == CHIP_RS400) || | ||
| 50 | (rdev->family == CHIP_RS480)) | ||
| 51 | ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; | ||
| 52 | else if (ASIC_IS_AVIVO(rdev)) | ||
| 53 | ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1; | ||
| 54 | else | ||
| 55 | ret = ENCODER_OBJECT_ID_INTERNAL_DAC1; | ||
| 56 | break; | ||
| 57 | case 2: /* dac b */ | ||
| 58 | if (ASIC_IS_AVIVO(rdev)) | ||
| 59 | ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2; | ||
| 60 | else { | ||
| 61 | /*if (rdev->family == CHIP_R200) | ||
| 62 | ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; | ||
| 63 | else*/ | ||
| 64 | ret = ENCODER_OBJECT_ID_INTERNAL_DAC2; | ||
| 65 | } | ||
| 66 | break; | ||
| 67 | case 3: /* external dac */ | ||
| 68 | if (ASIC_IS_AVIVO(rdev)) | ||
| 69 | ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; | ||
| 70 | else | ||
| 71 | ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; | ||
| 72 | break; | ||
| 73 | } | ||
| 74 | break; | ||
| 75 | case ATOM_DEVICE_LCD1_SUPPORT: | ||
| 76 | if (ASIC_IS_AVIVO(rdev)) | ||
| 77 | ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; | ||
| 78 | else | ||
| 79 | ret = ENCODER_OBJECT_ID_INTERNAL_LVDS; | ||
| 80 | break; | ||
| 81 | case ATOM_DEVICE_DFP1_SUPPORT: | ||
| 82 | if ((rdev->family == CHIP_RS300) || | ||
| 83 | (rdev->family == CHIP_RS400) || | ||
| 84 | (rdev->family == CHIP_RS480)) | ||
| 85 | ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; | ||
| 86 | else if (ASIC_IS_AVIVO(rdev)) | ||
| 87 | ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1; | ||
| 88 | else | ||
| 89 | ret = ENCODER_OBJECT_ID_INTERNAL_TMDS1; | ||
| 90 | break; | ||
| 91 | case ATOM_DEVICE_LCD2_SUPPORT: | ||
| 92 | case ATOM_DEVICE_DFP2_SUPPORT: | ||
| 93 | if ((rdev->family == CHIP_RS600) || | ||
| 94 | (rdev->family == CHIP_RS690) || | ||
| 95 | (rdev->family == CHIP_RS740)) | ||
| 96 | ret = ENCODER_OBJECT_ID_INTERNAL_DDI; | ||
| 97 | else if (ASIC_IS_AVIVO(rdev)) | ||
| 98 | ret = ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1; | ||
| 99 | else | ||
| 100 | ret = ENCODER_OBJECT_ID_INTERNAL_DVO1; | ||
| 101 | break; | ||
| 102 | case ATOM_DEVICE_DFP3_SUPPORT: | ||
| 103 | ret = ENCODER_OBJECT_ID_INTERNAL_LVTM1; | ||
| 104 | break; | ||
| 105 | } | ||
| 106 | |||
| 107 | return ret; | ||
| 108 | } | ||
| 109 | |||
| 110 | void | ||
| 111 | radeon_link_encoder_connector(struct drm_device *dev) | ||
| 112 | { | ||
| 113 | struct drm_connector *connector; | ||
| 114 | struct radeon_connector *radeon_connector; | ||
| 115 | struct drm_encoder *encoder; | ||
| 116 | struct radeon_encoder *radeon_encoder; | ||
| 117 | |||
| 118 | /* walk the list and link encoders to connectors */ | ||
| 119 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 120 | radeon_connector = to_radeon_connector(connector); | ||
| 121 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 122 | radeon_encoder = to_radeon_encoder(encoder); | ||
| 123 | if (radeon_encoder->devices & radeon_connector->devices) | ||
| 124 | drm_mode_connector_attach_encoder(connector, encoder); | ||
| 125 | } | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | static struct drm_connector * | ||
| 130 | radeon_get_connector_for_encoder(struct drm_encoder *encoder) | ||
| 131 | { | ||
| 132 | struct drm_device *dev = encoder->dev; | ||
| 133 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 134 | struct drm_connector *connector; | ||
| 135 | struct radeon_connector *radeon_connector; | ||
| 136 | |||
| 137 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||
| 138 | radeon_connector = to_radeon_connector(connector); | ||
| 139 | if (radeon_encoder->devices & radeon_connector->devices) | ||
| 140 | return connector; | ||
| 141 | } | ||
| 142 | return NULL; | ||
| 143 | } | ||
| 144 | |||
| 145 | /* used for both atom and legacy */ | ||
| 146 | void radeon_rmx_mode_fixup(struct drm_encoder *encoder, | ||
| 147 | struct drm_display_mode *mode, | ||
| 148 | struct drm_display_mode *adjusted_mode) | ||
| 149 | { | ||
| 150 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 151 | struct drm_device *dev = encoder->dev; | ||
| 152 | struct radeon_device *rdev = dev->dev_private; | ||
| 153 | struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; | ||
| 154 | |||
| 155 | if (mode->hdisplay < native_mode->panel_xres || | ||
| 156 | mode->vdisplay < native_mode->panel_yres) { | ||
| 157 | radeon_encoder->flags |= RADEON_USE_RMX; | ||
| 158 | if (ASIC_IS_AVIVO(rdev)) { | ||
| 159 | adjusted_mode->hdisplay = native_mode->panel_xres; | ||
| 160 | adjusted_mode->vdisplay = native_mode->panel_yres; | ||
| 161 | adjusted_mode->htotal = native_mode->panel_xres + native_mode->hblank; | ||
| 162 | adjusted_mode->hsync_start = native_mode->panel_xres + native_mode->hoverplus; | ||
| 163 | adjusted_mode->hsync_end = adjusted_mode->hsync_start + native_mode->hsync_width; | ||
| 164 | adjusted_mode->vtotal = native_mode->panel_yres + native_mode->vblank; | ||
| 165 | adjusted_mode->vsync_start = native_mode->panel_yres + native_mode->voverplus; | ||
| 166 | adjusted_mode->vsync_end = adjusted_mode->vsync_start + native_mode->vsync_width; | ||
| 167 | /* update crtc values */ | ||
| 168 | drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); | ||
| 169 | /* adjust crtc values */ | ||
| 170 | adjusted_mode->crtc_hdisplay = native_mode->panel_xres; | ||
| 171 | adjusted_mode->crtc_vdisplay = native_mode->panel_yres; | ||
| 172 | adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + native_mode->hblank; | ||
| 173 | adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + native_mode->hoverplus; | ||
| 174 | adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + native_mode->hsync_width; | ||
| 175 | adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + native_mode->vblank; | ||
| 176 | adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + native_mode->voverplus; | ||
| 177 | adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + native_mode->vsync_width; | ||
| 178 | } else { | ||
| 179 | adjusted_mode->htotal = native_mode->panel_xres + native_mode->hblank; | ||
| 180 | adjusted_mode->hsync_start = native_mode->panel_xres + native_mode->hoverplus; | ||
| 181 | adjusted_mode->hsync_end = adjusted_mode->hsync_start + native_mode->hsync_width; | ||
| 182 | adjusted_mode->vtotal = native_mode->panel_yres + native_mode->vblank; | ||
| 183 | adjusted_mode->vsync_start = native_mode->panel_yres + native_mode->voverplus; | ||
| 184 | adjusted_mode->vsync_end = adjusted_mode->vsync_start + native_mode->vsync_width; | ||
| 185 | /* update crtc values */ | ||
| 186 | drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); | ||
| 187 | /* adjust crtc values */ | ||
| 188 | adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + native_mode->hblank; | ||
| 189 | adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + native_mode->hoverplus; | ||
| 190 | adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + native_mode->hsync_width; | ||
| 191 | adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + native_mode->vblank; | ||
| 192 | adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + native_mode->voverplus; | ||
| 193 | adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + native_mode->vsync_width; | ||
| 194 | } | ||
| 195 | adjusted_mode->flags = native_mode->flags; | ||
| 196 | adjusted_mode->clock = native_mode->dotclock; | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, | ||
| 201 | struct drm_display_mode *mode, | ||
| 202 | struct drm_display_mode *adjusted_mode) | ||
| 203 | { | ||
| 204 | |||
| 205 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 206 | |||
| 207 | radeon_encoder->flags &= ~RADEON_USE_RMX; | ||
| 208 | |||
| 209 | drm_mode_set_crtcinfo(adjusted_mode, 0); | ||
| 210 | |||
| 211 | if (radeon_encoder->rmx_type != RMX_OFF) | ||
| 212 | radeon_rmx_mode_fixup(encoder, mode, adjusted_mode); | ||
| 213 | |||
| 214 | /* hw bug */ | ||
| 215 | if ((mode->flags & DRM_MODE_FLAG_INTERLACE) | ||
| 216 | && (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2))) | ||
| 217 | adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2; | ||
| 218 | |||
| 219 | return true; | ||
| 220 | } | ||
| 221 | |||
| 222 | static void | ||
| 223 | atombios_dac_setup(struct drm_encoder *encoder, int action) | ||
| 224 | { | ||
| 225 | struct drm_device *dev = encoder->dev; | ||
| 226 | struct radeon_device *rdev = dev->dev_private; | ||
| 227 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 228 | DAC_ENCODER_CONTROL_PS_ALLOCATION args; | ||
| 229 | int index = 0, num = 0; | ||
| 230 | /* fixme - fill in enc_priv for atom dac */ | ||
| 231 | enum radeon_tv_std tv_std = TV_STD_NTSC; | ||
| 232 | |||
| 233 | memset(&args, 0, sizeof(args)); | ||
| 234 | |||
| 235 | switch (radeon_encoder->encoder_id) { | ||
| 236 | case ENCODER_OBJECT_ID_INTERNAL_DAC1: | ||
| 237 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: | ||
| 238 | index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl); | ||
| 239 | num = 1; | ||
| 240 | break; | ||
| 241 | case ENCODER_OBJECT_ID_INTERNAL_DAC2: | ||
| 242 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: | ||
| 243 | index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl); | ||
| 244 | num = 2; | ||
| 245 | break; | ||
| 246 | } | ||
| 247 | |||
| 248 | args.ucAction = action; | ||
| 249 | |||
| 250 | if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT)) | ||
| 251 | args.ucDacStandard = ATOM_DAC1_PS2; | ||
| 252 | else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) | ||
| 253 | args.ucDacStandard = ATOM_DAC1_CV; | ||
| 254 | else { | ||
| 255 | switch (tv_std) { | ||
| 256 | case TV_STD_PAL: | ||
| 257 | case TV_STD_PAL_M: | ||
| 258 | case TV_STD_SCART_PAL: | ||
| 259 | case TV_STD_SECAM: | ||
| 260 | case TV_STD_PAL_CN: | ||
| 261 | args.ucDacStandard = ATOM_DAC1_PAL; | ||
| 262 | break; | ||
| 263 | case TV_STD_NTSC: | ||
| 264 | case TV_STD_NTSC_J: | ||
| 265 | case TV_STD_PAL_60: | ||
| 266 | default: | ||
| 267 | args.ucDacStandard = ATOM_DAC1_NTSC; | ||
| 268 | break; | ||
| 269 | } | ||
| 270 | } | ||
| 271 | args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); | ||
| 272 | |||
| 273 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 274 | |||
| 275 | } | ||
| 276 | |||
| 277 | static void | ||
| 278 | atombios_tv_setup(struct drm_encoder *encoder, int action) | ||
| 279 | { | ||
| 280 | struct drm_device *dev = encoder->dev; | ||
| 281 | struct radeon_device *rdev = dev->dev_private; | ||
| 282 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 283 | TV_ENCODER_CONTROL_PS_ALLOCATION args; | ||
| 284 | int index = 0; | ||
| 285 | /* fixme - fill in enc_priv for atom dac */ | ||
| 286 | enum radeon_tv_std tv_std = TV_STD_NTSC; | ||
| 287 | |||
| 288 | memset(&args, 0, sizeof(args)); | ||
| 289 | |||
| 290 | index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); | ||
| 291 | |||
| 292 | args.sTVEncoder.ucAction = action; | ||
| 293 | |||
| 294 | if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) | ||
| 295 | args.sTVEncoder.ucTvStandard = ATOM_TV_CV; | ||
| 296 | else { | ||
| 297 | switch (tv_std) { | ||
| 298 | case TV_STD_NTSC: | ||
| 299 | args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; | ||
| 300 | break; | ||
| 301 | case TV_STD_PAL: | ||
| 302 | args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; | ||
| 303 | break; | ||
| 304 | case TV_STD_PAL_M: | ||
| 305 | args.sTVEncoder.ucTvStandard = ATOM_TV_PALM; | ||
| 306 | break; | ||
| 307 | case TV_STD_PAL_60: | ||
| 308 | args.sTVEncoder.ucTvStandard = ATOM_TV_PAL60; | ||
| 309 | break; | ||
| 310 | case TV_STD_NTSC_J: | ||
| 311 | args.sTVEncoder.ucTvStandard = ATOM_TV_NTSCJ; | ||
| 312 | break; | ||
| 313 | case TV_STD_SCART_PAL: | ||
| 314 | args.sTVEncoder.ucTvStandard = ATOM_TV_PAL; /* ??? */ | ||
| 315 | break; | ||
| 316 | case TV_STD_SECAM: | ||
| 317 | args.sTVEncoder.ucTvStandard = ATOM_TV_SECAM; | ||
| 318 | break; | ||
| 319 | case TV_STD_PAL_CN: | ||
| 320 | args.sTVEncoder.ucTvStandard = ATOM_TV_PALCN; | ||
| 321 | break; | ||
| 322 | default: | ||
| 323 | args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC; | ||
| 324 | break; | ||
| 325 | } | ||
| 326 | } | ||
| 327 | |||
| 328 | args.sTVEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); | ||
| 329 | |||
| 330 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 331 | |||
| 332 | } | ||
| 333 | |||
| 334 | void | ||
| 335 | atombios_external_tmds_setup(struct drm_encoder *encoder, int action) | ||
| 336 | { | ||
| 337 | struct drm_device *dev = encoder->dev; | ||
| 338 | struct radeon_device *rdev = dev->dev_private; | ||
| 339 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 340 | ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION args; | ||
| 341 | int index = 0; | ||
| 342 | |||
| 343 | memset(&args, 0, sizeof(args)); | ||
| 344 | |||
| 345 | index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); | ||
| 346 | |||
| 347 | args.sXTmdsEncoder.ucEnable = action; | ||
| 348 | |||
| 349 | if (radeon_encoder->pixel_clock > 165000) | ||
| 350 | args.sXTmdsEncoder.ucMisc = PANEL_ENCODER_MISC_DUAL; | ||
| 351 | |||
| 352 | /*if (pScrn->rgbBits == 8)*/ | ||
| 353 | args.sXTmdsEncoder.ucMisc |= (1 << 1); | ||
| 354 | |||
| 355 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 356 | |||
| 357 | } | ||
| 358 | |||
| 359 | static void | ||
| 360 | atombios_ddia_setup(struct drm_encoder *encoder, int action) | ||
| 361 | { | ||
| 362 | struct drm_device *dev = encoder->dev; | ||
| 363 | struct radeon_device *rdev = dev->dev_private; | ||
| 364 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 365 | DVO_ENCODER_CONTROL_PS_ALLOCATION args; | ||
| 366 | int index = 0; | ||
| 367 | |||
| 368 | memset(&args, 0, sizeof(args)); | ||
| 369 | |||
| 370 | index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); | ||
| 371 | |||
| 372 | args.sDVOEncoder.ucAction = action; | ||
| 373 | args.sDVOEncoder.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); | ||
| 374 | |||
| 375 | if (radeon_encoder->pixel_clock > 165000) | ||
| 376 | args.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL; | ||
| 377 | |||
| 378 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 379 | |||
| 380 | } | ||
| 381 | |||
| 382 | union lvds_encoder_control { | ||
| 383 | LVDS_ENCODER_CONTROL_PS_ALLOCATION v1; | ||
| 384 | LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2; | ||
| 385 | }; | ||
| 386 | |||
| 387 | static void | ||
| 388 | atombios_digital_setup(struct drm_encoder *encoder, int action) | ||
| 389 | { | ||
| 390 | struct drm_device *dev = encoder->dev; | ||
| 391 | struct radeon_device *rdev = dev->dev_private; | ||
| 392 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 393 | union lvds_encoder_control args; | ||
| 394 | int index = 0; | ||
| 395 | uint8_t frev, crev; | ||
| 396 | struct radeon_encoder_atom_dig *dig; | ||
| 397 | struct drm_connector *connector; | ||
| 398 | struct radeon_connector *radeon_connector; | ||
| 399 | struct radeon_connector_atom_dig *dig_connector; | ||
| 400 | |||
| 401 | connector = radeon_get_connector_for_encoder(encoder); | ||
| 402 | if (!connector) | ||
| 403 | return; | ||
| 404 | |||
| 405 | radeon_connector = to_radeon_connector(connector); | ||
| 406 | |||
| 407 | if (!radeon_encoder->enc_priv) | ||
| 408 | return; | ||
| 409 | |||
| 410 | dig = radeon_encoder->enc_priv; | ||
| 411 | |||
| 412 | if (!radeon_connector->con_priv) | ||
| 413 | return; | ||
| 414 | |||
| 415 | dig_connector = radeon_connector->con_priv; | ||
| 416 | |||
| 417 | memset(&args, 0, sizeof(args)); | ||
| 418 | |||
| 419 | switch (radeon_encoder->encoder_id) { | ||
| 420 | case ENCODER_OBJECT_ID_INTERNAL_LVDS: | ||
| 421 | index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); | ||
| 422 | break; | ||
| 423 | case ENCODER_OBJECT_ID_INTERNAL_TMDS1: | ||
| 424 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: | ||
| 425 | index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl); | ||
| 426 | break; | ||
| 427 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: | ||
| 428 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) | ||
| 429 | index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl); | ||
| 430 | else | ||
| 431 | index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl); | ||
| 432 | break; | ||
| 433 | } | ||
| 434 | |||
| 435 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); | ||
| 436 | |||
| 437 | switch (frev) { | ||
| 438 | case 1: | ||
| 439 | case 2: | ||
| 440 | switch (crev) { | ||
| 441 | case 1: | ||
| 442 | args.v1.ucMisc = 0; | ||
| 443 | args.v1.ucAction = action; | ||
| 444 | if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr)) | ||
| 445 | args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; | ||
| 446 | args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); | ||
| 447 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | ||
| 448 | if (dig->lvds_misc & (1 << 0)) | ||
| 449 | args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; | ||
| 450 | if (dig->lvds_misc & (1 << 1)) | ||
| 451 | args.v1.ucMisc |= (1 << 1); | ||
| 452 | } else { | ||
| 453 | if (dig_connector->linkb) | ||
| 454 | args.v1.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; | ||
| 455 | if (radeon_encoder->pixel_clock > 165000) | ||
| 456 | args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; | ||
| 457 | /*if (pScrn->rgbBits == 8) */ | ||
| 458 | args.v1.ucMisc |= (1 << 1); | ||
| 459 | } | ||
| 460 | break; | ||
| 461 | case 2: | ||
| 462 | case 3: | ||
| 463 | args.v2.ucMisc = 0; | ||
| 464 | args.v2.ucAction = action; | ||
| 465 | if (crev == 3) { | ||
| 466 | if (dig->coherent_mode) | ||
| 467 | args.v2.ucMisc |= PANEL_ENCODER_MISC_COHERENT; | ||
| 468 | } | ||
| 469 | if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr)) | ||
| 470 | args.v2.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; | ||
| 471 | args.v2.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); | ||
| 472 | args.v2.ucTruncate = 0; | ||
| 473 | args.v2.ucSpatial = 0; | ||
| 474 | args.v2.ucTemporal = 0; | ||
| 475 | args.v2.ucFRC = 0; | ||
| 476 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | ||
| 477 | if (dig->lvds_misc & (1 << 0)) | ||
| 478 | args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; | ||
| 479 | if (dig->lvds_misc & (1 << 5)) { | ||
| 480 | args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; | ||
| 481 | if (dig->lvds_misc & (1 << 1)) | ||
| 482 | args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; | ||
| 483 | } | ||
| 484 | if (dig->lvds_misc & (1 << 6)) { | ||
| 485 | args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; | ||
| 486 | if (dig->lvds_misc & (1 << 1)) | ||
| 487 | args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; | ||
| 488 | if (((dig->lvds_misc >> 2) & 0x3) == 2) | ||
| 489 | args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; | ||
| 490 | } | ||
| 491 | } else { | ||
| 492 | if (dig_connector->linkb) | ||
| 493 | args.v2.ucMisc |= PANEL_ENCODER_MISC_TMDS_LINKB; | ||
| 494 | if (radeon_encoder->pixel_clock > 165000) | ||
| 495 | args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; | ||
| 496 | } | ||
| 497 | break; | ||
| 498 | default: | ||
| 499 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev); | ||
| 500 | break; | ||
| 501 | } | ||
| 502 | break; | ||
| 503 | default: | ||
| 504 | DRM_ERROR("Unknown table version %d, %d\n", frev, crev); | ||
| 505 | break; | ||
| 506 | } | ||
| 507 | |||
| 508 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 509 | |||
| 510 | } | ||
| 511 | |||
| 512 | int | ||
| 513 | atombios_get_encoder_mode(struct drm_encoder *encoder) | ||
| 514 | { | ||
| 515 | struct drm_connector *connector; | ||
| 516 | struct radeon_connector *radeon_connector; | ||
| 517 | |||
| 518 | connector = radeon_get_connector_for_encoder(encoder); | ||
| 519 | if (!connector) | ||
| 520 | return 0; | ||
| 521 | |||
| 522 | radeon_connector = to_radeon_connector(connector); | ||
| 523 | |||
| 524 | switch (connector->connector_type) { | ||
| 525 | case DRM_MODE_CONNECTOR_DVII: | ||
| 526 | if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr)) | ||
| 527 | return ATOM_ENCODER_MODE_HDMI; | ||
| 528 | else if (radeon_connector->use_digital) | ||
| 529 | return ATOM_ENCODER_MODE_DVI; | ||
| 530 | else | ||
| 531 | return ATOM_ENCODER_MODE_CRT; | ||
| 532 | break; | ||
| 533 | case DRM_MODE_CONNECTOR_DVID: | ||
| 534 | case DRM_MODE_CONNECTOR_HDMIA: | ||
| 535 | case DRM_MODE_CONNECTOR_HDMIB: | ||
| 536 | default: | ||
| 537 | if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr)) | ||
| 538 | return ATOM_ENCODER_MODE_HDMI; | ||
| 539 | else | ||
| 540 | return ATOM_ENCODER_MODE_DVI; | ||
| 541 | break; | ||
| 542 | case DRM_MODE_CONNECTOR_LVDS: | ||
| 543 | return ATOM_ENCODER_MODE_LVDS; | ||
| 544 | break; | ||
| 545 | case DRM_MODE_CONNECTOR_DisplayPort: | ||
| 546 | /*if (radeon_output->MonType == MT_DP) | ||
| 547 | return ATOM_ENCODER_MODE_DP; | ||
| 548 | else*/ | ||
| 549 | if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr)) | ||
| 550 | return ATOM_ENCODER_MODE_HDMI; | ||
| 551 | else | ||
| 552 | return ATOM_ENCODER_MODE_DVI; | ||
| 553 | break; | ||
| 554 | case CONNECTOR_DVI_A: | ||
| 555 | case CONNECTOR_VGA: | ||
| 556 | return ATOM_ENCODER_MODE_CRT; | ||
| 557 | break; | ||
| 558 | case CONNECTOR_STV: | ||
| 559 | case CONNECTOR_CTV: | ||
| 560 | case CONNECTOR_DIN: | ||
| 561 | /* fix me */ | ||
| 562 | return ATOM_ENCODER_MODE_TV; | ||
| 563 | /*return ATOM_ENCODER_MODE_CV;*/ | ||
| 564 | break; | ||
| 565 | } | ||
| 566 | } | ||
| 567 | |||
| 568 | static void | ||
| 569 | atombios_dig_encoder_setup(struct drm_encoder *encoder, int action) | ||
| 570 | { | ||
| 571 | struct drm_device *dev = encoder->dev; | ||
| 572 | struct radeon_device *rdev = dev->dev_private; | ||
| 573 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 574 | DIG_ENCODER_CONTROL_PS_ALLOCATION args; | ||
| 575 | int index = 0, num = 0; | ||
| 576 | uint8_t frev, crev; | ||
| 577 | struct radeon_encoder_atom_dig *dig; | ||
| 578 | struct drm_connector *connector; | ||
| 579 | struct radeon_connector *radeon_connector; | ||
| 580 | struct radeon_connector_atom_dig *dig_connector; | ||
| 581 | |||
| 582 | connector = radeon_get_connector_for_encoder(encoder); | ||
| 583 | if (!connector) | ||
| 584 | return; | ||
| 585 | |||
| 586 | radeon_connector = to_radeon_connector(connector); | ||
| 587 | |||
| 588 | if (!radeon_connector->con_priv) | ||
| 589 | return; | ||
| 590 | |||
| 591 | dig_connector = radeon_connector->con_priv; | ||
| 592 | |||
| 593 | if (!radeon_encoder->enc_priv) | ||
| 594 | return; | ||
| 595 | |||
| 596 | dig = radeon_encoder->enc_priv; | ||
| 597 | |||
| 598 | memset(&args, 0, sizeof(args)); | ||
| 599 | |||
| 600 | if (ASIC_IS_DCE32(rdev)) { | ||
| 601 | if (dig->dig_block) | ||
| 602 | index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); | ||
| 603 | else | ||
| 604 | index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); | ||
| 605 | num = dig->dig_block + 1; | ||
| 606 | } else { | ||
| 607 | switch (radeon_encoder->encoder_id) { | ||
| 608 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | ||
| 609 | index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl); | ||
| 610 | num = 1; | ||
| 611 | break; | ||
| 612 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
| 613 | index = GetIndexIntoMasterTable(COMMAND, DIG2EncoderControl); | ||
| 614 | num = 2; | ||
| 615 | break; | ||
| 616 | } | ||
| 617 | } | ||
| 618 | |||
| 619 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); | ||
| 620 | |||
| 621 | args.ucAction = action; | ||
| 622 | args.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); | ||
| 623 | |||
| 624 | if (ASIC_IS_DCE32(rdev)) { | ||
| 625 | switch (radeon_encoder->encoder_id) { | ||
| 626 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | ||
| 627 | args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER1; | ||
| 628 | break; | ||
| 629 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | ||
| 630 | args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER2; | ||
| 631 | break; | ||
| 632 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | ||
| 633 | args.ucConfig = ATOM_ENCODER_CONFIG_V2_TRANSMITTER3; | ||
| 634 | break; | ||
| 635 | } | ||
| 636 | } else { | ||
| 637 | switch (radeon_encoder->encoder_id) { | ||
| 638 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | ||
| 639 | args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER1; | ||
| 640 | break; | ||
| 641 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
| 642 | args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER2; | ||
| 643 | break; | ||
| 644 | } | ||
| 645 | } | ||
| 646 | |||
| 647 | if (radeon_encoder->pixel_clock > 165000) { | ||
| 648 | args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA_B; | ||
| 649 | args.ucLaneNum = 8; | ||
| 650 | } else { | ||
| 651 | if (dig_connector->linkb) | ||
| 652 | args.ucConfig |= ATOM_ENCODER_CONFIG_LINKB; | ||
| 653 | else | ||
| 654 | args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA; | ||
| 655 | args.ucLaneNum = 4; | ||
| 656 | } | ||
| 657 | |||
| 658 | args.ucEncoderMode = atombios_get_encoder_mode(encoder); | ||
| 659 | |||
| 660 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 661 | |||
| 662 | } | ||
| 663 | |||
| 664 | union dig_transmitter_control { | ||
| 665 | DIG_TRANSMITTER_CONTROL_PS_ALLOCATION v1; | ||
| 666 | DIG_TRANSMITTER_CONTROL_PARAMETERS_V2 v2; | ||
| 667 | }; | ||
| 668 | |||
| 669 | static void | ||
| 670 | atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action) | ||
| 671 | { | ||
| 672 | struct drm_device *dev = encoder->dev; | ||
| 673 | struct radeon_device *rdev = dev->dev_private; | ||
| 674 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 675 | union dig_transmitter_control args; | ||
| 676 | int index = 0, num = 0; | ||
| 677 | uint8_t frev, crev; | ||
| 678 | struct radeon_encoder_atom_dig *dig; | ||
| 679 | struct drm_connector *connector; | ||
| 680 | struct radeon_connector *radeon_connector; | ||
| 681 | struct radeon_connector_atom_dig *dig_connector; | ||
| 682 | |||
| 683 | connector = radeon_get_connector_for_encoder(encoder); | ||
| 684 | if (!connector) | ||
| 685 | return; | ||
| 686 | |||
| 687 | radeon_connector = to_radeon_connector(connector); | ||
| 688 | |||
| 689 | if (!radeon_encoder->enc_priv) | ||
| 690 | return; | ||
| 691 | |||
| 692 | dig = radeon_encoder->enc_priv; | ||
| 693 | |||
| 694 | if (!radeon_connector->con_priv) | ||
| 695 | return; | ||
| 696 | |||
| 697 | dig_connector = radeon_connector->con_priv; | ||
| 698 | |||
| 699 | memset(&args, 0, sizeof(args)); | ||
| 700 | |||
| 701 | if (ASIC_IS_DCE32(rdev)) | ||
| 702 | index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); | ||
| 703 | else { | ||
| 704 | switch (radeon_encoder->encoder_id) { | ||
| 705 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | ||
| 706 | index = GetIndexIntoMasterTable(COMMAND, DIG1TransmitterControl); | ||
| 707 | break; | ||
| 708 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
| 709 | index = GetIndexIntoMasterTable(COMMAND, DIG2TransmitterControl); | ||
| 710 | break; | ||
| 711 | } | ||
| 712 | } | ||
| 713 | |||
| 714 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); | ||
| 715 | |||
| 716 | args.v1.ucAction = action; | ||
| 717 | |||
| 718 | if (ASIC_IS_DCE32(rdev)) { | ||
| 719 | if (radeon_encoder->pixel_clock > 165000) { | ||
| 720 | args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock * 10 * 2) / 100); | ||
| 721 | args.v2.acConfig.fDualLinkConnector = 1; | ||
| 722 | } else { | ||
| 723 | args.v2.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock * 10 * 4) / 100); | ||
| 724 | } | ||
| 725 | if (dig->dig_block) | ||
| 726 | args.v2.acConfig.ucEncoderSel = 1; | ||
| 727 | |||
| 728 | switch (radeon_encoder->encoder_id) { | ||
| 729 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | ||
| 730 | args.v2.acConfig.ucTransmitterSel = 0; | ||
| 731 | num = 0; | ||
| 732 | break; | ||
| 733 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | ||
| 734 | args.v2.acConfig.ucTransmitterSel = 1; | ||
| 735 | num = 1; | ||
| 736 | break; | ||
| 737 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | ||
| 738 | args.v2.acConfig.ucTransmitterSel = 2; | ||
| 739 | num = 2; | ||
| 740 | break; | ||
| 741 | } | ||
| 742 | |||
| 743 | if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { | ||
| 744 | if (dig->coherent_mode) | ||
| 745 | args.v2.acConfig.fCoherentMode = 1; | ||
| 746 | } | ||
| 747 | } else { | ||
| 748 | args.v1.ucConfig = ATOM_TRANSMITTER_CONFIG_CLKSRC_PPLL; | ||
| 749 | args.v1.usPixelClock = cpu_to_le16((radeon_encoder->pixel_clock) / 10); | ||
| 750 | |||
| 751 | switch (radeon_encoder->encoder_id) { | ||
| 752 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | ||
| 753 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG1_ENCODER; | ||
| 754 | if (rdev->flags & RADEON_IS_IGP) { | ||
| 755 | if (radeon_encoder->pixel_clock > 165000) { | ||
| 756 | args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | | ||
| 757 | ATOM_TRANSMITTER_CONFIG_LINKA_B); | ||
| 758 | if (dig_connector->igp_lane_info & 0x3) | ||
| 759 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_7; | ||
| 760 | else if (dig_connector->igp_lane_info & 0xc) | ||
| 761 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_15; | ||
| 762 | } else { | ||
| 763 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA; | ||
| 764 | if (dig_connector->igp_lane_info & 0x1) | ||
| 765 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_0_3; | ||
| 766 | else if (dig_connector->igp_lane_info & 0x2) | ||
| 767 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_4_7; | ||
| 768 | else if (dig_connector->igp_lane_info & 0x4) | ||
| 769 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_8_11; | ||
| 770 | else if (dig_connector->igp_lane_info & 0x8) | ||
| 771 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LANE_12_15; | ||
| 772 | } | ||
| 773 | } else { | ||
| 774 | if (radeon_encoder->pixel_clock > 165000) | ||
| 775 | args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | | ||
| 776 | ATOM_TRANSMITTER_CONFIG_LINKA_B | | ||
| 777 | ATOM_TRANSMITTER_CONFIG_LANE_0_7); | ||
| 778 | else { | ||
| 779 | if (dig_connector->linkb) | ||
| 780 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3; | ||
| 781 | else | ||
| 782 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3; | ||
| 783 | } | ||
| 784 | } | ||
| 785 | break; | ||
| 786 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
| 787 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_DIG2_ENCODER; | ||
| 788 | if (radeon_encoder->pixel_clock > 165000) | ||
| 789 | args.v1.ucConfig |= (ATOM_TRANSMITTER_CONFIG_8LANE_LINK | | ||
| 790 | ATOM_TRANSMITTER_CONFIG_LINKA_B | | ||
| 791 | ATOM_TRANSMITTER_CONFIG_LANE_0_7); | ||
| 792 | else { | ||
| 793 | if (dig_connector->linkb) | ||
| 794 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKB | ATOM_TRANSMITTER_CONFIG_LANE_0_3; | ||
| 795 | else | ||
| 796 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_LINKA | ATOM_TRANSMITTER_CONFIG_LANE_0_3; | ||
| 797 | } | ||
| 798 | break; | ||
| 799 | } | ||
| 800 | |||
| 801 | if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { | ||
| 802 | if (dig->coherent_mode) | ||
| 803 | args.v1.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT; | ||
| 804 | } | ||
| 805 | } | ||
| 806 | |||
| 807 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 808 | |||
| 809 | } | ||
| 810 | |||
| 811 | static void atom_rv515_force_tv_scaler(struct radeon_device *rdev) | ||
| 812 | { | ||
| 813 | |||
| 814 | WREG32(0x659C, 0x0); | ||
| 815 | WREG32(0x6594, 0x705); | ||
| 816 | WREG32(0x65A4, 0x10001); | ||
| 817 | WREG32(0x65D8, 0x0); | ||
| 818 | WREG32(0x65B0, 0x0); | ||
| 819 | WREG32(0x65C0, 0x0); | ||
| 820 | WREG32(0x65D4, 0x0); | ||
| 821 | WREG32(0x6578, 0x0); | ||
| 822 | WREG32(0x657C, 0x841880A8); | ||
| 823 | WREG32(0x6578, 0x1); | ||
| 824 | WREG32(0x657C, 0x84208680); | ||
| 825 | WREG32(0x6578, 0x2); | ||
| 826 | WREG32(0x657C, 0xBFF880B0); | ||
| 827 | WREG32(0x6578, 0x100); | ||
| 828 | WREG32(0x657C, 0x83D88088); | ||
| 829 | WREG32(0x6578, 0x101); | ||
| 830 | WREG32(0x657C, 0x84608680); | ||
| 831 | WREG32(0x6578, 0x102); | ||
| 832 | WREG32(0x657C, 0xBFF080D0); | ||
| 833 | WREG32(0x6578, 0x200); | ||
| 834 | WREG32(0x657C, 0x83988068); | ||
| 835 | WREG32(0x6578, 0x201); | ||
| 836 | WREG32(0x657C, 0x84A08680); | ||
| 837 | WREG32(0x6578, 0x202); | ||
| 838 | WREG32(0x657C, 0xBFF080F8); | ||
| 839 | WREG32(0x6578, 0x300); | ||
| 840 | WREG32(0x657C, 0x83588058); | ||
| 841 | WREG32(0x6578, 0x301); | ||
| 842 | WREG32(0x657C, 0x84E08660); | ||
| 843 | WREG32(0x6578, 0x302); | ||
| 844 | WREG32(0x657C, 0xBFF88120); | ||
| 845 | WREG32(0x6578, 0x400); | ||
| 846 | WREG32(0x657C, 0x83188040); | ||
| 847 | WREG32(0x6578, 0x401); | ||
| 848 | WREG32(0x657C, 0x85008660); | ||
| 849 | WREG32(0x6578, 0x402); | ||
| 850 | WREG32(0x657C, 0xBFF88150); | ||
| 851 | WREG32(0x6578, 0x500); | ||
| 852 | WREG32(0x657C, 0x82D88030); | ||
| 853 | WREG32(0x6578, 0x501); | ||
| 854 | WREG32(0x657C, 0x85408640); | ||
| 855 | WREG32(0x6578, 0x502); | ||
| 856 | WREG32(0x657C, 0xBFF88180); | ||
| 857 | WREG32(0x6578, 0x600); | ||
| 858 | WREG32(0x657C, 0x82A08018); | ||
| 859 | WREG32(0x6578, 0x601); | ||
| 860 | WREG32(0x657C, 0x85808620); | ||
| 861 | WREG32(0x6578, 0x602); | ||
| 862 | WREG32(0x657C, 0xBFF081B8); | ||
| 863 | WREG32(0x6578, 0x700); | ||
| 864 | WREG32(0x657C, 0x82608010); | ||
| 865 | WREG32(0x6578, 0x701); | ||
| 866 | WREG32(0x657C, 0x85A08600); | ||
| 867 | WREG32(0x6578, 0x702); | ||
| 868 | WREG32(0x657C, 0x800081F0); | ||
| 869 | WREG32(0x6578, 0x800); | ||
| 870 | WREG32(0x657C, 0x8228BFF8); | ||
| 871 | WREG32(0x6578, 0x801); | ||
| 872 | WREG32(0x657C, 0x85E085E0); | ||
| 873 | WREG32(0x6578, 0x802); | ||
| 874 | WREG32(0x657C, 0xBFF88228); | ||
| 875 | WREG32(0x6578, 0x10000); | ||
| 876 | WREG32(0x657C, 0x82A8BF00); | ||
| 877 | WREG32(0x6578, 0x10001); | ||
| 878 | WREG32(0x657C, 0x82A08CC0); | ||
| 879 | WREG32(0x6578, 0x10002); | ||
| 880 | WREG32(0x657C, 0x8008BEF8); | ||
| 881 | WREG32(0x6578, 0x10100); | ||
| 882 | WREG32(0x657C, 0x81F0BF28); | ||
| 883 | WREG32(0x6578, 0x10101); | ||
| 884 | WREG32(0x657C, 0x83608CA0); | ||
| 885 | WREG32(0x6578, 0x10102); | ||
| 886 | WREG32(0x657C, 0x8018BED0); | ||
| 887 | WREG32(0x6578, 0x10200); | ||
| 888 | WREG32(0x657C, 0x8148BF38); | ||
| 889 | WREG32(0x6578, 0x10201); | ||
| 890 | WREG32(0x657C, 0x84408C80); | ||
| 891 | WREG32(0x6578, 0x10202); | ||
| 892 | WREG32(0x657C, 0x8008BEB8); | ||
| 893 | WREG32(0x6578, 0x10300); | ||
| 894 | WREG32(0x657C, 0x80B0BF78); | ||
| 895 | WREG32(0x6578, 0x10301); | ||
| 896 | WREG32(0x657C, 0x85008C20); | ||
| 897 | WREG32(0x6578, 0x10302); | ||
| 898 | WREG32(0x657C, 0x8020BEA0); | ||
| 899 | WREG32(0x6578, 0x10400); | ||
| 900 | WREG32(0x657C, 0x8028BF90); | ||
| 901 | WREG32(0x6578, 0x10401); | ||
| 902 | WREG32(0x657C, 0x85E08BC0); | ||
| 903 | WREG32(0x6578, 0x10402); | ||
| 904 | WREG32(0x657C, 0x8018BE90); | ||
| 905 | WREG32(0x6578, 0x10500); | ||
| 906 | WREG32(0x657C, 0xBFB8BFB0); | ||
| 907 | WREG32(0x6578, 0x10501); | ||
| 908 | WREG32(0x657C, 0x86C08B40); | ||
| 909 | WREG32(0x6578, 0x10502); | ||
| 910 | WREG32(0x657C, 0x8010BE90); | ||
| 911 | WREG32(0x6578, 0x10600); | ||
| 912 | WREG32(0x657C, 0xBF58BFC8); | ||
| 913 | WREG32(0x6578, 0x10601); | ||
| 914 | WREG32(0x657C, 0x87A08AA0); | ||
| 915 | WREG32(0x6578, 0x10602); | ||
| 916 | WREG32(0x657C, 0x8010BE98); | ||
| 917 | WREG32(0x6578, 0x10700); | ||
| 918 | WREG32(0x657C, 0xBF10BFF0); | ||
| 919 | WREG32(0x6578, 0x10701); | ||
| 920 | WREG32(0x657C, 0x886089E0); | ||
| 921 | WREG32(0x6578, 0x10702); | ||
| 922 | WREG32(0x657C, 0x8018BEB0); | ||
| 923 | WREG32(0x6578, 0x10800); | ||
| 924 | WREG32(0x657C, 0xBED8BFE8); | ||
| 925 | WREG32(0x6578, 0x10801); | ||
| 926 | WREG32(0x657C, 0x89408940); | ||
| 927 | WREG32(0x6578, 0x10802); | ||
| 928 | WREG32(0x657C, 0xBFE8BED8); | ||
| 929 | WREG32(0x6578, 0x20000); | ||
| 930 | WREG32(0x657C, 0x80008000); | ||
| 931 | WREG32(0x6578, 0x20001); | ||
| 932 | WREG32(0x657C, 0x90008000); | ||
| 933 | WREG32(0x6578, 0x20002); | ||
| 934 | WREG32(0x657C, 0x80008000); | ||
| 935 | WREG32(0x6578, 0x20003); | ||
| 936 | WREG32(0x657C, 0x80008000); | ||
| 937 | WREG32(0x6578, 0x20100); | ||
| 938 | WREG32(0x657C, 0x80108000); | ||
| 939 | WREG32(0x6578, 0x20101); | ||
| 940 | WREG32(0x657C, 0x8FE0BF70); | ||
| 941 | WREG32(0x6578, 0x20102); | ||
| 942 | WREG32(0x657C, 0xBFE880C0); | ||
| 943 | WREG32(0x6578, 0x20103); | ||
| 944 | WREG32(0x657C, 0x80008000); | ||
| 945 | WREG32(0x6578, 0x20200); | ||
| 946 | WREG32(0x657C, 0x8018BFF8); | ||
| 947 | WREG32(0x6578, 0x20201); | ||
| 948 | WREG32(0x657C, 0x8F80BF08); | ||
| 949 | WREG32(0x6578, 0x20202); | ||
| 950 | WREG32(0x657C, 0xBFD081A0); | ||
| 951 | WREG32(0x6578, 0x20203); | ||
| 952 | WREG32(0x657C, 0xBFF88000); | ||
| 953 | WREG32(0x6578, 0x20300); | ||
| 954 | WREG32(0x657C, 0x80188000); | ||
| 955 | WREG32(0x6578, 0x20301); | ||
| 956 | WREG32(0x657C, 0x8EE0BEC0); | ||
| 957 | WREG32(0x6578, 0x20302); | ||
| 958 | WREG32(0x657C, 0xBFB082A0); | ||
| 959 | WREG32(0x6578, 0x20303); | ||
| 960 | WREG32(0x657C, 0x80008000); | ||
| 961 | WREG32(0x6578, 0x20400); | ||
| 962 | WREG32(0x657C, 0x80188000); | ||
| 963 | WREG32(0x6578, 0x20401); | ||
| 964 | WREG32(0x657C, 0x8E00BEA0); | ||
| 965 | WREG32(0x6578, 0x20402); | ||
| 966 | WREG32(0x657C, 0xBF8883C0); | ||
| 967 | WREG32(0x6578, 0x20403); | ||
| 968 | WREG32(0x657C, 0x80008000); | ||
| 969 | WREG32(0x6578, 0x20500); | ||
| 970 | WREG32(0x657C, 0x80188000); | ||
| 971 | WREG32(0x6578, 0x20501); | ||
| 972 | WREG32(0x657C, 0x8D00BE90); | ||
| 973 | WREG32(0x6578, 0x20502); | ||
| 974 | WREG32(0x657C, 0xBF588500); | ||
| 975 | WREG32(0x6578, 0x20503); | ||
| 976 | WREG32(0x657C, 0x80008008); | ||
| 977 | WREG32(0x6578, 0x20600); | ||
| 978 | WREG32(0x657C, 0x80188000); | ||
| 979 | WREG32(0x6578, 0x20601); | ||
| 980 | WREG32(0x657C, 0x8BC0BE98); | ||
| 981 | WREG32(0x6578, 0x20602); | ||
| 982 | WREG32(0x657C, 0xBF308660); | ||
| 983 | WREG32(0x6578, 0x20603); | ||
| 984 | WREG32(0x657C, 0x80008008); | ||
| 985 | WREG32(0x6578, 0x20700); | ||
| 986 | WREG32(0x657C, 0x80108000); | ||
| 987 | WREG32(0x6578, 0x20701); | ||
| 988 | WREG32(0x657C, 0x8A80BEB0); | ||
| 989 | WREG32(0x6578, 0x20702); | ||
| 990 | WREG32(0x657C, 0xBF0087C0); | ||
| 991 | WREG32(0x6578, 0x20703); | ||
| 992 | WREG32(0x657C, 0x80008008); | ||
| 993 | WREG32(0x6578, 0x20800); | ||
| 994 | WREG32(0x657C, 0x80108000); | ||
| 995 | WREG32(0x6578, 0x20801); | ||
| 996 | WREG32(0x657C, 0x8920BED0); | ||
| 997 | WREG32(0x6578, 0x20802); | ||
| 998 | WREG32(0x657C, 0xBED08920); | ||
| 999 | WREG32(0x6578, 0x20803); | ||
| 1000 | WREG32(0x657C, 0x80008010); | ||
| 1001 | WREG32(0x6578, 0x30000); | ||
| 1002 | WREG32(0x657C, 0x90008000); | ||
| 1003 | WREG32(0x6578, 0x30001); | ||
| 1004 | WREG32(0x657C, 0x80008000); | ||
| 1005 | WREG32(0x6578, 0x30100); | ||
| 1006 | WREG32(0x657C, 0x8FE0BF90); | ||
| 1007 | WREG32(0x6578, 0x30101); | ||
| 1008 | WREG32(0x657C, 0xBFF880A0); | ||
| 1009 | WREG32(0x6578, 0x30200); | ||
| 1010 | WREG32(0x657C, 0x8F60BF40); | ||
| 1011 | WREG32(0x6578, 0x30201); | ||
| 1012 | WREG32(0x657C, 0xBFE88180); | ||
| 1013 | WREG32(0x6578, 0x30300); | ||
| 1014 | WREG32(0x657C, 0x8EC0BF00); | ||
| 1015 | WREG32(0x6578, 0x30301); | ||
| 1016 | WREG32(0x657C, 0xBFC88280); | ||
| 1017 | WREG32(0x6578, 0x30400); | ||
| 1018 | WREG32(0x657C, 0x8DE0BEE0); | ||
| 1019 | WREG32(0x6578, 0x30401); | ||
| 1020 | WREG32(0x657C, 0xBFA083A0); | ||
| 1021 | WREG32(0x6578, 0x30500); | ||
| 1022 | WREG32(0x657C, 0x8CE0BED0); | ||
| 1023 | WREG32(0x6578, 0x30501); | ||
| 1024 | WREG32(0x657C, 0xBF7884E0); | ||
| 1025 | WREG32(0x6578, 0x30600); | ||
| 1026 | WREG32(0x657C, 0x8BA0BED8); | ||
| 1027 | WREG32(0x6578, 0x30601); | ||
| 1028 | WREG32(0x657C, 0xBF508640); | ||
| 1029 | WREG32(0x6578, 0x30700); | ||
| 1030 | WREG32(0x657C, 0x8A60BEE8); | ||
| 1031 | WREG32(0x6578, 0x30701); | ||
| 1032 | WREG32(0x657C, 0xBF2087A0); | ||
| 1033 | WREG32(0x6578, 0x30800); | ||
| 1034 | WREG32(0x657C, 0x8900BF00); | ||
| 1035 | WREG32(0x6578, 0x30801); | ||
| 1036 | WREG32(0x657C, 0xBF008900); | ||
| 1037 | } | ||
| 1038 | |||
| 1039 | static void | ||
| 1040 | atombios_yuv_setup(struct drm_encoder *encoder, bool enable) | ||
| 1041 | { | ||
| 1042 | struct drm_device *dev = encoder->dev; | ||
| 1043 | struct radeon_device *rdev = dev->dev_private; | ||
| 1044 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 1045 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
| 1046 | ENABLE_YUV_PS_ALLOCATION args; | ||
| 1047 | int index = GetIndexIntoMasterTable(COMMAND, EnableYUV); | ||
| 1048 | uint32_t temp, reg; | ||
| 1049 | |||
| 1050 | memset(&args, 0, sizeof(args)); | ||
| 1051 | |||
| 1052 | if (rdev->family >= CHIP_R600) | ||
| 1053 | reg = R600_BIOS_3_SCRATCH; | ||
| 1054 | else | ||
| 1055 | reg = RADEON_BIOS_3_SCRATCH; | ||
| 1056 | |||
| 1057 | /* XXX: fix up scratch reg handling */ | ||
| 1058 | temp = RREG32(reg); | ||
| 1059 | if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) | ||
| 1060 | WREG32(reg, (ATOM_S3_TV1_ACTIVE | | ||
| 1061 | (radeon_crtc->crtc_id << 18))); | ||
| 1062 | else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) | ||
| 1063 | WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24))); | ||
| 1064 | else | ||
| 1065 | WREG32(reg, 0); | ||
| 1066 | |||
| 1067 | if (enable) | ||
| 1068 | args.ucEnable = ATOM_ENABLE; | ||
| 1069 | args.ucCRTC = radeon_crtc->crtc_id; | ||
| 1070 | |||
| 1071 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 1072 | |||
| 1073 | WREG32(reg, temp); | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | static void | ||
| 1077 | atombios_overscan_setup(struct drm_encoder *encoder, | ||
| 1078 | struct drm_display_mode *mode, | ||
| 1079 | struct drm_display_mode *adjusted_mode) | ||
| 1080 | { | ||
| 1081 | struct drm_device *dev = encoder->dev; | ||
| 1082 | struct radeon_device *rdev = dev->dev_private; | ||
| 1083 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 1084 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
| 1085 | SET_CRTC_OVERSCAN_PS_ALLOCATION args; | ||
| 1086 | int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan); | ||
| 1087 | |||
| 1088 | memset(&args, 0, sizeof(args)); | ||
| 1089 | |||
| 1090 | args.usOverscanRight = 0; | ||
| 1091 | args.usOverscanLeft = 0; | ||
| 1092 | args.usOverscanBottom = 0; | ||
| 1093 | args.usOverscanTop = 0; | ||
| 1094 | args.ucCRTC = radeon_crtc->crtc_id; | ||
| 1095 | |||
| 1096 | if (radeon_encoder->flags & RADEON_USE_RMX) { | ||
| 1097 | if (radeon_encoder->rmx_type == RMX_FULL) { | ||
| 1098 | args.usOverscanRight = 0; | ||
| 1099 | args.usOverscanLeft = 0; | ||
| 1100 | args.usOverscanBottom = 0; | ||
| 1101 | args.usOverscanTop = 0; | ||
| 1102 | } else if (radeon_encoder->rmx_type == RMX_CENTER) { | ||
| 1103 | args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; | ||
| 1104 | args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; | ||
| 1105 | args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; | ||
| 1106 | args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; | ||
| 1107 | } else if (radeon_encoder->rmx_type == RMX_ASPECT) { | ||
| 1108 | int a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay; | ||
| 1109 | int a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay; | ||
| 1110 | |||
| 1111 | if (a1 > a2) { | ||
| 1112 | args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2; | ||
| 1113 | args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2; | ||
| 1114 | } else if (a2 > a1) { | ||
| 1115 | args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2; | ||
| 1116 | args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2; | ||
| 1117 | } | ||
| 1118 | } | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 1122 | |||
| 1123 | } | ||
| 1124 | |||
| 1125 | static void | ||
| 1126 | atombios_scaler_setup(struct drm_encoder *encoder) | ||
| 1127 | { | ||
| 1128 | struct drm_device *dev = encoder->dev; | ||
| 1129 | struct radeon_device *rdev = dev->dev_private; | ||
| 1130 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 1131 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
| 1132 | ENABLE_SCALER_PS_ALLOCATION args; | ||
| 1133 | int index = GetIndexIntoMasterTable(COMMAND, EnableScaler); | ||
| 1134 | /* fixme - fill in enc_priv for atom dac */ | ||
| 1135 | enum radeon_tv_std tv_std = TV_STD_NTSC; | ||
| 1136 | |||
| 1137 | if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id) | ||
| 1138 | return; | ||
| 1139 | |||
| 1140 | memset(&args, 0, sizeof(args)); | ||
| 1141 | |||
| 1142 | args.ucScaler = radeon_crtc->crtc_id; | ||
| 1143 | |||
| 1144 | if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) { | ||
| 1145 | switch (tv_std) { | ||
| 1146 | case TV_STD_NTSC: | ||
| 1147 | default: | ||
| 1148 | args.ucTVStandard = ATOM_TV_NTSC; | ||
| 1149 | break; | ||
| 1150 | case TV_STD_PAL: | ||
| 1151 | args.ucTVStandard = ATOM_TV_PAL; | ||
| 1152 | break; | ||
| 1153 | case TV_STD_PAL_M: | ||
| 1154 | args.ucTVStandard = ATOM_TV_PALM; | ||
| 1155 | break; | ||
| 1156 | case TV_STD_PAL_60: | ||
| 1157 | args.ucTVStandard = ATOM_TV_PAL60; | ||
| 1158 | break; | ||
| 1159 | case TV_STD_NTSC_J: | ||
| 1160 | args.ucTVStandard = ATOM_TV_NTSCJ; | ||
| 1161 | break; | ||
| 1162 | case TV_STD_SCART_PAL: | ||
| 1163 | args.ucTVStandard = ATOM_TV_PAL; /* ??? */ | ||
| 1164 | break; | ||
| 1165 | case TV_STD_SECAM: | ||
| 1166 | args.ucTVStandard = ATOM_TV_SECAM; | ||
| 1167 | break; | ||
| 1168 | case TV_STD_PAL_CN: | ||
| 1169 | args.ucTVStandard = ATOM_TV_PALCN; | ||
| 1170 | break; | ||
| 1171 | } | ||
| 1172 | args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; | ||
| 1173 | } else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) { | ||
| 1174 | args.ucTVStandard = ATOM_TV_CV; | ||
| 1175 | args.ucEnable = SCALER_ENABLE_MULTITAP_MODE; | ||
| 1176 | } else if (radeon_encoder->flags & RADEON_USE_RMX) { | ||
| 1177 | if (radeon_encoder->rmx_type == RMX_FULL) | ||
| 1178 | args.ucEnable = ATOM_SCALER_EXPANSION; | ||
| 1179 | else if (radeon_encoder->rmx_type == RMX_CENTER) | ||
| 1180 | args.ucEnable = ATOM_SCALER_CENTER; | ||
| 1181 | else if (radeon_encoder->rmx_type == RMX_ASPECT) | ||
| 1182 | args.ucEnable = ATOM_SCALER_EXPANSION; | ||
| 1183 | } else { | ||
| 1184 | if (ASIC_IS_AVIVO(rdev)) | ||
| 1185 | args.ucEnable = ATOM_SCALER_DISABLE; | ||
| 1186 | else | ||
| 1187 | args.ucEnable = ATOM_SCALER_CENTER; | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 1191 | |||
| 1192 | if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT) | ||
| 1193 | && rdev->family >= CHIP_RV515 && rdev->family <= CHIP_RV570) { | ||
| 1194 | atom_rv515_force_tv_scaler(rdev); | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | } | ||
| 1198 | |||
| 1199 | static void | ||
| 1200 | radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) | ||
| 1201 | { | ||
| 1202 | struct drm_device *dev = encoder->dev; | ||
| 1203 | struct radeon_device *rdev = dev->dev_private; | ||
| 1204 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 1205 | DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args; | ||
| 1206 | int index = 0; | ||
| 1207 | bool is_dig = false; | ||
| 1208 | |||
| 1209 | memset(&args, 0, sizeof(args)); | ||
| 1210 | |||
| 1211 | switch (radeon_encoder->encoder_id) { | ||
| 1212 | case ENCODER_OBJECT_ID_INTERNAL_TMDS1: | ||
| 1213 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: | ||
| 1214 | index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl); | ||
| 1215 | break; | ||
| 1216 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | ||
| 1217 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | ||
| 1218 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | ||
| 1219 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
| 1220 | is_dig = true; | ||
| 1221 | break; | ||
| 1222 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: | ||
| 1223 | case ENCODER_OBJECT_ID_INTERNAL_DDI: | ||
| 1224 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | ||
| 1225 | index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl); | ||
| 1226 | break; | ||
| 1227 | case ENCODER_OBJECT_ID_INTERNAL_LVDS: | ||
| 1228 | index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); | ||
| 1229 | break; | ||
| 1230 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: | ||
| 1231 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) | ||
| 1232 | index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl); | ||
| 1233 | else | ||
| 1234 | index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl); | ||
| 1235 | break; | ||
| 1236 | case ENCODER_OBJECT_ID_INTERNAL_DAC1: | ||
| 1237 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: | ||
| 1238 | if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) | ||
| 1239 | index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); | ||
| 1240 | else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) | ||
| 1241 | index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); | ||
| 1242 | else | ||
| 1243 | index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); | ||
| 1244 | break; | ||
| 1245 | case ENCODER_OBJECT_ID_INTERNAL_DAC2: | ||
| 1246 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: | ||
| 1247 | if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) | ||
| 1248 | index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); | ||
| 1249 | else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) | ||
| 1250 | index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); | ||
| 1251 | else | ||
| 1252 | index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); | ||
| 1253 | break; | ||
| 1254 | } | ||
| 1255 | |||
| 1256 | if (is_dig) { | ||
| 1257 | switch (mode) { | ||
| 1258 | case DRM_MODE_DPMS_ON: | ||
| 1259 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE); | ||
| 1260 | break; | ||
| 1261 | case DRM_MODE_DPMS_STANDBY: | ||
| 1262 | case DRM_MODE_DPMS_SUSPEND: | ||
| 1263 | case DRM_MODE_DPMS_OFF: | ||
| 1264 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE); | ||
| 1265 | break; | ||
| 1266 | } | ||
| 1267 | } else { | ||
| 1268 | switch (mode) { | ||
| 1269 | case DRM_MODE_DPMS_ON: | ||
| 1270 | args.ucAction = ATOM_ENABLE; | ||
| 1271 | break; | ||
| 1272 | case DRM_MODE_DPMS_STANDBY: | ||
| 1273 | case DRM_MODE_DPMS_SUSPEND: | ||
| 1274 | case DRM_MODE_DPMS_OFF: | ||
| 1275 | args.ucAction = ATOM_DISABLE; | ||
| 1276 | break; | ||
| 1277 | } | ||
| 1278 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 1279 | } | ||
| 1280 | radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | union crtc_sourc_param { | ||
| 1284 | SELECT_CRTC_SOURCE_PS_ALLOCATION v1; | ||
| 1285 | SELECT_CRTC_SOURCE_PARAMETERS_V2 v2; | ||
| 1286 | }; | ||
| 1287 | |||
| 1288 | static void | ||
| 1289 | atombios_set_encoder_crtc_source(struct drm_encoder *encoder) | ||
| 1290 | { | ||
| 1291 | struct drm_device *dev = encoder->dev; | ||
| 1292 | struct radeon_device *rdev = dev->dev_private; | ||
| 1293 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 1294 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
| 1295 | union crtc_sourc_param args; | ||
| 1296 | int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source); | ||
| 1297 | uint8_t frev, crev; | ||
| 1298 | |||
| 1299 | memset(&args, 0, sizeof(args)); | ||
| 1300 | |||
| 1301 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); | ||
| 1302 | |||
| 1303 | switch (frev) { | ||
| 1304 | case 1: | ||
| 1305 | switch (crev) { | ||
| 1306 | case 1: | ||
| 1307 | default: | ||
| 1308 | if (ASIC_IS_AVIVO(rdev)) | ||
| 1309 | args.v1.ucCRTC = radeon_crtc->crtc_id; | ||
| 1310 | else { | ||
| 1311 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) { | ||
| 1312 | args.v1.ucCRTC = radeon_crtc->crtc_id; | ||
| 1313 | } else { | ||
| 1314 | args.v1.ucCRTC = radeon_crtc->crtc_id << 2; | ||
| 1315 | } | ||
| 1316 | } | ||
| 1317 | switch (radeon_encoder->encoder_id) { | ||
| 1318 | case ENCODER_OBJECT_ID_INTERNAL_TMDS1: | ||
| 1319 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: | ||
| 1320 | args.v1.ucDevice = ATOM_DEVICE_DFP1_INDEX; | ||
| 1321 | break; | ||
| 1322 | case ENCODER_OBJECT_ID_INTERNAL_LVDS: | ||
| 1323 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: | ||
| 1324 | if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) | ||
| 1325 | args.v1.ucDevice = ATOM_DEVICE_LCD1_INDEX; | ||
| 1326 | else | ||
| 1327 | args.v1.ucDevice = ATOM_DEVICE_DFP3_INDEX; | ||
| 1328 | break; | ||
| 1329 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: | ||
| 1330 | case ENCODER_OBJECT_ID_INTERNAL_DDI: | ||
| 1331 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | ||
| 1332 | args.v1.ucDevice = ATOM_DEVICE_DFP2_INDEX; | ||
| 1333 | break; | ||
| 1334 | case ENCODER_OBJECT_ID_INTERNAL_DAC1: | ||
| 1335 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: | ||
| 1336 | if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) | ||
| 1337 | args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; | ||
| 1338 | else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) | ||
| 1339 | args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; | ||
| 1340 | else | ||
| 1341 | args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX; | ||
| 1342 | break; | ||
| 1343 | case ENCODER_OBJECT_ID_INTERNAL_DAC2: | ||
| 1344 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: | ||
| 1345 | if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) | ||
| 1346 | args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX; | ||
| 1347 | else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) | ||
| 1348 | args.v1.ucDevice = ATOM_DEVICE_CV_INDEX; | ||
| 1349 | else | ||
| 1350 | args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX; | ||
| 1351 | break; | ||
| 1352 | } | ||
| 1353 | break; | ||
| 1354 | case 2: | ||
| 1355 | args.v2.ucCRTC = radeon_crtc->crtc_id; | ||
| 1356 | args.v2.ucEncodeMode = atombios_get_encoder_mode(encoder); | ||
| 1357 | switch (radeon_encoder->encoder_id) { | ||
| 1358 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | ||
| 1359 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | ||
| 1360 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | ||
| 1361 | if (ASIC_IS_DCE32(rdev)) { | ||
| 1362 | if (radeon_crtc->crtc_id) | ||
| 1363 | args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; | ||
| 1364 | else | ||
| 1365 | args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; | ||
| 1366 | } else | ||
| 1367 | args.v2.ucEncoderID = ASIC_INT_DIG1_ENCODER_ID; | ||
| 1368 | break; | ||
| 1369 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | ||
| 1370 | args.v2.ucEncoderID = ASIC_INT_DVO_ENCODER_ID; | ||
| 1371 | break; | ||
| 1372 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
| 1373 | args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID; | ||
| 1374 | break; | ||
| 1375 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: | ||
| 1376 | if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) | ||
| 1377 | args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; | ||
| 1378 | else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) | ||
| 1379 | args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; | ||
| 1380 | else | ||
| 1381 | args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID; | ||
| 1382 | break; | ||
| 1383 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: | ||
| 1384 | if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) | ||
| 1385 | args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; | ||
| 1386 | else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) | ||
| 1387 | args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID; | ||
| 1388 | else | ||
| 1389 | args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID; | ||
| 1390 | break; | ||
| 1391 | } | ||
| 1392 | break; | ||
| 1393 | } | ||
| 1394 | break; | ||
| 1395 | default: | ||
| 1396 | DRM_ERROR("Unknown table version: %d, %d\n", frev, crev); | ||
| 1397 | break; | ||
| 1398 | } | ||
| 1399 | |||
| 1400 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 1401 | |||
| 1402 | } | ||
| 1403 | |||
| 1404 | static void | ||
| 1405 | atombios_apply_encoder_quirks(struct drm_encoder *encoder, | ||
| 1406 | struct drm_display_mode *mode) | ||
| 1407 | { | ||
| 1408 | struct drm_device *dev = encoder->dev; | ||
| 1409 | struct radeon_device *rdev = dev->dev_private; | ||
| 1410 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 1411 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
| 1412 | |||
| 1413 | /* Funky macbooks */ | ||
| 1414 | if ((dev->pdev->device == 0x71C5) && | ||
| 1415 | (dev->pdev->subsystem_vendor == 0x106b) && | ||
| 1416 | (dev->pdev->subsystem_device == 0x0080)) { | ||
| 1417 | if (radeon_encoder->devices & ATOM_DEVICE_LCD1_SUPPORT) { | ||
| 1418 | uint32_t lvtma_bit_depth_control = RREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL); | ||
| 1419 | |||
| 1420 | lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_TRUNCATE_EN; | ||
| 1421 | lvtma_bit_depth_control &= ~AVIVO_LVTMA_BIT_DEPTH_CONTROL_SPATIAL_DITHER_EN; | ||
| 1422 | |||
| 1423 | WREG32(AVIVO_LVTMA_BIT_DEPTH_CONTROL, lvtma_bit_depth_control); | ||
| 1424 | } | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | /* set scaler clears this on some chips */ | ||
| 1428 | if (ASIC_IS_AVIVO(rdev) && (mode->flags & DRM_MODE_FLAG_INTERLACE)) | ||
| 1429 | WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, AVIVO_D1MODE_INTERLEAVE_EN); | ||
| 1430 | } | ||
| 1431 | |||
| 1432 | static void | ||
| 1433 | radeon_atom_encoder_mode_set(struct drm_encoder *encoder, | ||
| 1434 | struct drm_display_mode *mode, | ||
| 1435 | struct drm_display_mode *adjusted_mode) | ||
| 1436 | { | ||
| 1437 | struct drm_device *dev = encoder->dev; | ||
| 1438 | struct radeon_device *rdev = dev->dev_private; | ||
| 1439 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 1440 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
| 1441 | |||
| 1442 | if (radeon_encoder->enc_priv) { | ||
| 1443 | struct radeon_encoder_atom_dig *dig; | ||
| 1444 | |||
| 1445 | dig = radeon_encoder->enc_priv; | ||
| 1446 | dig->dig_block = radeon_crtc->crtc_id; | ||
| 1447 | } | ||
| 1448 | radeon_encoder->pixel_clock = adjusted_mode->clock; | ||
| 1449 | |||
| 1450 | radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | ||
| 1451 | atombios_overscan_setup(encoder, mode, adjusted_mode); | ||
| 1452 | atombios_scaler_setup(encoder); | ||
| 1453 | atombios_set_encoder_crtc_source(encoder); | ||
| 1454 | |||
| 1455 | if (ASIC_IS_AVIVO(rdev)) { | ||
| 1456 | if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) | ||
| 1457 | atombios_yuv_setup(encoder, true); | ||
| 1458 | else | ||
| 1459 | atombios_yuv_setup(encoder, false); | ||
| 1460 | } | ||
| 1461 | |||
| 1462 | switch (radeon_encoder->encoder_id) { | ||
| 1463 | case ENCODER_OBJECT_ID_INTERNAL_TMDS1: | ||
| 1464 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: | ||
| 1465 | case ENCODER_OBJECT_ID_INTERNAL_LVDS: | ||
| 1466 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: | ||
| 1467 | atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE); | ||
| 1468 | break; | ||
| 1469 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | ||
| 1470 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | ||
| 1471 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | ||
| 1472 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
| 1473 | /* disable the encoder and transmitter */ | ||
| 1474 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE); | ||
| 1475 | atombios_dig_encoder_setup(encoder, ATOM_DISABLE); | ||
| 1476 | |||
| 1477 | /* setup and enable the encoder and transmitter */ | ||
| 1478 | atombios_dig_encoder_setup(encoder, ATOM_ENABLE); | ||
| 1479 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP); | ||
| 1480 | atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE); | ||
| 1481 | break; | ||
| 1482 | case ENCODER_OBJECT_ID_INTERNAL_DDI: | ||
| 1483 | atombios_ddia_setup(encoder, ATOM_ENABLE); | ||
| 1484 | break; | ||
| 1485 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: | ||
| 1486 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | ||
| 1487 | atombios_external_tmds_setup(encoder, ATOM_ENABLE); | ||
| 1488 | break; | ||
| 1489 | case ENCODER_OBJECT_ID_INTERNAL_DAC1: | ||
| 1490 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: | ||
| 1491 | case ENCODER_OBJECT_ID_INTERNAL_DAC2: | ||
| 1492 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: | ||
| 1493 | atombios_dac_setup(encoder, ATOM_ENABLE); | ||
| 1494 | if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT)) | ||
| 1495 | atombios_tv_setup(encoder, ATOM_ENABLE); | ||
| 1496 | break; | ||
| 1497 | } | ||
| 1498 | atombios_apply_encoder_quirks(encoder, adjusted_mode); | ||
| 1499 | } | ||
| 1500 | |||
| 1501 | static bool | ||
| 1502 | atombios_dac_load_detect(struct drm_encoder *encoder) | ||
| 1503 | { | ||
| 1504 | struct drm_device *dev = encoder->dev; | ||
| 1505 | struct radeon_device *rdev = dev->dev_private; | ||
| 1506 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 1507 | |||
| 1508 | if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | | ||
| 1509 | ATOM_DEVICE_CV_SUPPORT | | ||
| 1510 | ATOM_DEVICE_CRT_SUPPORT)) { | ||
| 1511 | DAC_LOAD_DETECTION_PS_ALLOCATION args; | ||
| 1512 | int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection); | ||
| 1513 | uint8_t frev, crev; | ||
| 1514 | |||
| 1515 | memset(&args, 0, sizeof(args)); | ||
| 1516 | |||
| 1517 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev); | ||
| 1518 | |||
| 1519 | args.sDacload.ucMisc = 0; | ||
| 1520 | |||
| 1521 | if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_DAC1) || | ||
| 1522 | (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1)) | ||
| 1523 | args.sDacload.ucDacType = ATOM_DAC_A; | ||
| 1524 | else | ||
| 1525 | args.sDacload.ucDacType = ATOM_DAC_B; | ||
| 1526 | |||
| 1527 | if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) | ||
| 1528 | args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT); | ||
| 1529 | else if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) | ||
| 1530 | args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT); | ||
| 1531 | else if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) { | ||
| 1532 | args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT); | ||
| 1533 | if (crev >= 3) | ||
| 1534 | args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; | ||
| 1535 | } else if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) { | ||
| 1536 | args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT); | ||
| 1537 | if (crev >= 3) | ||
| 1538 | args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb; | ||
| 1539 | } | ||
| 1540 | |||
| 1541 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | ||
| 1542 | |||
| 1543 | return true; | ||
| 1544 | } else | ||
| 1545 | return false; | ||
| 1546 | } | ||
| 1547 | |||
| 1548 | static enum drm_connector_status | ||
| 1549 | radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) | ||
| 1550 | { | ||
| 1551 | struct drm_device *dev = encoder->dev; | ||
| 1552 | struct radeon_device *rdev = dev->dev_private; | ||
| 1553 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 1554 | uint32_t bios_0_scratch; | ||
| 1555 | |||
| 1556 | if (!atombios_dac_load_detect(encoder)) { | ||
| 1557 | DRM_DEBUG("detect returned false \n"); | ||
| 1558 | return connector_status_unknown; | ||
| 1559 | } | ||
| 1560 | |||
| 1561 | if (rdev->family >= CHIP_R600) | ||
| 1562 | bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); | ||
| 1563 | else | ||
| 1564 | bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH); | ||
| 1565 | |||
| 1566 | DRM_DEBUG("Bios 0 scratch %x\n", bios_0_scratch); | ||
| 1567 | if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) { | ||
| 1568 | if (bios_0_scratch & ATOM_S0_CRT1_MASK) | ||
| 1569 | return connector_status_connected; | ||
| 1570 | } else if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) { | ||
| 1571 | if (bios_0_scratch & ATOM_S0_CRT2_MASK) | ||
| 1572 | return connector_status_connected; | ||
| 1573 | } else if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) { | ||
| 1574 | if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) | ||
| 1575 | return connector_status_connected; | ||
| 1576 | } else if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) { | ||
| 1577 | if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) | ||
| 1578 | return connector_status_connected; /* CTV */ | ||
| 1579 | else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) | ||
| 1580 | return connector_status_connected; /* STV */ | ||
| 1581 | } | ||
| 1582 | return connector_status_disconnected; | ||
| 1583 | } | ||
| 1584 | |||
| 1585 | static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) | ||
| 1586 | { | ||
| 1587 | radeon_atom_output_lock(encoder, true); | ||
| 1588 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); | ||
| 1589 | } | ||
| 1590 | |||
| 1591 | static void radeon_atom_encoder_commit(struct drm_encoder *encoder) | ||
| 1592 | { | ||
| 1593 | radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON); | ||
| 1594 | radeon_atom_output_lock(encoder, false); | ||
| 1595 | } | ||
| 1596 | |||
| 1597 | static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = { | ||
| 1598 | .dpms = radeon_atom_encoder_dpms, | ||
| 1599 | .mode_fixup = radeon_atom_mode_fixup, | ||
| 1600 | .prepare = radeon_atom_encoder_prepare, | ||
| 1601 | .mode_set = radeon_atom_encoder_mode_set, | ||
| 1602 | .commit = radeon_atom_encoder_commit, | ||
| 1603 | /* no detect for TMDS/LVDS yet */ | ||
| 1604 | }; | ||
| 1605 | |||
| 1606 | static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = { | ||
| 1607 | .dpms = radeon_atom_encoder_dpms, | ||
| 1608 | .mode_fixup = radeon_atom_mode_fixup, | ||
| 1609 | .prepare = radeon_atom_encoder_prepare, | ||
| 1610 | .mode_set = radeon_atom_encoder_mode_set, | ||
| 1611 | .commit = radeon_atom_encoder_commit, | ||
| 1612 | .detect = radeon_atom_dac_detect, | ||
| 1613 | }; | ||
| 1614 | |||
| 1615 | void radeon_enc_destroy(struct drm_encoder *encoder) | ||
| 1616 | { | ||
| 1617 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 1618 | kfree(radeon_encoder->enc_priv); | ||
| 1619 | drm_encoder_cleanup(encoder); | ||
| 1620 | kfree(radeon_encoder); | ||
| 1621 | } | ||
| 1622 | |||
| 1623 | static const struct drm_encoder_funcs radeon_atom_enc_funcs = { | ||
| 1624 | .destroy = radeon_enc_destroy, | ||
| 1625 | }; | ||
| 1626 | |||
| 1627 | struct radeon_encoder_atom_dig * | ||
| 1628 | radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder) | ||
| 1629 | { | ||
| 1630 | struct radeon_encoder_atom_dig *dig = kzalloc(sizeof(struct radeon_encoder_atom_dig), GFP_KERNEL); | ||
| 1631 | |||
| 1632 | if (!dig) | ||
| 1633 | return NULL; | ||
| 1634 | |||
| 1635 | /* coherent mode by default */ | ||
| 1636 | dig->coherent_mode = true; | ||
| 1637 | |||
| 1638 | return dig; | ||
| 1639 | } | ||
| 1640 | |||
| 1641 | void | ||
| 1642 | radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device) | ||
| 1643 | { | ||
| 1644 | struct drm_encoder *encoder; | ||
| 1645 | struct radeon_encoder *radeon_encoder; | ||
| 1646 | |||
| 1647 | /* see if we already added it */ | ||
| 1648 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 1649 | radeon_encoder = to_radeon_encoder(encoder); | ||
| 1650 | if (radeon_encoder->encoder_id == encoder_id) { | ||
| 1651 | radeon_encoder->devices |= supported_device; | ||
| 1652 | return; | ||
| 1653 | } | ||
| 1654 | |||
| 1655 | } | ||
| 1656 | |||
| 1657 | /* add a new one */ | ||
| 1658 | radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); | ||
| 1659 | if (!radeon_encoder) | ||
| 1660 | return; | ||
| 1661 | |||
| 1662 | encoder = &radeon_encoder->base; | ||
| 1663 | encoder->possible_crtcs = 0x3; | ||
| 1664 | encoder->possible_clones = 0; | ||
| 1665 | |||
| 1666 | radeon_encoder->enc_priv = NULL; | ||
| 1667 | |||
| 1668 | radeon_encoder->encoder_id = encoder_id; | ||
| 1669 | radeon_encoder->devices = supported_device; | ||
| 1670 | |||
| 1671 | switch (radeon_encoder->encoder_id) { | ||
| 1672 | case ENCODER_OBJECT_ID_INTERNAL_LVDS: | ||
| 1673 | case ENCODER_OBJECT_ID_INTERNAL_TMDS1: | ||
| 1674 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: | ||
| 1675 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: | ||
| 1676 | if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { | ||
| 1677 | radeon_encoder->rmx_type = RMX_FULL; | ||
| 1678 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS); | ||
| 1679 | radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); | ||
| 1680 | } else { | ||
| 1681 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); | ||
| 1682 | radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); | ||
| 1683 | } | ||
| 1684 | drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); | ||
| 1685 | break; | ||
| 1686 | case ENCODER_OBJECT_ID_INTERNAL_DAC1: | ||
| 1687 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_DAC); | ||
| 1688 | drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); | ||
| 1689 | break; | ||
| 1690 | case ENCODER_OBJECT_ID_INTERNAL_DAC2: | ||
| 1691 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: | ||
| 1692 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: | ||
| 1693 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC); | ||
| 1694 | drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs); | ||
| 1695 | break; | ||
| 1696 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: | ||
| 1697 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | ||
| 1698 | case ENCODER_OBJECT_ID_INTERNAL_DDI: | ||
| 1699 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: | ||
| 1700 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: | ||
| 1701 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: | ||
| 1702 | case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: | ||
| 1703 | drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS); | ||
| 1704 | radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder); | ||
| 1705 | drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs); | ||
| 1706 | break; | ||
| 1707 | } | ||
| 1708 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c new file mode 100644 index 000000000000..fa86d398945e --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_fb.c | |||
| @@ -0,0 +1,825 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2007 David Airlie | ||
| 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 (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 21 | * DEALINGS IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * David Airlie | ||
| 25 | */ | ||
| 26 | /* | ||
| 27 | * Modularization | ||
| 28 | */ | ||
| 29 | |||
| 30 | #include <linux/module.h> | ||
| 31 | #include <linux/kernel.h> | ||
| 32 | #include <linux/errno.h> | ||
| 33 | #include <linux/string.h> | ||
| 34 | #include <linux/mm.h> | ||
| 35 | #include <linux/tty.h> | ||
| 36 | #include <linux/slab.h> | ||
| 37 | #include <linux/delay.h> | ||
| 38 | #include <linux/fb.h> | ||
| 39 | #include <linux/init.h> | ||
| 40 | |||
| 41 | #include "drmP.h" | ||
| 42 | #include "drm.h" | ||
| 43 | #include "drm_crtc.h" | ||
| 44 | #include "drm_crtc_helper.h" | ||
| 45 | #include "radeon_drm.h" | ||
| 46 | #include "radeon.h" | ||
| 47 | |||
| 48 | struct radeon_fb_device { | ||
| 49 | struct radeon_device *rdev; | ||
| 50 | struct drm_display_mode *mode; | ||
| 51 | struct radeon_framebuffer *rfb; | ||
| 52 | int crtc_count; | ||
| 53 | /* crtc currently bound to this */ | ||
| 54 | uint32_t crtc_ids[2]; | ||
| 55 | }; | ||
| 56 | |||
| 57 | static int radeonfb_setcolreg(unsigned regno, | ||
| 58 | unsigned red, | ||
| 59 | unsigned green, | ||
| 60 | unsigned blue, | ||
| 61 | unsigned transp, | ||
| 62 | struct fb_info *info) | ||
| 63 | { | ||
| 64 | struct radeon_fb_device *rfbdev = info->par; | ||
| 65 | struct drm_device *dev = rfbdev->rdev->ddev; | ||
| 66 | struct drm_crtc *crtc; | ||
| 67 | int i; | ||
| 68 | |||
| 69 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
| 70 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 71 | struct drm_mode_set *modeset = &radeon_crtc->mode_set; | ||
| 72 | struct drm_framebuffer *fb = modeset->fb; | ||
| 73 | |||
| 74 | for (i = 0; i < rfbdev->crtc_count; i++) { | ||
| 75 | if (crtc->base.id == rfbdev->crtc_ids[i]) { | ||
| 76 | break; | ||
| 77 | } | ||
| 78 | } | ||
| 79 | if (i == rfbdev->crtc_count) { | ||
| 80 | continue; | ||
| 81 | } | ||
| 82 | if (regno > 255) { | ||
| 83 | return 1; | ||
| 84 | } | ||
| 85 | if (fb->depth == 8) { | ||
| 86 | radeon_crtc_fb_gamma_set(crtc, red, green, blue, regno); | ||
| 87 | return 0; | ||
| 88 | } | ||
| 89 | |||
| 90 | if (regno < 16) { | ||
| 91 | switch (fb->depth) { | ||
| 92 | case 15: | ||
| 93 | fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) | | ||
| 94 | ((green & 0xf800) >> 6) | | ||
| 95 | ((blue & 0xf800) >> 11); | ||
| 96 | break; | ||
| 97 | case 16: | ||
| 98 | fb->pseudo_palette[regno] = (red & 0xf800) | | ||
| 99 | ((green & 0xfc00) >> 5) | | ||
| 100 | ((blue & 0xf800) >> 11); | ||
| 101 | break; | ||
| 102 | case 24: | ||
| 103 | case 32: | ||
| 104 | fb->pseudo_palette[regno] = ((red & 0xff00) << 8) | | ||
| 105 | (green & 0xff00) | | ||
| 106 | ((blue & 0xff00) >> 8); | ||
| 107 | break; | ||
| 108 | } | ||
| 109 | } | ||
| 110 | } | ||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | static int radeonfb_check_var(struct fb_var_screeninfo *var, | ||
| 115 | struct fb_info *info) | ||
| 116 | { | ||
| 117 | struct radeon_fb_device *rfbdev = info->par; | ||
| 118 | struct radeon_framebuffer *rfb = rfbdev->rfb; | ||
| 119 | struct drm_framebuffer *fb = &rfb->base; | ||
| 120 | int depth; | ||
| 121 | |||
| 122 | if (var->pixclock == -1 || !var->pixclock) { | ||
| 123 | return -EINVAL; | ||
| 124 | } | ||
| 125 | /* Need to resize the fb object !!! */ | ||
| 126 | if (var->xres > fb->width || var->yres > fb->height) { | ||
| 127 | DRM_ERROR("Requested width/height is greater than current fb " | ||
| 128 | "object %dx%d > %dx%d\n", var->xres, var->yres, | ||
| 129 | fb->width, fb->height); | ||
| 130 | DRM_ERROR("Need resizing code.\n"); | ||
| 131 | return -EINVAL; | ||
| 132 | } | ||
| 133 | |||
| 134 | switch (var->bits_per_pixel) { | ||
| 135 | case 16: | ||
| 136 | depth = (var->green.length == 6) ? 16 : 15; | ||
| 137 | break; | ||
| 138 | case 32: | ||
| 139 | depth = (var->transp.length > 0) ? 32 : 24; | ||
| 140 | break; | ||
| 141 | default: | ||
| 142 | depth = var->bits_per_pixel; | ||
| 143 | break; | ||
| 144 | } | ||
| 145 | |||
| 146 | switch (depth) { | ||
| 147 | case 8: | ||
| 148 | var->red.offset = 0; | ||
| 149 | var->green.offset = 0; | ||
| 150 | var->blue.offset = 0; | ||
| 151 | var->red.length = 8; | ||
| 152 | var->green.length = 8; | ||
| 153 | var->blue.length = 8; | ||
| 154 | var->transp.length = 0; | ||
| 155 | var->transp.offset = 0; | ||
| 156 | break; | ||
| 157 | case 15: | ||
| 158 | var->red.offset = 10; | ||
| 159 | var->green.offset = 5; | ||
| 160 | var->blue.offset = 0; | ||
| 161 | var->red.length = 5; | ||
| 162 | var->green.length = 5; | ||
| 163 | var->blue.length = 5; | ||
| 164 | var->transp.length = 1; | ||
| 165 | var->transp.offset = 15; | ||
| 166 | break; | ||
| 167 | case 16: | ||
| 168 | var->red.offset = 11; | ||
| 169 | var->green.offset = 5; | ||
| 170 | var->blue.offset = 0; | ||
| 171 | var->red.length = 5; | ||
| 172 | var->green.length = 6; | ||
| 173 | var->blue.length = 5; | ||
| 174 | var->transp.length = 0; | ||
| 175 | var->transp.offset = 0; | ||
| 176 | break; | ||
| 177 | case 24: | ||
| 178 | var->red.offset = 16; | ||
| 179 | var->green.offset = 8; | ||
| 180 | var->blue.offset = 0; | ||
| 181 | var->red.length = 8; | ||
| 182 | var->green.length = 8; | ||
| 183 | var->blue.length = 8; | ||
| 184 | var->transp.length = 0; | ||
| 185 | var->transp.offset = 0; | ||
| 186 | break; | ||
| 187 | case 32: | ||
| 188 | var->red.offset = 16; | ||
| 189 | var->green.offset = 8; | ||
| 190 | var->blue.offset = 0; | ||
| 191 | var->red.length = 8; | ||
| 192 | var->green.length = 8; | ||
| 193 | var->blue.length = 8; | ||
| 194 | var->transp.length = 8; | ||
| 195 | var->transp.offset = 24; | ||
| 196 | break; | ||
| 197 | default: | ||
| 198 | return -EINVAL; | ||
| 199 | } | ||
| 200 | return 0; | ||
| 201 | } | ||
| 202 | |||
| 203 | /* this will let fbcon do the mode init */ | ||
| 204 | static int radeonfb_set_par(struct fb_info *info) | ||
| 205 | { | ||
| 206 | struct radeon_fb_device *rfbdev = info->par; | ||
| 207 | struct drm_device *dev = rfbdev->rdev->ddev; | ||
| 208 | struct fb_var_screeninfo *var = &info->var; | ||
| 209 | struct drm_crtc *crtc; | ||
| 210 | int ret; | ||
| 211 | int i; | ||
| 212 | |||
| 213 | if (var->pixclock != -1) { | ||
| 214 | DRM_ERROR("PIXEL CLCOK SET\n"); | ||
| 215 | return -EINVAL; | ||
| 216 | } | ||
| 217 | |||
| 218 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
| 219 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 220 | |||
| 221 | for (i = 0; i < rfbdev->crtc_count; i++) { | ||
| 222 | if (crtc->base.id == rfbdev->crtc_ids[i]) { | ||
| 223 | break; | ||
| 224 | } | ||
| 225 | } | ||
| 226 | if (i == rfbdev->crtc_count) { | ||
| 227 | continue; | ||
| 228 | } | ||
| 229 | if (crtc->fb == radeon_crtc->mode_set.fb) { | ||
| 230 | mutex_lock(&dev->mode_config.mutex); | ||
| 231 | ret = crtc->funcs->set_config(&radeon_crtc->mode_set); | ||
| 232 | mutex_unlock(&dev->mode_config.mutex); | ||
| 233 | if (ret) { | ||
| 234 | return ret; | ||
| 235 | } | ||
| 236 | } | ||
| 237 | } | ||
| 238 | return 0; | ||
| 239 | } | ||
| 240 | |||
| 241 | static int radeonfb_pan_display(struct fb_var_screeninfo *var, | ||
| 242 | struct fb_info *info) | ||
| 243 | { | ||
| 244 | struct radeon_fb_device *rfbdev = info->par; | ||
| 245 | struct drm_device *dev = rfbdev->rdev->ddev; | ||
| 246 | struct drm_mode_set *modeset; | ||
| 247 | struct drm_crtc *crtc; | ||
| 248 | struct radeon_crtc *radeon_crtc; | ||
| 249 | int ret = 0; | ||
| 250 | int i; | ||
| 251 | |||
| 252 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
| 253 | for (i = 0; i < rfbdev->crtc_count; i++) { | ||
| 254 | if (crtc->base.id == rfbdev->crtc_ids[i]) { | ||
| 255 | break; | ||
| 256 | } | ||
| 257 | } | ||
| 258 | |||
| 259 | if (i == rfbdev->crtc_count) { | ||
| 260 | continue; | ||
| 261 | } | ||
| 262 | |||
| 263 | radeon_crtc = to_radeon_crtc(crtc); | ||
| 264 | modeset = &radeon_crtc->mode_set; | ||
| 265 | |||
| 266 | modeset->x = var->xoffset; | ||
| 267 | modeset->y = var->yoffset; | ||
| 268 | |||
| 269 | if (modeset->num_connectors) { | ||
| 270 | mutex_lock(&dev->mode_config.mutex); | ||
| 271 | ret = crtc->funcs->set_config(modeset); | ||
| 272 | mutex_unlock(&dev->mode_config.mutex); | ||
| 273 | if (!ret) { | ||
| 274 | info->var.xoffset = var->xoffset; | ||
| 275 | info->var.yoffset = var->yoffset; | ||
| 276 | } | ||
| 277 | } | ||
| 278 | } | ||
| 279 | return ret; | ||
| 280 | } | ||
| 281 | |||
| 282 | static void radeonfb_on(struct fb_info *info) | ||
| 283 | { | ||
| 284 | struct radeon_fb_device *rfbdev = info->par; | ||
| 285 | struct drm_device *dev = rfbdev->rdev->ddev; | ||
| 286 | struct drm_crtc *crtc; | ||
| 287 | struct drm_encoder *encoder; | ||
| 288 | int i; | ||
| 289 | |||
| 290 | /* | ||
| 291 | * For each CRTC in this fb, find all associated encoders | ||
| 292 | * and turn them off, then turn off the CRTC. | ||
| 293 | */ | ||
| 294 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
| 295 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
| 296 | |||
| 297 | for (i = 0; i < rfbdev->crtc_count; i++) { | ||
| 298 | if (crtc->base.id == rfbdev->crtc_ids[i]) { | ||
| 299 | break; | ||
| 300 | } | ||
| 301 | } | ||
| 302 | |||
| 303 | mutex_lock(&dev->mode_config.mutex); | ||
| 304 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); | ||
| 305 | mutex_unlock(&dev->mode_config.mutex); | ||
| 306 | |||
| 307 | /* Found a CRTC on this fb, now find encoders */ | ||
| 308 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 309 | if (encoder->crtc == crtc) { | ||
| 310 | struct drm_encoder_helper_funcs *encoder_funcs; | ||
| 311 | |||
| 312 | encoder_funcs = encoder->helper_private; | ||
| 313 | mutex_lock(&dev->mode_config.mutex); | ||
| 314 | encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); | ||
| 315 | mutex_unlock(&dev->mode_config.mutex); | ||
| 316 | } | ||
| 317 | } | ||
| 318 | } | ||
| 319 | } | ||
| 320 | |||
| 321 | static void radeonfb_off(struct fb_info *info, int dpms_mode) | ||
| 322 | { | ||
| 323 | struct radeon_fb_device *rfbdev = info->par; | ||
| 324 | struct drm_device *dev = rfbdev->rdev->ddev; | ||
| 325 | struct drm_crtc *crtc; | ||
| 326 | struct drm_encoder *encoder; | ||
| 327 | int i; | ||
| 328 | |||
| 329 | /* | ||
| 330 | * For each CRTC in this fb, find all associated encoders | ||
| 331 | * and turn them off, then turn off the CRTC. | ||
| 332 | */ | ||
| 333 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
| 334 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
| 335 | |||
| 336 | for (i = 0; i < rfbdev->crtc_count; i++) { | ||
| 337 | if (crtc->base.id == rfbdev->crtc_ids[i]) { | ||
| 338 | break; | ||
| 339 | } | ||
| 340 | } | ||
| 341 | |||
| 342 | /* Found a CRTC on this fb, now find encoders */ | ||
| 343 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 344 | if (encoder->crtc == crtc) { | ||
| 345 | struct drm_encoder_helper_funcs *encoder_funcs; | ||
| 346 | |||
| 347 | encoder_funcs = encoder->helper_private; | ||
| 348 | mutex_lock(&dev->mode_config.mutex); | ||
| 349 | encoder_funcs->dpms(encoder, dpms_mode); | ||
| 350 | mutex_unlock(&dev->mode_config.mutex); | ||
| 351 | } | ||
| 352 | } | ||
| 353 | if (dpms_mode == DRM_MODE_DPMS_OFF) { | ||
| 354 | mutex_lock(&dev->mode_config.mutex); | ||
| 355 | crtc_funcs->dpms(crtc, dpms_mode); | ||
| 356 | mutex_unlock(&dev->mode_config.mutex); | ||
| 357 | } | ||
| 358 | } | ||
| 359 | } | ||
| 360 | |||
| 361 | int radeonfb_blank(int blank, struct fb_info *info) | ||
| 362 | { | ||
| 363 | switch (blank) { | ||
| 364 | case FB_BLANK_UNBLANK: | ||
| 365 | radeonfb_on(info); | ||
| 366 | break; | ||
| 367 | case FB_BLANK_NORMAL: | ||
| 368 | radeonfb_off(info, DRM_MODE_DPMS_STANDBY); | ||
| 369 | break; | ||
| 370 | case FB_BLANK_HSYNC_SUSPEND: | ||
| 371 | radeonfb_off(info, DRM_MODE_DPMS_STANDBY); | ||
| 372 | break; | ||
| 373 | case FB_BLANK_VSYNC_SUSPEND: | ||
| 374 | radeonfb_off(info, DRM_MODE_DPMS_SUSPEND); | ||
| 375 | break; | ||
| 376 | case FB_BLANK_POWERDOWN: | ||
| 377 | radeonfb_off(info, DRM_MODE_DPMS_OFF); | ||
| 378 | break; | ||
| 379 | } | ||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | |||
| 383 | static struct fb_ops radeonfb_ops = { | ||
| 384 | .owner = THIS_MODULE, | ||
| 385 | .fb_check_var = radeonfb_check_var, | ||
| 386 | .fb_set_par = radeonfb_set_par, | ||
| 387 | .fb_setcolreg = radeonfb_setcolreg, | ||
| 388 | .fb_fillrect = cfb_fillrect, | ||
| 389 | .fb_copyarea = cfb_copyarea, | ||
| 390 | .fb_imageblit = cfb_imageblit, | ||
| 391 | .fb_pan_display = radeonfb_pan_display, | ||
| 392 | .fb_blank = radeonfb_blank, | ||
| 393 | }; | ||
| 394 | |||
| 395 | /** | ||
| 396 | * Curretly it is assumed that the old framebuffer is reused. | ||
| 397 | * | ||
| 398 | * LOCKING | ||
| 399 | * caller should hold the mode config lock. | ||
| 400 | * | ||
| 401 | */ | ||
| 402 | int radeonfb_resize(struct drm_device *dev, struct drm_crtc *crtc) | ||
| 403 | { | ||
| 404 | struct fb_info *info; | ||
| 405 | struct drm_framebuffer *fb; | ||
| 406 | struct drm_display_mode *mode = crtc->desired_mode; | ||
| 407 | |||
| 408 | fb = crtc->fb; | ||
| 409 | if (fb == NULL) { | ||
| 410 | return 1; | ||
| 411 | } | ||
| 412 | info = fb->fbdev; | ||
| 413 | if (info == NULL) { | ||
| 414 | return 1; | ||
| 415 | } | ||
| 416 | if (mode == NULL) { | ||
| 417 | return 1; | ||
| 418 | } | ||
| 419 | info->var.xres = mode->hdisplay; | ||
| 420 | info->var.right_margin = mode->hsync_start - mode->hdisplay; | ||
| 421 | info->var.hsync_len = mode->hsync_end - mode->hsync_start; | ||
| 422 | info->var.left_margin = mode->htotal - mode->hsync_end; | ||
| 423 | info->var.yres = mode->vdisplay; | ||
| 424 | info->var.lower_margin = mode->vsync_start - mode->vdisplay; | ||
| 425 | info->var.vsync_len = mode->vsync_end - mode->vsync_start; | ||
| 426 | info->var.upper_margin = mode->vtotal - mode->vsync_end; | ||
| 427 | info->var.pixclock = 10000000 / mode->htotal * 1000 / mode->vtotal * 100; | ||
| 428 | /* avoid overflow */ | ||
| 429 | info->var.pixclock = info->var.pixclock * 1000 / mode->vrefresh; | ||
| 430 | |||
| 431 | return 0; | ||
| 432 | } | ||
| 433 | EXPORT_SYMBOL(radeonfb_resize); | ||
| 434 | |||
| 435 | static struct drm_mode_set panic_mode; | ||
| 436 | |||
| 437 | int radeonfb_panic(struct notifier_block *n, unsigned long ununsed, | ||
| 438 | void *panic_str) | ||
| 439 | { | ||
| 440 | DRM_ERROR("panic occurred, switching back to text console\n"); | ||
| 441 | drm_crtc_helper_set_config(&panic_mode); | ||
| 442 | return 0; | ||
| 443 | } | ||
| 444 | EXPORT_SYMBOL(radeonfb_panic); | ||
| 445 | |||
| 446 | static struct notifier_block paniced = { | ||
| 447 | .notifier_call = radeonfb_panic, | ||
| 448 | }; | ||
| 449 | |||
| 450 | static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp) | ||
| 451 | { | ||
| 452 | int aligned = width; | ||
| 453 | int align_large = (ASIC_IS_AVIVO(rdev)); | ||
| 454 | int pitch_mask = 0; | ||
| 455 | |||
| 456 | switch (bpp / 8) { | ||
| 457 | case 1: | ||
| 458 | pitch_mask = align_large ? 255 : 127; | ||
| 459 | break; | ||
| 460 | case 2: | ||
| 461 | pitch_mask = align_large ? 127 : 31; | ||
| 462 | break; | ||
| 463 | case 3: | ||
| 464 | case 4: | ||
| 465 | pitch_mask = align_large ? 63 : 15; | ||
| 466 | break; | ||
| 467 | } | ||
| 468 | |||
| 469 | aligned += pitch_mask; | ||
| 470 | aligned &= ~pitch_mask; | ||
| 471 | return aligned; | ||
| 472 | } | ||
| 473 | |||
| 474 | int radeonfb_create(struct radeon_device *rdev, | ||
| 475 | uint32_t fb_width, uint32_t fb_height, | ||
| 476 | uint32_t surface_width, uint32_t surface_height, | ||
| 477 | struct radeon_framebuffer **rfb_p) | ||
| 478 | { | ||
| 479 | struct fb_info *info; | ||
| 480 | struct radeon_fb_device *rfbdev; | ||
| 481 | struct drm_framebuffer *fb; | ||
| 482 | struct radeon_framebuffer *rfb; | ||
| 483 | struct drm_mode_fb_cmd mode_cmd; | ||
| 484 | struct drm_gem_object *gobj = NULL; | ||
| 485 | struct radeon_object *robj = NULL; | ||
| 486 | struct device *device = &rdev->pdev->dev; | ||
| 487 | int size, aligned_size, ret; | ||
| 488 | void *fbptr = NULL; | ||
| 489 | |||
| 490 | mode_cmd.width = surface_width; | ||
| 491 | mode_cmd.height = surface_height; | ||
| 492 | mode_cmd.bpp = 32; | ||
| 493 | /* need to align pitch with crtc limits */ | ||
| 494 | mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp) * ((mode_cmd.bpp + 1) / 8); | ||
| 495 | mode_cmd.depth = 24; | ||
| 496 | |||
| 497 | size = mode_cmd.pitch * mode_cmd.height; | ||
| 498 | aligned_size = ALIGN(size, PAGE_SIZE); | ||
| 499 | |||
| 500 | ret = radeon_gem_object_create(rdev, aligned_size, 0, | ||
| 501 | RADEON_GEM_DOMAIN_VRAM, | ||
| 502 | false, ttm_bo_type_kernel, | ||
| 503 | false, &gobj); | ||
| 504 | if (ret) { | ||
| 505 | printk(KERN_ERR "failed to allocate framebuffer\n"); | ||
| 506 | ret = -ENOMEM; | ||
| 507 | goto out; | ||
| 508 | } | ||
| 509 | robj = gobj->driver_private; | ||
| 510 | |||
| 511 | mutex_lock(&rdev->ddev->struct_mutex); | ||
| 512 | fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj); | ||
| 513 | if (fb == NULL) { | ||
| 514 | DRM_ERROR("failed to allocate fb.\n"); | ||
| 515 | ret = -ENOMEM; | ||
| 516 | goto out_unref; | ||
| 517 | } | ||
| 518 | |||
| 519 | list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list); | ||
| 520 | |||
| 521 | rfb = to_radeon_framebuffer(fb); | ||
| 522 | *rfb_p = rfb; | ||
| 523 | rdev->fbdev_rfb = rfb; | ||
| 524 | |||
| 525 | info = framebuffer_alloc(sizeof(struct radeon_fb_device), device); | ||
| 526 | if (info == NULL) { | ||
| 527 | ret = -ENOMEM; | ||
| 528 | goto out_unref; | ||
| 529 | } | ||
| 530 | rfbdev = info->par; | ||
| 531 | |||
| 532 | ret = radeon_object_kmap(robj, &fbptr); | ||
| 533 | if (ret) { | ||
| 534 | goto out_unref; | ||
| 535 | } | ||
| 536 | |||
| 537 | strcpy(info->fix.id, "radeondrmfb"); | ||
| 538 | info->fix.type = FB_TYPE_PACKED_PIXELS; | ||
| 539 | info->fix.visual = FB_VISUAL_TRUECOLOR; | ||
| 540 | info->fix.type_aux = 0; | ||
| 541 | info->fix.xpanstep = 1; /* doing it in hw */ | ||
| 542 | info->fix.ypanstep = 1; /* doing it in hw */ | ||
| 543 | info->fix.ywrapstep = 0; | ||
| 544 | info->fix.accel = FB_ACCEL_I830; | ||
| 545 | info->fix.type_aux = 0; | ||
| 546 | info->flags = FBINFO_DEFAULT; | ||
| 547 | info->fbops = &radeonfb_ops; | ||
| 548 | info->fix.line_length = fb->pitch; | ||
| 549 | info->screen_base = fbptr; | ||
| 550 | info->fix.smem_start = (unsigned long)fbptr; | ||
| 551 | info->fix.smem_len = size; | ||
| 552 | info->screen_base = fbptr; | ||
| 553 | info->screen_size = size; | ||
| 554 | info->pseudo_palette = fb->pseudo_palette; | ||
| 555 | info->var.xres_virtual = fb->width; | ||
| 556 | info->var.yres_virtual = fb->height; | ||
| 557 | info->var.bits_per_pixel = fb->bits_per_pixel; | ||
| 558 | info->var.xoffset = 0; | ||
| 559 | info->var.yoffset = 0; | ||
| 560 | info->var.activate = FB_ACTIVATE_NOW; | ||
| 561 | info->var.height = -1; | ||
| 562 | info->var.width = -1; | ||
| 563 | info->var.xres = fb_width; | ||
| 564 | info->var.yres = fb_height; | ||
| 565 | info->fix.mmio_start = pci_resource_start(rdev->pdev, 2); | ||
| 566 | info->fix.mmio_len = pci_resource_len(rdev->pdev, 2); | ||
| 567 | info->pixmap.size = 64*1024; | ||
| 568 | info->pixmap.buf_align = 8; | ||
| 569 | info->pixmap.access_align = 32; | ||
| 570 | info->pixmap.flags = FB_PIXMAP_SYSTEM; | ||
| 571 | info->pixmap.scan_align = 1; | ||
| 572 | if (info->screen_base == NULL) { | ||
| 573 | ret = -ENOSPC; | ||
| 574 | goto out_unref; | ||
| 575 | } | ||
| 576 | DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start); | ||
| 577 | DRM_INFO("vram apper at 0x%lX\n", (unsigned long)rdev->mc.aper_base); | ||
| 578 | DRM_INFO("size %lu\n", (unsigned long)size); | ||
| 579 | DRM_INFO("fb depth is %d\n", fb->depth); | ||
| 580 | DRM_INFO(" pitch is %d\n", fb->pitch); | ||
| 581 | |||
| 582 | switch (fb->depth) { | ||
| 583 | case 8: | ||
| 584 | info->var.red.offset = 0; | ||
| 585 | info->var.green.offset = 0; | ||
| 586 | info->var.blue.offset = 0; | ||
| 587 | info->var.red.length = 8; /* 8bit DAC */ | ||
| 588 | info->var.green.length = 8; | ||
| 589 | info->var.blue.length = 8; | ||
| 590 | info->var.transp.offset = 0; | ||
| 591 | info->var.transp.length = 0; | ||
| 592 | break; | ||
| 593 | case 15: | ||
| 594 | info->var.red.offset = 10; | ||
| 595 | info->var.green.offset = 5; | ||
| 596 | info->var.blue.offset = 0; | ||
| 597 | info->var.red.length = 5; | ||
| 598 | info->var.green.length = 5; | ||
| 599 | info->var.blue.length = 5; | ||
| 600 | info->var.transp.offset = 15; | ||
| 601 | info->var.transp.length = 1; | ||
| 602 | break; | ||
| 603 | case 16: | ||
| 604 | info->var.red.offset = 11; | ||
| 605 | info->var.green.offset = 5; | ||
| 606 | info->var.blue.offset = 0; | ||
| 607 | info->var.red.length = 5; | ||
| 608 | info->var.green.length = 6; | ||
| 609 | info->var.blue.length = 5; | ||
| 610 | info->var.transp.offset = 0; | ||
| 611 | break; | ||
| 612 | case 24: | ||
| 613 | info->var.red.offset = 16; | ||
| 614 | info->var.green.offset = 8; | ||
| 615 | info->var.blue.offset = 0; | ||
| 616 | info->var.red.length = 8; | ||
| 617 | info->var.green.length = 8; | ||
| 618 | info->var.blue.length = 8; | ||
| 619 | info->var.transp.offset = 0; | ||
| 620 | info->var.transp.length = 0; | ||
| 621 | break; | ||
| 622 | case 32: | ||
| 623 | info->var.red.offset = 16; | ||
| 624 | info->var.green.offset = 8; | ||
| 625 | info->var.blue.offset = 0; | ||
| 626 | info->var.red.length = 8; | ||
| 627 | info->var.green.length = 8; | ||
| 628 | info->var.blue.length = 8; | ||
| 629 | info->var.transp.offset = 24; | ||
| 630 | info->var.transp.length = 8; | ||
| 631 | break; | ||
| 632 | default: | ||
| 633 | break; | ||
| 634 | } | ||
| 635 | |||
| 636 | fb->fbdev = info; | ||
| 637 | rfbdev->rfb = rfb; | ||
| 638 | rfbdev->rdev = rdev; | ||
| 639 | |||
| 640 | mutex_unlock(&rdev->ddev->struct_mutex); | ||
| 641 | return 0; | ||
| 642 | |||
| 643 | out_unref: | ||
| 644 | if (robj) { | ||
| 645 | radeon_object_kunmap(robj); | ||
| 646 | } | ||
| 647 | if (ret) { | ||
| 648 | list_del(&fb->filp_head); | ||
| 649 | drm_gem_object_unreference(gobj); | ||
| 650 | drm_framebuffer_cleanup(fb); | ||
| 651 | kfree(fb); | ||
| 652 | } | ||
| 653 | drm_gem_object_unreference(gobj); | ||
| 654 | mutex_unlock(&rdev->ddev->struct_mutex); | ||
| 655 | out: | ||
| 656 | return ret; | ||
| 657 | } | ||
| 658 | |||
| 659 | static int radeonfb_single_fb_probe(struct radeon_device *rdev) | ||
| 660 | { | ||
| 661 | struct drm_crtc *crtc; | ||
| 662 | struct drm_connector *connector; | ||
| 663 | unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1; | ||
| 664 | unsigned int surface_width = 0, surface_height = 0; | ||
| 665 | int new_fb = 0; | ||
| 666 | int crtc_count = 0; | ||
| 667 | int ret, i, conn_count = 0; | ||
| 668 | struct radeon_framebuffer *rfb; | ||
| 669 | struct fb_info *info; | ||
| 670 | struct radeon_fb_device *rfbdev; | ||
| 671 | struct drm_mode_set *modeset = NULL; | ||
| 672 | |||
| 673 | /* first up get a count of crtcs now in use and new min/maxes width/heights */ | ||
| 674 | list_for_each_entry(crtc, &rdev->ddev->mode_config.crtc_list, head) { | ||
| 675 | if (drm_helper_crtc_in_use(crtc)) { | ||
| 676 | if (crtc->desired_mode) { | ||
| 677 | if (crtc->desired_mode->hdisplay < fb_width) | ||
| 678 | fb_width = crtc->desired_mode->hdisplay; | ||
| 679 | |||
| 680 | if (crtc->desired_mode->vdisplay < fb_height) | ||
| 681 | fb_height = crtc->desired_mode->vdisplay; | ||
| 682 | |||
| 683 | if (crtc->desired_mode->hdisplay > surface_width) | ||
| 684 | surface_width = crtc->desired_mode->hdisplay; | ||
| 685 | |||
| 686 | if (crtc->desired_mode->vdisplay > surface_height) | ||
| 687 | surface_height = crtc->desired_mode->vdisplay; | ||
| 688 | } | ||
| 689 | crtc_count++; | ||
| 690 | } | ||
| 691 | } | ||
| 692 | |||
| 693 | if (crtc_count == 0 || fb_width == -1 || fb_height == -1) { | ||
| 694 | /* hmm everyone went away - assume VGA cable just fell out | ||
| 695 | and will come back later. */ | ||
| 696 | return 0; | ||
| 697 | } | ||
| 698 | |||
| 699 | /* do we have an fb already? */ | ||
| 700 | if (list_empty(&rdev->ddev->mode_config.fb_kernel_list)) { | ||
| 701 | /* create an fb if we don't have one */ | ||
| 702 | ret = radeonfb_create(rdev, fb_width, fb_height, surface_width, surface_height, &rfb); | ||
| 703 | if (ret) { | ||
| 704 | return -EINVAL; | ||
| 705 | } | ||
| 706 | new_fb = 1; | ||
| 707 | } else { | ||
| 708 | struct drm_framebuffer *fb; | ||
| 709 | fb = list_first_entry(&rdev->ddev->mode_config.fb_kernel_list, struct drm_framebuffer, filp_head); | ||
| 710 | rfb = to_radeon_framebuffer(fb); | ||
| 711 | |||
| 712 | /* if someone hotplugs something bigger than we have already allocated, we are pwned. | ||
| 713 | As really we can't resize an fbdev that is in the wild currently due to fbdev | ||
| 714 | not really being designed for the lower layers moving stuff around under it. | ||
| 715 | - so in the grand style of things - punt. */ | ||
| 716 | if ((fb->width < surface_width) || (fb->height < surface_height)) { | ||
| 717 | DRM_ERROR("Framebuffer not large enough to scale console onto.\n"); | ||
| 718 | return -EINVAL; | ||
| 719 | } | ||
| 720 | } | ||
| 721 | |||
| 722 | info = rfb->base.fbdev; | ||
| 723 | rdev->fbdev_info = info; | ||
| 724 | rfbdev = info->par; | ||
| 725 | |||
| 726 | crtc_count = 0; | ||
| 727 | /* okay we need to setup new connector sets in the crtcs */ | ||
| 728 | list_for_each_entry(crtc, &rdev->ddev->mode_config.crtc_list, head) { | ||
| 729 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 730 | modeset = &radeon_crtc->mode_set; | ||
| 731 | modeset->fb = &rfb->base; | ||
| 732 | conn_count = 0; | ||
| 733 | list_for_each_entry(connector, &rdev->ddev->mode_config.connector_list, head) { | ||
| 734 | if (connector->encoder) | ||
| 735 | if (connector->encoder->crtc == modeset->crtc) { | ||
| 736 | modeset->connectors[conn_count] = connector; | ||
| 737 | conn_count++; | ||
| 738 | if (conn_count > RADEONFB_CONN_LIMIT) | ||
| 739 | BUG(); | ||
| 740 | } | ||
| 741 | } | ||
| 742 | |||
| 743 | for (i = conn_count; i < RADEONFB_CONN_LIMIT; i++) | ||
| 744 | modeset->connectors[i] = NULL; | ||
| 745 | |||
| 746 | |||
| 747 | rfbdev->crtc_ids[crtc_count++] = crtc->base.id; | ||
| 748 | |||
| 749 | modeset->num_connectors = conn_count; | ||
| 750 | if (modeset->crtc->desired_mode) { | ||
| 751 | if (modeset->mode) { | ||
| 752 | drm_mode_destroy(rdev->ddev, modeset->mode); | ||
| 753 | } | ||
| 754 | modeset->mode = drm_mode_duplicate(rdev->ddev, | ||
| 755 | modeset->crtc->desired_mode); | ||
| 756 | } | ||
| 757 | } | ||
| 758 | rfbdev->crtc_count = crtc_count; | ||
| 759 | |||
| 760 | if (new_fb) { | ||
| 761 | info->var.pixclock = -1; | ||
| 762 | if (register_framebuffer(info) < 0) | ||
| 763 | return -EINVAL; | ||
| 764 | } else { | ||
| 765 | radeonfb_set_par(info); | ||
| 766 | } | ||
| 767 | printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, | ||
| 768 | info->fix.id); | ||
| 769 | |||
| 770 | /* Switch back to kernel console on panic */ | ||
| 771 | panic_mode = *modeset; | ||
| 772 | atomic_notifier_chain_register(&panic_notifier_list, &paniced); | ||
| 773 | printk(KERN_INFO "registered panic notifier\n"); | ||
| 774 | |||
| 775 | return 0; | ||
| 776 | } | ||
| 777 | |||
| 778 | int radeonfb_probe(struct drm_device *dev) | ||
| 779 | { | ||
| 780 | int ret; | ||
| 781 | |||
| 782 | /* something has changed in the lower levels of hell - deal with it | ||
| 783 | here */ | ||
| 784 | |||
| 785 | /* two modes : a) 1 fb to rule all crtcs. | ||
| 786 | b) one fb per crtc. | ||
| 787 | two actions 1) new connected device | ||
| 788 | 2) device removed. | ||
| 789 | case a/1 : if the fb surface isn't big enough - resize the surface fb. | ||
| 790 | if the fb size isn't big enough - resize fb into surface. | ||
| 791 | if everything big enough configure the new crtc/etc. | ||
| 792 | case a/2 : undo the configuration | ||
| 793 | possibly resize down the fb to fit the new configuration. | ||
| 794 | case b/1 : see if it is on a new crtc - setup a new fb and add it. | ||
| 795 | case b/2 : teardown the new fb. | ||
| 796 | */ | ||
| 797 | ret = radeonfb_single_fb_probe(dev->dev_private); | ||
| 798 | return ret; | ||
| 799 | } | ||
| 800 | EXPORT_SYMBOL(radeonfb_probe); | ||
| 801 | |||
| 802 | int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) | ||
| 803 | { | ||
| 804 | struct fb_info *info; | ||
| 805 | struct radeon_framebuffer *rfb = to_radeon_framebuffer(fb); | ||
| 806 | struct radeon_object *robj; | ||
| 807 | |||
| 808 | if (!fb) { | ||
| 809 | return -EINVAL; | ||
| 810 | } | ||
| 811 | info = fb->fbdev; | ||
| 812 | if (info) { | ||
| 813 | robj = rfb->obj->driver_private; | ||
| 814 | unregister_framebuffer(info); | ||
| 815 | radeon_object_kunmap(robj); | ||
| 816 | framebuffer_release(info); | ||
| 817 | } | ||
| 818 | |||
| 819 | printk(KERN_INFO "unregistered panic notifier\n"); | ||
| 820 | atomic_notifier_chain_unregister(&panic_notifier_list, &paniced); | ||
| 821 | memset(&panic_mode, 0, sizeof(struct drm_mode_set)); | ||
| 822 | return 0; | ||
| 823 | } | ||
| 824 | EXPORT_SYMBOL(radeonfb_remove); | ||
| 825 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c new file mode 100644 index 000000000000..96afbf5ae2ad --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_fence.c | |||
| @@ -0,0 +1,387 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2009 Jerome Glisse. | ||
| 3 | * All Rights Reserved. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * 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, sub license, 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 16 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 17 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 18 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 19 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 20 | * | ||
| 21 | * The above copyright notice and this permission notice (including the | ||
| 22 | * next paragraph) shall be included in all copies or substantial portions | ||
| 23 | * of the Software. | ||
| 24 | * | ||
| 25 | */ | ||
| 26 | /* | ||
| 27 | * Authors: | ||
| 28 | * Jerome Glisse <glisse@freedesktop.org> | ||
| 29 | * Dave Airlie | ||
| 30 | */ | ||
| 31 | #include <linux/seq_file.h> | ||
| 32 | #include <asm/atomic.h> | ||
| 33 | #include <linux/wait.h> | ||
| 34 | #include <linux/list.h> | ||
| 35 | #include <linux/kref.h> | ||
| 36 | #include "drmP.h" | ||
| 37 | #include "drm.h" | ||
| 38 | #include "radeon_reg.h" | ||
| 39 | #include "radeon.h" | ||
| 40 | |||
| 41 | int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) | ||
| 42 | { | ||
| 43 | unsigned long irq_flags; | ||
| 44 | |||
| 45 | write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); | ||
| 46 | if (fence->emited) { | ||
| 47 | write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); | ||
| 48 | return 0; | ||
| 49 | } | ||
| 50 | fence->seq = atomic_add_return(1, &rdev->fence_drv.seq); | ||
| 51 | if (!rdev->cp.ready) { | ||
| 52 | /* FIXME: cp is not running assume everythings is done right | ||
| 53 | * away | ||
| 54 | */ | ||
| 55 | WREG32(rdev->fence_drv.scratch_reg, fence->seq); | ||
| 56 | } else { | ||
| 57 | radeon_fence_ring_emit(rdev, fence); | ||
| 58 | } | ||
| 59 | fence->emited = true; | ||
| 60 | fence->timeout = jiffies + ((2000 * HZ) / 1000); | ||
| 61 | list_del(&fence->list); | ||
| 62 | list_add_tail(&fence->list, &rdev->fence_drv.emited); | ||
| 63 | write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); | ||
| 64 | return 0; | ||
| 65 | } | ||
| 66 | |||
| 67 | static bool radeon_fence_poll_locked(struct radeon_device *rdev) | ||
| 68 | { | ||
| 69 | struct radeon_fence *fence; | ||
| 70 | struct list_head *i, *n; | ||
| 71 | uint32_t seq; | ||
| 72 | bool wake = false; | ||
| 73 | |||
| 74 | if (rdev == NULL) { | ||
| 75 | return true; | ||
| 76 | } | ||
| 77 | if (rdev->shutdown) { | ||
| 78 | return true; | ||
| 79 | } | ||
| 80 | seq = RREG32(rdev->fence_drv.scratch_reg); | ||
| 81 | rdev->fence_drv.last_seq = seq; | ||
| 82 | n = NULL; | ||
| 83 | list_for_each(i, &rdev->fence_drv.emited) { | ||
| 84 | fence = list_entry(i, struct radeon_fence, list); | ||
| 85 | if (fence->seq == seq) { | ||
| 86 | n = i; | ||
| 87 | break; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | /* all fence previous to this one are considered as signaled */ | ||
| 91 | if (n) { | ||
| 92 | i = n; | ||
| 93 | do { | ||
| 94 | n = i->prev; | ||
| 95 | list_del(i); | ||
| 96 | list_add_tail(i, &rdev->fence_drv.signaled); | ||
| 97 | fence = list_entry(i, struct radeon_fence, list); | ||
| 98 | fence->signaled = true; | ||
| 99 | i = n; | ||
| 100 | } while (i != &rdev->fence_drv.emited); | ||
| 101 | wake = true; | ||
| 102 | } | ||
| 103 | return wake; | ||
| 104 | } | ||
| 105 | |||
| 106 | static void radeon_fence_destroy(struct kref *kref) | ||
| 107 | { | ||
| 108 | unsigned long irq_flags; | ||
| 109 | struct radeon_fence *fence; | ||
| 110 | |||
| 111 | fence = container_of(kref, struct radeon_fence, kref); | ||
| 112 | write_lock_irqsave(&fence->rdev->fence_drv.lock, irq_flags); | ||
| 113 | list_del(&fence->list); | ||
| 114 | fence->emited = false; | ||
| 115 | write_unlock_irqrestore(&fence->rdev->fence_drv.lock, irq_flags); | ||
| 116 | kfree(fence); | ||
| 117 | } | ||
| 118 | |||
| 119 | int radeon_fence_create(struct radeon_device *rdev, struct radeon_fence **fence) | ||
| 120 | { | ||
| 121 | unsigned long irq_flags; | ||
| 122 | |||
| 123 | *fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL); | ||
| 124 | if ((*fence) == NULL) { | ||
| 125 | return -ENOMEM; | ||
| 126 | } | ||
| 127 | kref_init(&((*fence)->kref)); | ||
| 128 | (*fence)->rdev = rdev; | ||
| 129 | (*fence)->emited = false; | ||
| 130 | (*fence)->signaled = false; | ||
| 131 | (*fence)->seq = 0; | ||
| 132 | INIT_LIST_HEAD(&(*fence)->list); | ||
| 133 | |||
| 134 | write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); | ||
| 135 | list_add_tail(&(*fence)->list, &rdev->fence_drv.created); | ||
| 136 | write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); | ||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | |||
| 141 | bool radeon_fence_signaled(struct radeon_fence *fence) | ||
| 142 | { | ||
| 143 | struct radeon_device *rdev = fence->rdev; | ||
| 144 | unsigned long irq_flags; | ||
| 145 | bool signaled = false; | ||
| 146 | |||
| 147 | if (rdev->gpu_lockup) { | ||
| 148 | return true; | ||
| 149 | } | ||
| 150 | if (fence == NULL) { | ||
| 151 | return true; | ||
| 152 | } | ||
| 153 | write_lock_irqsave(&fence->rdev->fence_drv.lock, irq_flags); | ||
| 154 | signaled = fence->signaled; | ||
| 155 | /* if we are shuting down report all fence as signaled */ | ||
| 156 | if (fence->rdev->shutdown) { | ||
| 157 | signaled = true; | ||
| 158 | } | ||
| 159 | if (!fence->emited) { | ||
| 160 | WARN(1, "Querying an unemited fence : %p !\n", fence); | ||
| 161 | signaled = true; | ||
| 162 | } | ||
| 163 | if (!signaled) { | ||
| 164 | radeon_fence_poll_locked(fence->rdev); | ||
| 165 | signaled = fence->signaled; | ||
| 166 | } | ||
| 167 | write_unlock_irqrestore(&fence->rdev->fence_drv.lock, irq_flags); | ||
| 168 | return signaled; | ||
| 169 | } | ||
| 170 | |||
| 171 | int radeon_fence_wait(struct radeon_fence *fence, bool interruptible) | ||
| 172 | { | ||
| 173 | struct radeon_device *rdev; | ||
| 174 | unsigned long cur_jiffies; | ||
| 175 | unsigned long timeout; | ||
| 176 | bool expired = false; | ||
| 177 | int r; | ||
| 178 | |||
| 179 | |||
| 180 | if (fence == NULL) { | ||
| 181 | WARN(1, "Querying an invalid fence : %p !\n", fence); | ||
| 182 | return 0; | ||
| 183 | } | ||
| 184 | rdev = fence->rdev; | ||
| 185 | if (radeon_fence_signaled(fence)) { | ||
| 186 | return 0; | ||
| 187 | } | ||
| 188 | retry: | ||
| 189 | cur_jiffies = jiffies; | ||
| 190 | timeout = HZ / 100; | ||
| 191 | if (time_after(fence->timeout, cur_jiffies)) { | ||
| 192 | timeout = fence->timeout - cur_jiffies; | ||
| 193 | } | ||
| 194 | if (interruptible) { | ||
| 195 | r = wait_event_interruptible_timeout(rdev->fence_drv.queue, | ||
| 196 | radeon_fence_signaled(fence), timeout); | ||
| 197 | if (unlikely(r == -ERESTARTSYS)) { | ||
| 198 | return -ERESTART; | ||
| 199 | } | ||
| 200 | } else { | ||
| 201 | r = wait_event_timeout(rdev->fence_drv.queue, | ||
| 202 | radeon_fence_signaled(fence), timeout); | ||
| 203 | } | ||
| 204 | if (unlikely(!radeon_fence_signaled(fence))) { | ||
| 205 | if (unlikely(r == 0)) { | ||
| 206 | expired = true; | ||
| 207 | } | ||
| 208 | if (unlikely(expired)) { | ||
| 209 | timeout = 1; | ||
| 210 | if (time_after(cur_jiffies, fence->timeout)) { | ||
| 211 | timeout = cur_jiffies - fence->timeout; | ||
| 212 | } | ||
| 213 | timeout = jiffies_to_msecs(timeout); | ||
| 214 | if (timeout > 500) { | ||
| 215 | DRM_ERROR("fence(%p:0x%08X) %lums timeout " | ||
| 216 | "going to reset GPU\n", | ||
| 217 | fence, fence->seq, timeout); | ||
| 218 | radeon_gpu_reset(rdev); | ||
| 219 | WREG32(rdev->fence_drv.scratch_reg, fence->seq); | ||
| 220 | } | ||
| 221 | } | ||
| 222 | goto retry; | ||
| 223 | } | ||
| 224 | if (unlikely(expired)) { | ||
| 225 | rdev->fence_drv.count_timeout++; | ||
| 226 | cur_jiffies = jiffies; | ||
| 227 | timeout = 1; | ||
| 228 | if (time_after(cur_jiffies, fence->timeout)) { | ||
| 229 | timeout = cur_jiffies - fence->timeout; | ||
| 230 | } | ||
| 231 | timeout = jiffies_to_msecs(timeout); | ||
| 232 | DRM_ERROR("fence(%p:0x%08X) %lums timeout\n", | ||
| 233 | fence, fence->seq, timeout); | ||
| 234 | DRM_ERROR("last signaled fence(0x%08X)\n", | ||
| 235 | rdev->fence_drv.last_seq); | ||
| 236 | } | ||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 240 | int radeon_fence_wait_next(struct radeon_device *rdev) | ||
| 241 | { | ||
| 242 | unsigned long irq_flags; | ||
| 243 | struct radeon_fence *fence; | ||
| 244 | int r; | ||
| 245 | |||
| 246 | if (rdev->gpu_lockup) { | ||
| 247 | return 0; | ||
| 248 | } | ||
| 249 | write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); | ||
| 250 | if (list_empty(&rdev->fence_drv.emited)) { | ||
| 251 | write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); | ||
| 252 | return 0; | ||
| 253 | } | ||
| 254 | fence = list_entry(rdev->fence_drv.emited.next, | ||
| 255 | struct radeon_fence, list); | ||
| 256 | radeon_fence_ref(fence); | ||
| 257 | write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); | ||
| 258 | r = radeon_fence_wait(fence, false); | ||
| 259 | radeon_fence_unref(&fence); | ||
| 260 | return r; | ||
| 261 | } | ||
| 262 | |||
| 263 | int radeon_fence_wait_last(struct radeon_device *rdev) | ||
| 264 | { | ||
| 265 | unsigned long irq_flags; | ||
| 266 | struct radeon_fence *fence; | ||
| 267 | int r; | ||
| 268 | |||
| 269 | if (rdev->gpu_lockup) { | ||
| 270 | return 0; | ||
| 271 | } | ||
| 272 | write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); | ||
| 273 | if (list_empty(&rdev->fence_drv.emited)) { | ||
| 274 | write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); | ||
| 275 | return 0; | ||
| 276 | } | ||
| 277 | fence = list_entry(rdev->fence_drv.emited.prev, | ||
| 278 | struct radeon_fence, list); | ||
| 279 | radeon_fence_ref(fence); | ||
| 280 | write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); | ||
| 281 | r = radeon_fence_wait(fence, false); | ||
| 282 | radeon_fence_unref(&fence); | ||
| 283 | return r; | ||
| 284 | } | ||
| 285 | |||
| 286 | struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence) | ||
| 287 | { | ||
| 288 | kref_get(&fence->kref); | ||
| 289 | return fence; | ||
| 290 | } | ||
| 291 | |||
| 292 | void radeon_fence_unref(struct radeon_fence **fence) | ||
| 293 | { | ||
| 294 | struct radeon_fence *tmp = *fence; | ||
| 295 | |||
| 296 | *fence = NULL; | ||
| 297 | if (tmp) { | ||
| 298 | kref_put(&tmp->kref, &radeon_fence_destroy); | ||
| 299 | } | ||
| 300 | } | ||
| 301 | |||
| 302 | void radeon_fence_process(struct radeon_device *rdev) | ||
| 303 | { | ||
| 304 | unsigned long irq_flags; | ||
| 305 | bool wake; | ||
| 306 | |||
| 307 | write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); | ||
| 308 | wake = radeon_fence_poll_locked(rdev); | ||
| 309 | write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); | ||
| 310 | if (wake) { | ||
| 311 | wake_up_all(&rdev->fence_drv.queue); | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | int radeon_fence_driver_init(struct radeon_device *rdev) | ||
| 316 | { | ||
| 317 | unsigned long irq_flags; | ||
| 318 | int r; | ||
| 319 | |||
| 320 | write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); | ||
| 321 | r = radeon_scratch_get(rdev, &rdev->fence_drv.scratch_reg); | ||
| 322 | if (r) { | ||
| 323 | DRM_ERROR("Fence failed to get a scratch register."); | ||
| 324 | write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); | ||
| 325 | return r; | ||
| 326 | } | ||
| 327 | WREG32(rdev->fence_drv.scratch_reg, 0); | ||
| 328 | atomic_set(&rdev->fence_drv.seq, 0); | ||
| 329 | INIT_LIST_HEAD(&rdev->fence_drv.created); | ||
| 330 | INIT_LIST_HEAD(&rdev->fence_drv.emited); | ||
| 331 | INIT_LIST_HEAD(&rdev->fence_drv.signaled); | ||
| 332 | rdev->fence_drv.count_timeout = 0; | ||
| 333 | init_waitqueue_head(&rdev->fence_drv.queue); | ||
| 334 | write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); | ||
| 335 | if (radeon_debugfs_fence_init(rdev)) { | ||
| 336 | DRM_ERROR("Failed to register debugfs file for fence !\n"); | ||
| 337 | } | ||
| 338 | return 0; | ||
| 339 | } | ||
| 340 | |||
| 341 | void radeon_fence_driver_fini(struct radeon_device *rdev) | ||
| 342 | { | ||
| 343 | unsigned long irq_flags; | ||
| 344 | |||
| 345 | wake_up_all(&rdev->fence_drv.queue); | ||
| 346 | write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); | ||
| 347 | radeon_scratch_free(rdev, rdev->fence_drv.scratch_reg); | ||
| 348 | write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); | ||
| 349 | DRM_INFO("radeon: fence finalized\n"); | ||
| 350 | } | ||
| 351 | |||
| 352 | |||
| 353 | /* | ||
| 354 | * Fence debugfs | ||
| 355 | */ | ||
| 356 | #if defined(CONFIG_DEBUG_FS) | ||
| 357 | static int radeon_debugfs_fence_info(struct seq_file *m, void *data) | ||
| 358 | { | ||
| 359 | struct drm_info_node *node = (struct drm_info_node *)m->private; | ||
| 360 | struct drm_device *dev = node->minor->dev; | ||
| 361 | struct radeon_device *rdev = dev->dev_private; | ||
| 362 | struct radeon_fence *fence; | ||
| 363 | |||
| 364 | seq_printf(m, "Last signaled fence 0x%08X\n", | ||
| 365 | RREG32(rdev->fence_drv.scratch_reg)); | ||
| 366 | if (!list_empty(&rdev->fence_drv.emited)) { | ||
| 367 | fence = list_entry(rdev->fence_drv.emited.prev, | ||
| 368 | struct radeon_fence, list); | ||
| 369 | seq_printf(m, "Last emited fence %p with 0x%08X\n", | ||
| 370 | fence, fence->seq); | ||
| 371 | } | ||
| 372 | return 0; | ||
| 373 | } | ||
| 374 | |||
| 375 | static struct drm_info_list radeon_debugfs_fence_list[] = { | ||
| 376 | {"radeon_fence_info", &radeon_debugfs_fence_info, 0, NULL}, | ||
| 377 | }; | ||
| 378 | #endif | ||
| 379 | |||
| 380 | int radeon_debugfs_fence_init(struct radeon_device *rdev) | ||
| 381 | { | ||
| 382 | #if defined(CONFIG_DEBUG_FS) | ||
| 383 | return radeon_debugfs_add_files(rdev, radeon_debugfs_fence_list, 1); | ||
| 384 | #else | ||
| 385 | return 0; | ||
| 386 | #endif | ||
| 387 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_fixed.h b/drivers/gpu/drm/radeon/radeon_fixed.h new file mode 100644 index 000000000000..90187d173847 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_fixed.h | |||
| @@ -0,0 +1,50 @@ | |||
| 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 | * Authors: Dave Airlie | ||
| 23 | */ | ||
| 24 | #ifndef RADEON_FIXED_H | ||
| 25 | #define RADEON_FIXED_H | ||
| 26 | |||
| 27 | typedef union rfixed { | ||
| 28 | u32 full; | ||
| 29 | } fixed20_12; | ||
| 30 | |||
| 31 | |||
| 32 | #define rfixed_const(A) (u32)(((A) << 12))/* + ((B + 0.000122)*4096)) */ | ||
| 33 | #define rfixed_const_half(A) (u32)(((A) << 12) + 2048) | ||
| 34 | #define rfixed_const_666(A) (u32)(((A) << 12) + 2731) | ||
| 35 | #define rfixed_const_8(A) (u32)(((A) << 12) + 3277) | ||
| 36 | #define rfixed_mul(A, B) ((u64)((u64)(A).full * (B).full + 2048) >> 12) | ||
| 37 | #define fixed_init(A) { .full = rfixed_const((A)) } | ||
| 38 | #define fixed_init_half(A) { .full = rfixed_const_half((A)) } | ||
| 39 | #define rfixed_trunc(A) ((A).full >> 12) | ||
| 40 | |||
| 41 | static inline u32 rfixed_div(fixed20_12 A, fixed20_12 B) | ||
| 42 | { | ||
| 43 | u64 tmp = ((u64)A.full << 13); | ||
| 44 | |||
| 45 | do_div(tmp, B.full); | ||
| 46 | tmp += 1; | ||
| 47 | tmp /= 2; | ||
| 48 | return lower_32_bits(tmp); | ||
| 49 | } | ||
| 50 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c new file mode 100644 index 000000000000..d343a15316ec --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_gart.c | |||
| @@ -0,0 +1,233 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include "drmP.h" | ||
| 29 | #include "radeon_drm.h" | ||
| 30 | #include "radeon.h" | ||
| 31 | #include "radeon_reg.h" | ||
| 32 | |||
| 33 | /* | ||
| 34 | * Common GART table functions. | ||
| 35 | */ | ||
| 36 | int radeon_gart_table_ram_alloc(struct radeon_device *rdev) | ||
| 37 | { | ||
| 38 | void *ptr; | ||
| 39 | |||
| 40 | ptr = pci_alloc_consistent(rdev->pdev, rdev->gart.table_size, | ||
| 41 | &rdev->gart.table_addr); | ||
| 42 | if (ptr == NULL) { | ||
| 43 | return -ENOMEM; | ||
| 44 | } | ||
| 45 | #ifdef CONFIG_X86 | ||
| 46 | if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 || | ||
| 47 | rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { | ||
| 48 | set_memory_uc((unsigned long)ptr, | ||
| 49 | rdev->gart.table_size >> PAGE_SHIFT); | ||
| 50 | } | ||
| 51 | #endif | ||
| 52 | rdev->gart.table.ram.ptr = ptr; | ||
| 53 | memset((void *)rdev->gart.table.ram.ptr, 0, rdev->gart.table_size); | ||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | |||
| 57 | void radeon_gart_table_ram_free(struct radeon_device *rdev) | ||
| 58 | { | ||
| 59 | if (rdev->gart.table.ram.ptr == NULL) { | ||
| 60 | return; | ||
| 61 | } | ||
| 62 | #ifdef CONFIG_X86 | ||
| 63 | if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480 || | ||
| 64 | rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) { | ||
| 65 | set_memory_wb((unsigned long)rdev->gart.table.ram.ptr, | ||
| 66 | rdev->gart.table_size >> PAGE_SHIFT); | ||
| 67 | } | ||
| 68 | #endif | ||
| 69 | pci_free_consistent(rdev->pdev, rdev->gart.table_size, | ||
| 70 | (void *)rdev->gart.table.ram.ptr, | ||
| 71 | rdev->gart.table_addr); | ||
| 72 | rdev->gart.table.ram.ptr = NULL; | ||
| 73 | rdev->gart.table_addr = 0; | ||
| 74 | } | ||
| 75 | |||
| 76 | int radeon_gart_table_vram_alloc(struct radeon_device *rdev) | ||
| 77 | { | ||
| 78 | uint64_t gpu_addr; | ||
| 79 | int r; | ||
| 80 | |||
| 81 | if (rdev->gart.table.vram.robj == NULL) { | ||
| 82 | r = radeon_object_create(rdev, NULL, | ||
| 83 | rdev->gart.table_size, | ||
| 84 | true, | ||
| 85 | RADEON_GEM_DOMAIN_VRAM, | ||
| 86 | false, &rdev->gart.table.vram.robj); | ||
| 87 | if (r) { | ||
| 88 | return r; | ||
| 89 | } | ||
| 90 | } | ||
| 91 | r = radeon_object_pin(rdev->gart.table.vram.robj, | ||
| 92 | RADEON_GEM_DOMAIN_VRAM, &gpu_addr); | ||
| 93 | if (r) { | ||
| 94 | radeon_object_unref(&rdev->gart.table.vram.robj); | ||
| 95 | return r; | ||
| 96 | } | ||
| 97 | r = radeon_object_kmap(rdev->gart.table.vram.robj, | ||
| 98 | (void **)&rdev->gart.table.vram.ptr); | ||
| 99 | if (r) { | ||
| 100 | radeon_object_unpin(rdev->gart.table.vram.robj); | ||
| 101 | radeon_object_unref(&rdev->gart.table.vram.robj); | ||
| 102 | DRM_ERROR("radeon: failed to map gart vram table.\n"); | ||
| 103 | return r; | ||
| 104 | } | ||
| 105 | rdev->gart.table_addr = gpu_addr; | ||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | |||
| 109 | void radeon_gart_table_vram_free(struct radeon_device *rdev) | ||
| 110 | { | ||
| 111 | if (rdev->gart.table.vram.robj == NULL) { | ||
| 112 | return; | ||
| 113 | } | ||
| 114 | radeon_object_kunmap(rdev->gart.table.vram.robj); | ||
| 115 | radeon_object_unpin(rdev->gart.table.vram.robj); | ||
| 116 | radeon_object_unref(&rdev->gart.table.vram.robj); | ||
| 117 | } | ||
| 118 | |||
| 119 | |||
| 120 | |||
| 121 | |||
| 122 | /* | ||
| 123 | * Common gart functions. | ||
| 124 | */ | ||
| 125 | void radeon_gart_unbind(struct radeon_device *rdev, unsigned offset, | ||
| 126 | int pages) | ||
| 127 | { | ||
| 128 | unsigned t; | ||
| 129 | unsigned p; | ||
| 130 | int i, j; | ||
| 131 | |||
| 132 | if (!rdev->gart.ready) { | ||
| 133 | WARN(1, "trying to unbind memory to unitialized GART !\n"); | ||
| 134 | return; | ||
| 135 | } | ||
| 136 | t = offset / 4096; | ||
| 137 | p = t / (PAGE_SIZE / 4096); | ||
| 138 | for (i = 0; i < pages; i++, p++) { | ||
| 139 | if (rdev->gart.pages[p]) { | ||
| 140 | pci_unmap_page(rdev->pdev, rdev->gart.pages_addr[p], | ||
| 141 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | ||
| 142 | rdev->gart.pages[p] = NULL; | ||
| 143 | rdev->gart.pages_addr[p] = 0; | ||
| 144 | for (j = 0; j < (PAGE_SIZE / 4096); j++, t++) { | ||
| 145 | radeon_gart_set_page(rdev, t, 0); | ||
| 146 | } | ||
| 147 | } | ||
| 148 | } | ||
| 149 | mb(); | ||
| 150 | radeon_gart_tlb_flush(rdev); | ||
| 151 | } | ||
| 152 | |||
| 153 | int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, | ||
| 154 | int pages, struct page **pagelist) | ||
| 155 | { | ||
| 156 | unsigned t; | ||
| 157 | unsigned p; | ||
| 158 | uint64_t page_base; | ||
| 159 | int i, j; | ||
| 160 | |||
| 161 | if (!rdev->gart.ready) { | ||
| 162 | DRM_ERROR("trying to bind memory to unitialized GART !\n"); | ||
| 163 | return -EINVAL; | ||
| 164 | } | ||
| 165 | t = offset / 4096; | ||
| 166 | p = t / (PAGE_SIZE / 4096); | ||
| 167 | |||
| 168 | for (i = 0; i < pages; i++, p++) { | ||
| 169 | /* we need to support large memory configurations */ | ||
| 170 | /* assume that unbind have already been call on the range */ | ||
| 171 | rdev->gart.pages_addr[p] = pci_map_page(rdev->pdev, pagelist[i], | ||
| 172 | 0, PAGE_SIZE, | ||
| 173 | PCI_DMA_BIDIRECTIONAL); | ||
| 174 | if (pci_dma_mapping_error(rdev->pdev, rdev->gart.pages_addr[p])) { | ||
| 175 | /* FIXME: failed to map page (return -ENOMEM?) */ | ||
| 176 | radeon_gart_unbind(rdev, offset, pages); | ||
| 177 | return -ENOMEM; | ||
| 178 | } | ||
| 179 | rdev->gart.pages[p] = pagelist[i]; | ||
| 180 | page_base = (uint32_t)rdev->gart.pages_addr[p]; | ||
| 181 | for (j = 0; j < (PAGE_SIZE / 4096); j++, t++) { | ||
| 182 | radeon_gart_set_page(rdev, t, page_base); | ||
| 183 | page_base += 4096; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | mb(); | ||
| 187 | radeon_gart_tlb_flush(rdev); | ||
| 188 | return 0; | ||
| 189 | } | ||
| 190 | |||
| 191 | int radeon_gart_init(struct radeon_device *rdev) | ||
| 192 | { | ||
| 193 | if (rdev->gart.pages) { | ||
| 194 | return 0; | ||
| 195 | } | ||
| 196 | /* We need PAGE_SIZE >= 4096 */ | ||
| 197 | if (PAGE_SIZE < 4096) { | ||
| 198 | DRM_ERROR("Page size is smaller than GPU page size!\n"); | ||
| 199 | return -EINVAL; | ||
| 200 | } | ||
| 201 | /* Compute table size */ | ||
| 202 | rdev->gart.num_cpu_pages = rdev->mc.gtt_size / PAGE_SIZE; | ||
| 203 | rdev->gart.num_gpu_pages = rdev->mc.gtt_size / 4096; | ||
| 204 | DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n", | ||
| 205 | rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages); | ||
| 206 | /* Allocate pages table */ | ||
| 207 | rdev->gart.pages = kzalloc(sizeof(void *) * rdev->gart.num_cpu_pages, | ||
| 208 | GFP_KERNEL); | ||
| 209 | if (rdev->gart.pages == NULL) { | ||
| 210 | radeon_gart_fini(rdev); | ||
| 211 | return -ENOMEM; | ||
| 212 | } | ||
| 213 | rdev->gart.pages_addr = kzalloc(sizeof(dma_addr_t) * | ||
| 214 | rdev->gart.num_cpu_pages, GFP_KERNEL); | ||
| 215 | if (rdev->gart.pages_addr == NULL) { | ||
| 216 | radeon_gart_fini(rdev); | ||
| 217 | return -ENOMEM; | ||
| 218 | } | ||
| 219 | return 0; | ||
| 220 | } | ||
| 221 | |||
| 222 | void radeon_gart_fini(struct radeon_device *rdev) | ||
| 223 | { | ||
| 224 | if (rdev->gart.pages && rdev->gart.pages_addr && rdev->gart.ready) { | ||
| 225 | /* unbind pages */ | ||
| 226 | radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages); | ||
| 227 | } | ||
| 228 | rdev->gart.ready = false; | ||
| 229 | kfree(rdev->gart.pages); | ||
| 230 | kfree(rdev->gart.pages_addr); | ||
| 231 | rdev->gart.pages = NULL; | ||
| 232 | rdev->gart.pages_addr = NULL; | ||
| 233 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c new file mode 100644 index 000000000000..eb516034235d --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_gem.c | |||
| @@ -0,0 +1,287 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include "drmP.h" | ||
| 29 | #include "drm.h" | ||
| 30 | #include "radeon_drm.h" | ||
| 31 | #include "radeon.h" | ||
| 32 | |||
| 33 | int radeon_gem_object_init(struct drm_gem_object *obj) | ||
| 34 | { | ||
| 35 | /* we do nothings here */ | ||
| 36 | return 0; | ||
| 37 | } | ||
| 38 | |||
| 39 | void radeon_gem_object_free(struct drm_gem_object *gobj) | ||
| 40 | { | ||
| 41 | struct radeon_object *robj = gobj->driver_private; | ||
| 42 | |||
| 43 | gobj->driver_private = NULL; | ||
| 44 | if (robj) { | ||
| 45 | radeon_object_unref(&robj); | ||
| 46 | } | ||
| 47 | } | ||
| 48 | |||
| 49 | int radeon_gem_object_create(struct radeon_device *rdev, int size, | ||
| 50 | int alignment, int initial_domain, | ||
| 51 | bool discardable, bool kernel, | ||
| 52 | bool interruptible, | ||
| 53 | struct drm_gem_object **obj) | ||
| 54 | { | ||
| 55 | struct drm_gem_object *gobj; | ||
| 56 | struct radeon_object *robj; | ||
| 57 | int r; | ||
| 58 | |||
| 59 | *obj = NULL; | ||
| 60 | gobj = drm_gem_object_alloc(rdev->ddev, size); | ||
| 61 | if (!gobj) { | ||
| 62 | return -ENOMEM; | ||
| 63 | } | ||
| 64 | /* At least align on page size */ | ||
| 65 | if (alignment < PAGE_SIZE) { | ||
| 66 | alignment = PAGE_SIZE; | ||
| 67 | } | ||
| 68 | r = radeon_object_create(rdev, gobj, size, kernel, initial_domain, | ||
| 69 | interruptible, &robj); | ||
| 70 | if (r) { | ||
| 71 | DRM_ERROR("Failed to allocate GEM object (%d, %d, %u)\n", | ||
| 72 | size, initial_domain, alignment); | ||
| 73 | mutex_lock(&rdev->ddev->struct_mutex); | ||
| 74 | drm_gem_object_unreference(gobj); | ||
| 75 | mutex_unlock(&rdev->ddev->struct_mutex); | ||
| 76 | return r; | ||
| 77 | } | ||
| 78 | gobj->driver_private = robj; | ||
| 79 | *obj = gobj; | ||
| 80 | return 0; | ||
| 81 | } | ||
| 82 | |||
| 83 | int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain, | ||
| 84 | uint64_t *gpu_addr) | ||
| 85 | { | ||
| 86 | struct radeon_object *robj = obj->driver_private; | ||
| 87 | uint32_t flags; | ||
| 88 | |||
| 89 | switch (pin_domain) { | ||
| 90 | case RADEON_GEM_DOMAIN_VRAM: | ||
| 91 | flags = TTM_PL_FLAG_VRAM; | ||
| 92 | break; | ||
| 93 | case RADEON_GEM_DOMAIN_GTT: | ||
| 94 | flags = TTM_PL_FLAG_TT; | ||
| 95 | break; | ||
| 96 | default: | ||
| 97 | flags = TTM_PL_FLAG_SYSTEM; | ||
| 98 | break; | ||
| 99 | } | ||
| 100 | return radeon_object_pin(robj, flags, gpu_addr); | ||
| 101 | } | ||
| 102 | |||
| 103 | void radeon_gem_object_unpin(struct drm_gem_object *obj) | ||
| 104 | { | ||
| 105 | struct radeon_object *robj = obj->driver_private; | ||
| 106 | radeon_object_unpin(robj); | ||
| 107 | } | ||
| 108 | |||
| 109 | int radeon_gem_set_domain(struct drm_gem_object *gobj, | ||
| 110 | uint32_t rdomain, uint32_t wdomain) | ||
| 111 | { | ||
| 112 | struct radeon_object *robj; | ||
| 113 | uint32_t domain; | ||
| 114 | int r; | ||
| 115 | |||
| 116 | /* FIXME: reeimplement */ | ||
| 117 | robj = gobj->driver_private; | ||
| 118 | /* work out where to validate the buffer to */ | ||
| 119 | domain = wdomain; | ||
| 120 | if (!domain) { | ||
| 121 | domain = rdomain; | ||
| 122 | } | ||
| 123 | if (!domain) { | ||
| 124 | /* Do nothings */ | ||
| 125 | printk(KERN_WARNING "Set domain withou domain !\n"); | ||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | if (domain == RADEON_GEM_DOMAIN_CPU) { | ||
| 129 | /* Asking for cpu access wait for object idle */ | ||
| 130 | r = radeon_object_wait(robj); | ||
| 131 | if (r) { | ||
| 132 | printk(KERN_ERR "Failed to wait for object !\n"); | ||
| 133 | return r; | ||
| 134 | } | ||
| 135 | } | ||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | int radeon_gem_init(struct radeon_device *rdev) | ||
| 140 | { | ||
| 141 | INIT_LIST_HEAD(&rdev->gem.objects); | ||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | |||
| 145 | void radeon_gem_fini(struct radeon_device *rdev) | ||
| 146 | { | ||
| 147 | radeon_object_force_delete(rdev); | ||
| 148 | } | ||
| 149 | |||
| 150 | |||
| 151 | /* | ||
| 152 | * GEM ioctls. | ||
| 153 | */ | ||
| 154 | int radeon_gem_info_ioctl(struct drm_device *dev, void *data, | ||
| 155 | struct drm_file *filp) | ||
| 156 | { | ||
| 157 | struct radeon_device *rdev = dev->dev_private; | ||
| 158 | struct drm_radeon_gem_info *args = data; | ||
| 159 | |||
| 160 | args->vram_size = rdev->mc.vram_size; | ||
| 161 | /* FIXME: report somethings that makes sense */ | ||
| 162 | args->vram_visible = rdev->mc.vram_size - (4 * 1024 * 1024); | ||
| 163 | args->gart_size = rdev->mc.gtt_size; | ||
| 164 | return 0; | ||
| 165 | } | ||
| 166 | |||
| 167 | int radeon_gem_pread_ioctl(struct drm_device *dev, void *data, | ||
| 168 | struct drm_file *filp) | ||
| 169 | { | ||
| 170 | /* TODO: implement */ | ||
| 171 | DRM_ERROR("unimplemented %s\n", __func__); | ||
| 172 | return -ENOSYS; | ||
| 173 | } | ||
| 174 | |||
| 175 | int radeon_gem_pwrite_ioctl(struct drm_device *dev, void *data, | ||
| 176 | struct drm_file *filp) | ||
| 177 | { | ||
| 178 | /* TODO: implement */ | ||
| 179 | DRM_ERROR("unimplemented %s\n", __func__); | ||
| 180 | return -ENOSYS; | ||
| 181 | } | ||
| 182 | |||
| 183 | int radeon_gem_create_ioctl(struct drm_device *dev, void *data, | ||
| 184 | struct drm_file *filp) | ||
| 185 | { | ||
| 186 | struct radeon_device *rdev = dev->dev_private; | ||
| 187 | struct drm_radeon_gem_create *args = data; | ||
| 188 | struct drm_gem_object *gobj; | ||
| 189 | uint32_t handle; | ||
| 190 | int r; | ||
| 191 | |||
| 192 | /* create a gem object to contain this object in */ | ||
| 193 | args->size = roundup(args->size, PAGE_SIZE); | ||
| 194 | r = radeon_gem_object_create(rdev, args->size, args->alignment, | ||
| 195 | args->initial_domain, false, | ||
| 196 | false, true, &gobj); | ||
| 197 | if (r) { | ||
| 198 | return r; | ||
| 199 | } | ||
| 200 | r = drm_gem_handle_create(filp, gobj, &handle); | ||
| 201 | if (r) { | ||
| 202 | mutex_lock(&dev->struct_mutex); | ||
| 203 | drm_gem_object_unreference(gobj); | ||
| 204 | mutex_unlock(&dev->struct_mutex); | ||
| 205 | return r; | ||
| 206 | } | ||
| 207 | mutex_lock(&dev->struct_mutex); | ||
| 208 | drm_gem_object_handle_unreference(gobj); | ||
| 209 | mutex_unlock(&dev->struct_mutex); | ||
| 210 | args->handle = handle; | ||
| 211 | return 0; | ||
| 212 | } | ||
| 213 | |||
| 214 | int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data, | ||
| 215 | struct drm_file *filp) | ||
| 216 | { | ||
| 217 | /* transition the BO to a domain - | ||
| 218 | * just validate the BO into a certain domain */ | ||
| 219 | struct drm_radeon_gem_set_domain *args = data; | ||
| 220 | struct drm_gem_object *gobj; | ||
| 221 | struct radeon_object *robj; | ||
| 222 | int r; | ||
| 223 | |||
| 224 | /* for now if someone requests domain CPU - | ||
| 225 | * just make sure the buffer is finished with */ | ||
| 226 | |||
| 227 | /* just do a BO wait for now */ | ||
| 228 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | ||
| 229 | if (gobj == NULL) { | ||
| 230 | return -EINVAL; | ||
| 231 | } | ||
| 232 | robj = gobj->driver_private; | ||
| 233 | |||
| 234 | r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain); | ||
| 235 | |||
| 236 | mutex_lock(&dev->struct_mutex); | ||
| 237 | drm_gem_object_unreference(gobj); | ||
| 238 | mutex_unlock(&dev->struct_mutex); | ||
| 239 | return r; | ||
| 240 | } | ||
| 241 | |||
| 242 | int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data, | ||
| 243 | struct drm_file *filp) | ||
| 244 | { | ||
| 245 | struct drm_radeon_gem_mmap *args = data; | ||
| 246 | struct drm_gem_object *gobj; | ||
| 247 | struct radeon_object *robj; | ||
| 248 | int r; | ||
| 249 | |||
| 250 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | ||
| 251 | if (gobj == NULL) { | ||
| 252 | return -EINVAL; | ||
| 253 | } | ||
| 254 | robj = gobj->driver_private; | ||
| 255 | r = radeon_object_mmap(robj, &args->addr_ptr); | ||
| 256 | mutex_lock(&dev->struct_mutex); | ||
| 257 | drm_gem_object_unreference(gobj); | ||
| 258 | mutex_unlock(&dev->struct_mutex); | ||
| 259 | return r; | ||
| 260 | } | ||
| 261 | |||
| 262 | int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, | ||
| 263 | struct drm_file *filp) | ||
| 264 | { | ||
| 265 | /* FIXME: implement */ | ||
| 266 | return 0; | ||
| 267 | } | ||
| 268 | |||
| 269 | int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, | ||
| 270 | struct drm_file *filp) | ||
| 271 | { | ||
| 272 | struct drm_radeon_gem_wait_idle *args = data; | ||
| 273 | struct drm_gem_object *gobj; | ||
| 274 | struct radeon_object *robj; | ||
| 275 | int r; | ||
| 276 | |||
| 277 | gobj = drm_gem_object_lookup(dev, filp, args->handle); | ||
| 278 | if (gobj == NULL) { | ||
| 279 | return -EINVAL; | ||
| 280 | } | ||
| 281 | robj = gobj->driver_private; | ||
| 282 | r = radeon_object_wait(robj); | ||
| 283 | mutex_lock(&dev->struct_mutex); | ||
| 284 | drm_gem_object_unreference(gobj); | ||
| 285 | mutex_unlock(&dev->struct_mutex); | ||
| 286 | return r; | ||
| 287 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c new file mode 100644 index 000000000000..71465ed2688a --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_i2c.c | |||
| @@ -0,0 +1,209 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2007-8 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * copy of this software and associated documentation files (the "Software"), | ||
| 7 | * to deal in the Software without restriction, including without limitation | ||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 10 | * Software is furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 21 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: Dave Airlie | ||
| 24 | * Alex Deucher | ||
| 25 | */ | ||
| 26 | #include "drmP.h" | ||
| 27 | #include "radeon_drm.h" | ||
| 28 | #include "radeon.h" | ||
| 29 | |||
| 30 | /** | ||
| 31 | * radeon_ddc_probe | ||
| 32 | * | ||
| 33 | */ | ||
| 34 | bool radeon_ddc_probe(struct radeon_connector *radeon_connector) | ||
| 35 | { | ||
| 36 | u8 out_buf[] = { 0x0, 0x0}; | ||
| 37 | u8 buf[2]; | ||
| 38 | int ret; | ||
| 39 | struct i2c_msg msgs[] = { | ||
| 40 | { | ||
| 41 | .addr = 0x50, | ||
| 42 | .flags = 0, | ||
| 43 | .len = 1, | ||
| 44 | .buf = out_buf, | ||
| 45 | }, | ||
| 46 | { | ||
| 47 | .addr = 0x50, | ||
| 48 | .flags = I2C_M_RD, | ||
| 49 | .len = 1, | ||
| 50 | .buf = buf, | ||
| 51 | } | ||
| 52 | }; | ||
| 53 | |||
| 54 | ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); | ||
| 55 | if (ret == 2) | ||
| 56 | return true; | ||
| 57 | |||
| 58 | return false; | ||
| 59 | } | ||
| 60 | |||
| 61 | |||
| 62 | void radeon_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state) | ||
| 63 | { | ||
| 64 | struct radeon_device *rdev = radeon_connector->base.dev->dev_private; | ||
| 65 | uint32_t temp; | ||
| 66 | struct radeon_i2c_bus_rec *rec = &radeon_connector->ddc_bus->rec; | ||
| 67 | |||
| 68 | /* RV410 appears to have a bug where the hw i2c in reset | ||
| 69 | * holds the i2c port in a bad state - switch hw i2c away before | ||
| 70 | * doing DDC - do this for all r200s/r300s/r400s for safety sake | ||
| 71 | */ | ||
| 72 | if ((rdev->family >= CHIP_R200) && !ASIC_IS_AVIVO(rdev)) { | ||
| 73 | if (rec->a_clk_reg == RADEON_GPIO_MONID) { | ||
| 74 | WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST | | ||
| 75 | R200_DVI_I2C_PIN_SEL(R200_SEL_DDC1))); | ||
| 76 | } else { | ||
| 77 | WREG32(RADEON_DVI_I2C_CNTL_0, (RADEON_I2C_SOFT_RST | | ||
| 78 | R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3))); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | if (lock_state) { | ||
| 82 | temp = RREG32(rec->a_clk_reg); | ||
| 83 | temp &= ~(rec->a_clk_mask); | ||
| 84 | WREG32(rec->a_clk_reg, temp); | ||
| 85 | |||
| 86 | temp = RREG32(rec->a_data_reg); | ||
| 87 | temp &= ~(rec->a_data_mask); | ||
| 88 | WREG32(rec->a_data_reg, temp); | ||
| 89 | } | ||
| 90 | |||
| 91 | temp = RREG32(rec->mask_clk_reg); | ||
| 92 | if (lock_state) | ||
| 93 | temp |= rec->mask_clk_mask; | ||
| 94 | else | ||
| 95 | temp &= ~rec->mask_clk_mask; | ||
| 96 | WREG32(rec->mask_clk_reg, temp); | ||
| 97 | temp = RREG32(rec->mask_clk_reg); | ||
| 98 | |||
| 99 | temp = RREG32(rec->mask_data_reg); | ||
| 100 | if (lock_state) | ||
| 101 | temp |= rec->mask_data_mask; | ||
| 102 | else | ||
| 103 | temp &= ~rec->mask_data_mask; | ||
| 104 | WREG32(rec->mask_data_reg, temp); | ||
| 105 | temp = RREG32(rec->mask_data_reg); | ||
| 106 | } | ||
| 107 | |||
| 108 | static int get_clock(void *i2c_priv) | ||
| 109 | { | ||
| 110 | struct radeon_i2c_chan *i2c = i2c_priv; | ||
| 111 | struct radeon_device *rdev = i2c->dev->dev_private; | ||
| 112 | struct radeon_i2c_bus_rec *rec = &i2c->rec; | ||
| 113 | uint32_t val; | ||
| 114 | |||
| 115 | val = RREG32(rec->get_clk_reg); | ||
| 116 | val &= rec->get_clk_mask; | ||
| 117 | |||
| 118 | return (val != 0); | ||
| 119 | } | ||
| 120 | |||
| 121 | |||
| 122 | static int get_data(void *i2c_priv) | ||
| 123 | { | ||
| 124 | struct radeon_i2c_chan *i2c = i2c_priv; | ||
| 125 | struct radeon_device *rdev = i2c->dev->dev_private; | ||
| 126 | struct radeon_i2c_bus_rec *rec = &i2c->rec; | ||
| 127 | uint32_t val; | ||
| 128 | |||
| 129 | val = RREG32(rec->get_data_reg); | ||
| 130 | val &= rec->get_data_mask; | ||
| 131 | return (val != 0); | ||
| 132 | } | ||
| 133 | |||
| 134 | static void set_clock(void *i2c_priv, int clock) | ||
| 135 | { | ||
| 136 | struct radeon_i2c_chan *i2c = i2c_priv; | ||
| 137 | struct radeon_device *rdev = i2c->dev->dev_private; | ||
| 138 | struct radeon_i2c_bus_rec *rec = &i2c->rec; | ||
| 139 | uint32_t val; | ||
| 140 | |||
| 141 | val = RREG32(rec->put_clk_reg) & (uint32_t)~(rec->put_clk_mask); | ||
| 142 | val |= clock ? 0 : rec->put_clk_mask; | ||
| 143 | WREG32(rec->put_clk_reg, val); | ||
| 144 | } | ||
| 145 | |||
| 146 | static void set_data(void *i2c_priv, int data) | ||
| 147 | { | ||
| 148 | struct radeon_i2c_chan *i2c = i2c_priv; | ||
| 149 | struct radeon_device *rdev = i2c->dev->dev_private; | ||
| 150 | struct radeon_i2c_bus_rec *rec = &i2c->rec; | ||
| 151 | uint32_t val; | ||
| 152 | |||
| 153 | val = RREG32(rec->put_data_reg) & (uint32_t)~(rec->put_data_mask); | ||
| 154 | val |= data ? 0 : rec->put_data_mask; | ||
| 155 | WREG32(rec->put_data_reg, val); | ||
| 156 | } | ||
| 157 | |||
| 158 | struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, | ||
| 159 | struct radeon_i2c_bus_rec *rec, | ||
| 160 | const char *name) | ||
| 161 | { | ||
| 162 | struct radeon_i2c_chan *i2c; | ||
| 163 | int ret; | ||
| 164 | |||
| 165 | i2c = drm_calloc(1, sizeof(struct radeon_i2c_chan), DRM_MEM_DRIVER); | ||
| 166 | if (i2c == NULL) | ||
| 167 | return NULL; | ||
| 168 | |||
| 169 | i2c->adapter.owner = THIS_MODULE; | ||
| 170 | i2c->adapter.algo_data = &i2c->algo; | ||
| 171 | i2c->dev = dev; | ||
| 172 | i2c->algo.setsda = set_data; | ||
| 173 | i2c->algo.setscl = set_clock; | ||
| 174 | i2c->algo.getsda = get_data; | ||
| 175 | i2c->algo.getscl = get_clock; | ||
| 176 | i2c->algo.udelay = 20; | ||
| 177 | /* vesa says 2.2 ms is enough, 1 jiffy doesn't seem to always | ||
| 178 | * make this, 2 jiffies is a lot more reliable */ | ||
| 179 | i2c->algo.timeout = 2; | ||
| 180 | i2c->algo.data = i2c; | ||
| 181 | i2c->rec = *rec; | ||
| 182 | i2c_set_adapdata(&i2c->adapter, i2c); | ||
| 183 | |||
| 184 | ret = i2c_bit_add_bus(&i2c->adapter); | ||
| 185 | if (ret) { | ||
| 186 | DRM_INFO("Failed to register i2c %s\n", name); | ||
| 187 | goto out_free; | ||
| 188 | } | ||
| 189 | |||
| 190 | return i2c; | ||
| 191 | out_free: | ||
| 192 | drm_free(i2c, sizeof(struct radeon_i2c_chan), DRM_MEM_DRIVER); | ||
| 193 | return NULL; | ||
| 194 | |||
| 195 | } | ||
| 196 | |||
| 197 | void radeon_i2c_destroy(struct radeon_i2c_chan *i2c) | ||
| 198 | { | ||
| 199 | if (!i2c) | ||
| 200 | return; | ||
| 201 | |||
| 202 | i2c_del_adapter(&i2c->adapter); | ||
| 203 | drm_free(i2c, sizeof(struct radeon_i2c_chan), DRM_MEM_DRIVER); | ||
| 204 | } | ||
| 205 | |||
| 206 | struct drm_encoder *radeon_best_encoder(struct drm_connector *connector) | ||
| 207 | { | ||
| 208 | return NULL; | ||
| 209 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c new file mode 100644 index 000000000000..491d569deb0e --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c | |||
| @@ -0,0 +1,158 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include "drmP.h" | ||
| 29 | #include "radeon_drm.h" | ||
| 30 | #include "radeon_reg.h" | ||
| 31 | #include "radeon_microcode.h" | ||
| 32 | #include "radeon.h" | ||
| 33 | #include "atom.h" | ||
| 34 | |||
| 35 | static inline uint32_t r100_irq_ack(struct radeon_device *rdev) | ||
| 36 | { | ||
| 37 | uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS); | ||
| 38 | uint32_t irq_mask = RADEON_SW_INT_TEST; | ||
| 39 | |||
| 40 | if (irqs) { | ||
| 41 | WREG32(RADEON_GEN_INT_STATUS, irqs); | ||
| 42 | } | ||
| 43 | return irqs & irq_mask; | ||
| 44 | } | ||
| 45 | |||
| 46 | int r100_irq_set(struct radeon_device *rdev) | ||
| 47 | { | ||
| 48 | uint32_t tmp = 0; | ||
| 49 | |||
| 50 | if (rdev->irq.sw_int) { | ||
| 51 | tmp |= RADEON_SW_INT_ENABLE; | ||
| 52 | } | ||
| 53 | /* Todo go through CRTC and enable vblank int or not */ | ||
| 54 | WREG32(RADEON_GEN_INT_CNTL, tmp); | ||
| 55 | return 0; | ||
| 56 | } | ||
| 57 | |||
| 58 | int r100_irq_process(struct radeon_device *rdev) | ||
| 59 | { | ||
| 60 | uint32_t status; | ||
| 61 | |||
| 62 | status = r100_irq_ack(rdev); | ||
| 63 | if (!status) { | ||
| 64 | return IRQ_NONE; | ||
| 65 | } | ||
| 66 | while (status) { | ||
| 67 | /* SW interrupt */ | ||
| 68 | if (status & RADEON_SW_INT_TEST) { | ||
| 69 | radeon_fence_process(rdev); | ||
| 70 | } | ||
| 71 | status = r100_irq_ack(rdev); | ||
| 72 | } | ||
| 73 | return IRQ_HANDLED; | ||
| 74 | } | ||
| 75 | |||
| 76 | int rs600_irq_set(struct radeon_device *rdev) | ||
| 77 | { | ||
| 78 | uint32_t tmp = 0; | ||
| 79 | |||
| 80 | if (rdev->irq.sw_int) { | ||
| 81 | tmp |= RADEON_SW_INT_ENABLE; | ||
| 82 | } | ||
| 83 | WREG32(RADEON_GEN_INT_CNTL, tmp); | ||
| 84 | /* Todo go through CRTC and enable vblank int or not */ | ||
| 85 | WREG32(R500_DxMODE_INT_MASK, 0); | ||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) | ||
| 90 | { | ||
| 91 | struct drm_device *dev = (struct drm_device *) arg; | ||
| 92 | struct radeon_device *rdev = dev->dev_private; | ||
| 93 | |||
| 94 | return radeon_irq_process(rdev); | ||
| 95 | } | ||
| 96 | |||
| 97 | void radeon_driver_irq_preinstall_kms(struct drm_device *dev) | ||
| 98 | { | ||
| 99 | struct radeon_device *rdev = dev->dev_private; | ||
| 100 | unsigned i; | ||
| 101 | |||
| 102 | /* Disable *all* interrupts */ | ||
| 103 | rdev->irq.sw_int = false; | ||
| 104 | for (i = 0; i < 2; i++) { | ||
| 105 | rdev->irq.crtc_vblank_int[i] = false; | ||
| 106 | } | ||
| 107 | radeon_irq_set(rdev); | ||
| 108 | /* Clear bits */ | ||
| 109 | radeon_irq_process(rdev); | ||
| 110 | } | ||
| 111 | |||
| 112 | int radeon_driver_irq_postinstall_kms(struct drm_device *dev) | ||
| 113 | { | ||
| 114 | struct radeon_device *rdev = dev->dev_private; | ||
| 115 | |||
| 116 | dev->max_vblank_count = 0x001fffff; | ||
| 117 | rdev->irq.sw_int = true; | ||
| 118 | radeon_irq_set(rdev); | ||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | void radeon_driver_irq_uninstall_kms(struct drm_device *dev) | ||
| 123 | { | ||
| 124 | struct radeon_device *rdev = dev->dev_private; | ||
| 125 | unsigned i; | ||
| 126 | |||
| 127 | if (rdev == NULL) { | ||
| 128 | return; | ||
| 129 | } | ||
| 130 | /* Disable *all* interrupts */ | ||
| 131 | rdev->irq.sw_int = false; | ||
| 132 | for (i = 0; i < 2; i++) { | ||
| 133 | rdev->irq.crtc_vblank_int[i] = false; | ||
| 134 | } | ||
| 135 | radeon_irq_set(rdev); | ||
| 136 | } | ||
| 137 | |||
| 138 | int radeon_irq_kms_init(struct radeon_device *rdev) | ||
| 139 | { | ||
| 140 | int r = 0; | ||
| 141 | |||
| 142 | r = drm_vblank_init(rdev->ddev, 2); | ||
| 143 | if (r) { | ||
| 144 | return r; | ||
| 145 | } | ||
| 146 | drm_irq_install(rdev->ddev); | ||
| 147 | rdev->irq.installed = true; | ||
| 148 | DRM_INFO("radeon: irq initialized.\n"); | ||
| 149 | return 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | void radeon_irq_kms_fini(struct radeon_device *rdev) | ||
| 153 | { | ||
| 154 | if (rdev->irq.installed) { | ||
| 155 | rdev->irq.installed = false; | ||
| 156 | drm_irq_uninstall(rdev->ddev); | ||
| 157 | } | ||
| 158 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c new file mode 100644 index 000000000000..b0ce44b9f5ab --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_kms.c | |||
| @@ -0,0 +1,295 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include "drmP.h" | ||
| 29 | #include "drm_sarea.h" | ||
| 30 | #include "radeon.h" | ||
| 31 | #include "radeon_drm.h" | ||
| 32 | |||
| 33 | |||
| 34 | /* | ||
| 35 | * Driver load/unload | ||
| 36 | */ | ||
| 37 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) | ||
| 38 | { | ||
| 39 | struct radeon_device *rdev; | ||
| 40 | int r; | ||
| 41 | |||
| 42 | rdev = kzalloc(sizeof(struct radeon_device), GFP_KERNEL); | ||
| 43 | if (rdev == NULL) { | ||
| 44 | return -ENOMEM; | ||
| 45 | } | ||
| 46 | dev->dev_private = (void *)rdev; | ||
| 47 | |||
| 48 | /* update BUS flag */ | ||
| 49 | if (drm_device_is_agp(dev)) { | ||
| 50 | flags |= RADEON_IS_AGP; | ||
| 51 | } else if (drm_device_is_pcie(dev)) { | ||
| 52 | flags |= RADEON_IS_PCIE; | ||
| 53 | } else { | ||
| 54 | flags |= RADEON_IS_PCI; | ||
| 55 | } | ||
| 56 | |||
| 57 | r = radeon_device_init(rdev, dev, dev->pdev, flags); | ||
| 58 | if (r) { | ||
| 59 | DRM_ERROR("Failed to initialize radeon, disabling IOCTL\n"); | ||
| 60 | radeon_device_fini(rdev); | ||
| 61 | return r; | ||
| 62 | } | ||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | |||
| 66 | int radeon_driver_unload_kms(struct drm_device *dev) | ||
| 67 | { | ||
| 68 | struct radeon_device *rdev = dev->dev_private; | ||
| 69 | |||
| 70 | radeon_device_fini(rdev); | ||
| 71 | kfree(rdev); | ||
| 72 | dev->dev_private = NULL; | ||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | |||
| 76 | |||
| 77 | /* | ||
| 78 | * Userspace get informations ioctl | ||
| 79 | */ | ||
| 80 | int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | ||
| 81 | { | ||
| 82 | struct radeon_device *rdev = dev->dev_private; | ||
| 83 | struct drm_radeon_info *info; | ||
| 84 | uint32_t *value_ptr; | ||
| 85 | uint32_t value; | ||
| 86 | |||
| 87 | info = data; | ||
| 88 | value_ptr = (uint32_t *)((unsigned long)info->value); | ||
| 89 | switch (info->request) { | ||
| 90 | case RADEON_INFO_DEVICE_ID: | ||
| 91 | value = dev->pci_device; | ||
| 92 | break; | ||
| 93 | case RADEON_INFO_NUM_GB_PIPES: | ||
| 94 | value = rdev->num_gb_pipes; | ||
| 95 | break; | ||
| 96 | default: | ||
| 97 | DRM_DEBUG("Invalid request %d\n", info->request); | ||
| 98 | return -EINVAL; | ||
| 99 | } | ||
| 100 | if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) { | ||
| 101 | DRM_ERROR("copy_to_user\n"); | ||
| 102 | return -EFAULT; | ||
| 103 | } | ||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | |||
| 107 | |||
| 108 | /* | ||
| 109 | * Outdated mess for old drm with Xorg being in charge (void function now). | ||
| 110 | */ | ||
| 111 | int radeon_driver_firstopen_kms(struct drm_device *dev) | ||
| 112 | { | ||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | |||
| 117 | void radeon_driver_lastclose_kms(struct drm_device *dev) | ||
| 118 | { | ||
| 119 | } | ||
| 120 | |||
| 121 | int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) | ||
| 122 | { | ||
| 123 | return 0; | ||
| 124 | } | ||
| 125 | |||
| 126 | void radeon_driver_postclose_kms(struct drm_device *dev, | ||
| 127 | struct drm_file *file_priv) | ||
| 128 | { | ||
| 129 | } | ||
| 130 | |||
| 131 | void radeon_driver_preclose_kms(struct drm_device *dev, | ||
| 132 | struct drm_file *file_priv) | ||
| 133 | { | ||
| 134 | } | ||
| 135 | |||
| 136 | |||
| 137 | /* | ||
| 138 | * VBlank related functions. | ||
| 139 | */ | ||
| 140 | u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) | ||
| 141 | { | ||
| 142 | /* FIXME: implement */ | ||
| 143 | return 0; | ||
| 144 | } | ||
| 145 | |||
| 146 | int radeon_enable_vblank_kms(struct drm_device *dev, int crtc) | ||
| 147 | { | ||
| 148 | /* FIXME: implement */ | ||
| 149 | return 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | void radeon_disable_vblank_kms(struct drm_device *dev, int crtc) | ||
| 153 | { | ||
| 154 | /* FIXME: implement */ | ||
| 155 | } | ||
| 156 | |||
| 157 | |||
| 158 | /* | ||
| 159 | * For multiple master (like multiple X). | ||
| 160 | */ | ||
| 161 | struct drm_radeon_master_private { | ||
| 162 | drm_local_map_t *sarea; | ||
| 163 | drm_radeon_sarea_t *sarea_priv; | ||
| 164 | }; | ||
| 165 | |||
| 166 | int radeon_master_create_kms(struct drm_device *dev, struct drm_master *master) | ||
| 167 | { | ||
| 168 | struct drm_radeon_master_private *master_priv; | ||
| 169 | unsigned long sareapage; | ||
| 170 | int ret; | ||
| 171 | |||
| 172 | master_priv = drm_calloc(1, sizeof(*master_priv), DRM_MEM_DRIVER); | ||
| 173 | if (master_priv == NULL) { | ||
| 174 | return -ENOMEM; | ||
| 175 | } | ||
| 176 | /* prebuild the SAREA */ | ||
| 177 | sareapage = max_t(unsigned long, SAREA_MAX, PAGE_SIZE); | ||
| 178 | ret = drm_addmap(dev, 0, sareapage, _DRM_SHM, | ||
| 179 | _DRM_CONTAINS_LOCK|_DRM_DRIVER, | ||
| 180 | &master_priv->sarea); | ||
| 181 | if (ret) { | ||
| 182 | DRM_ERROR("SAREA setup failed\n"); | ||
| 183 | return ret; | ||
| 184 | } | ||
| 185 | master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea); | ||
| 186 | master_priv->sarea_priv->pfCurrentPage = 0; | ||
| 187 | master->driver_priv = master_priv; | ||
| 188 | return 0; | ||
| 189 | } | ||
| 190 | |||
| 191 | void radeon_master_destroy_kms(struct drm_device *dev, | ||
| 192 | struct drm_master *master) | ||
| 193 | { | ||
| 194 | struct drm_radeon_master_private *master_priv = master->driver_priv; | ||
| 195 | |||
| 196 | if (master_priv == NULL) { | ||
| 197 | return; | ||
| 198 | } | ||
| 199 | if (master_priv->sarea) { | ||
| 200 | drm_rmmap_locked(dev, master_priv->sarea); | ||
| 201 | } | ||
| 202 | drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER); | ||
| 203 | master->driver_priv = NULL; | ||
| 204 | } | ||
| 205 | |||
| 206 | |||
| 207 | /* | ||
| 208 | * IOCTL. | ||
| 209 | */ | ||
| 210 | int radeon_dma_ioctl_kms(struct drm_device *dev, void *data, | ||
| 211 | struct drm_file *file_priv) | ||
| 212 | { | ||
| 213 | /* Not valid in KMS. */ | ||
| 214 | return -EINVAL; | ||
| 215 | } | ||
| 216 | |||
| 217 | #define KMS_INVALID_IOCTL(name) \ | ||
| 218 | int name(struct drm_device *dev, void *data, struct drm_file *file_priv)\ | ||
| 219 | { \ | ||
| 220 | DRM_ERROR("invalid ioctl with kms %s\n", __func__); \ | ||
| 221 | return -EINVAL; \ | ||
| 222 | } | ||
| 223 | |||
| 224 | /* | ||
| 225 | * All these ioctls are invalid in kms world. | ||
| 226 | */ | ||
| 227 | KMS_INVALID_IOCTL(radeon_cp_init_kms) | ||
| 228 | KMS_INVALID_IOCTL(radeon_cp_start_kms) | ||
| 229 | KMS_INVALID_IOCTL(radeon_cp_stop_kms) | ||
| 230 | KMS_INVALID_IOCTL(radeon_cp_reset_kms) | ||
| 231 | KMS_INVALID_IOCTL(radeon_cp_idle_kms) | ||
| 232 | KMS_INVALID_IOCTL(radeon_cp_resume_kms) | ||
| 233 | KMS_INVALID_IOCTL(radeon_engine_reset_kms) | ||
| 234 | KMS_INVALID_IOCTL(radeon_fullscreen_kms) | ||
| 235 | KMS_INVALID_IOCTL(radeon_cp_swap_kms) | ||
| 236 | KMS_INVALID_IOCTL(radeon_cp_clear_kms) | ||
| 237 | KMS_INVALID_IOCTL(radeon_cp_vertex_kms) | ||
| 238 | KMS_INVALID_IOCTL(radeon_cp_indices_kms) | ||
| 239 | KMS_INVALID_IOCTL(radeon_cp_texture_kms) | ||
| 240 | KMS_INVALID_IOCTL(radeon_cp_stipple_kms) | ||
| 241 | KMS_INVALID_IOCTL(radeon_cp_indirect_kms) | ||
| 242 | KMS_INVALID_IOCTL(radeon_cp_vertex2_kms) | ||
| 243 | KMS_INVALID_IOCTL(radeon_cp_cmdbuf_kms) | ||
| 244 | KMS_INVALID_IOCTL(radeon_cp_getparam_kms) | ||
| 245 | KMS_INVALID_IOCTL(radeon_cp_flip_kms) | ||
| 246 | KMS_INVALID_IOCTL(radeon_mem_alloc_kms) | ||
| 247 | KMS_INVALID_IOCTL(radeon_mem_free_kms) | ||
| 248 | KMS_INVALID_IOCTL(radeon_mem_init_heap_kms) | ||
| 249 | KMS_INVALID_IOCTL(radeon_irq_emit_kms) | ||
| 250 | KMS_INVALID_IOCTL(radeon_irq_wait_kms) | ||
| 251 | KMS_INVALID_IOCTL(radeon_cp_setparam_kms) | ||
| 252 | KMS_INVALID_IOCTL(radeon_surface_alloc_kms) | ||
| 253 | KMS_INVALID_IOCTL(radeon_surface_free_kms) | ||
| 254 | |||
| 255 | |||
| 256 | struct drm_ioctl_desc radeon_ioctls_kms[] = { | ||
| 257 | DRM_IOCTL_DEF(DRM_RADEON_CP_INIT, radeon_cp_init_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||
| 258 | DRM_IOCTL_DEF(DRM_RADEON_CP_START, radeon_cp_start_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||
| 259 | DRM_IOCTL_DEF(DRM_RADEON_CP_STOP, radeon_cp_stop_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||
| 260 | DRM_IOCTL_DEF(DRM_RADEON_CP_RESET, radeon_cp_reset_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||
| 261 | DRM_IOCTL_DEF(DRM_RADEON_CP_IDLE, radeon_cp_idle_kms, DRM_AUTH), | ||
| 262 | DRM_IOCTL_DEF(DRM_RADEON_CP_RESUME, radeon_cp_resume_kms, DRM_AUTH), | ||
| 263 | DRM_IOCTL_DEF(DRM_RADEON_RESET, radeon_engine_reset_kms, DRM_AUTH), | ||
| 264 | DRM_IOCTL_DEF(DRM_RADEON_FULLSCREEN, radeon_fullscreen_kms, DRM_AUTH), | ||
| 265 | DRM_IOCTL_DEF(DRM_RADEON_SWAP, radeon_cp_swap_kms, DRM_AUTH), | ||
| 266 | DRM_IOCTL_DEF(DRM_RADEON_CLEAR, radeon_cp_clear_kms, DRM_AUTH), | ||
| 267 | DRM_IOCTL_DEF(DRM_RADEON_VERTEX, radeon_cp_vertex_kms, DRM_AUTH), | ||
| 268 | DRM_IOCTL_DEF(DRM_RADEON_INDICES, radeon_cp_indices_kms, DRM_AUTH), | ||
| 269 | DRM_IOCTL_DEF(DRM_RADEON_TEXTURE, radeon_cp_texture_kms, DRM_AUTH), | ||
| 270 | DRM_IOCTL_DEF(DRM_RADEON_STIPPLE, radeon_cp_stipple_kms, DRM_AUTH), | ||
| 271 | DRM_IOCTL_DEF(DRM_RADEON_INDIRECT, radeon_cp_indirect_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||
| 272 | DRM_IOCTL_DEF(DRM_RADEON_VERTEX2, radeon_cp_vertex2_kms, DRM_AUTH), | ||
| 273 | DRM_IOCTL_DEF(DRM_RADEON_CMDBUF, radeon_cp_cmdbuf_kms, DRM_AUTH), | ||
| 274 | DRM_IOCTL_DEF(DRM_RADEON_GETPARAM, radeon_cp_getparam_kms, DRM_AUTH), | ||
| 275 | DRM_IOCTL_DEF(DRM_RADEON_FLIP, radeon_cp_flip_kms, DRM_AUTH), | ||
| 276 | DRM_IOCTL_DEF(DRM_RADEON_ALLOC, radeon_mem_alloc_kms, DRM_AUTH), | ||
| 277 | DRM_IOCTL_DEF(DRM_RADEON_FREE, radeon_mem_free_kms, DRM_AUTH), | ||
| 278 | DRM_IOCTL_DEF(DRM_RADEON_INIT_HEAP, radeon_mem_init_heap_kms, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||
| 279 | DRM_IOCTL_DEF(DRM_RADEON_IRQ_EMIT, radeon_irq_emit_kms, DRM_AUTH), | ||
| 280 | DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait_kms, DRM_AUTH), | ||
| 281 | DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam_kms, DRM_AUTH), | ||
| 282 | DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc_kms, DRM_AUTH), | ||
| 283 | DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free_kms, DRM_AUTH), | ||
| 284 | /* KMS */ | ||
| 285 | DRM_IOCTL_DEF(DRM_RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH), | ||
| 286 | DRM_IOCTL_DEF(DRM_RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH), | ||
| 287 | DRM_IOCTL_DEF(DRM_RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH), | ||
| 288 | DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH), | ||
| 289 | DRM_IOCTL_DEF(DRM_RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH), | ||
| 290 | DRM_IOCTL_DEF(DRM_RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH), | ||
| 291 | DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH), | ||
| 292 | DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH), | ||
| 293 | DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH), | ||
| 294 | }; | ||
| 295 | int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms); | ||
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c new file mode 100644 index 000000000000..8086ecf7f03d --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c | |||
| @@ -0,0 +1,1276 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2007-8 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * copy of this software and associated documentation files (the "Software"), | ||
| 7 | * to deal in the Software without restriction, including without limitation | ||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 10 | * Software is furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 21 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: Dave Airlie | ||
| 24 | * Alex Deucher | ||
| 25 | */ | ||
| 26 | #include <drm/drmP.h> | ||
| 27 | #include <drm/drm_crtc_helper.h> | ||
| 28 | #include <drm/radeon_drm.h> | ||
| 29 | #include "radeon_fixed.h" | ||
| 30 | #include "radeon.h" | ||
| 31 | |||
| 32 | void radeon_restore_common_regs(struct drm_device *dev) | ||
| 33 | { | ||
| 34 | /* don't need this yet */ | ||
| 35 | } | ||
| 36 | |||
| 37 | static void radeon_pll_wait_for_read_update_complete(struct drm_device *dev) | ||
| 38 | { | ||
| 39 | struct radeon_device *rdev = dev->dev_private; | ||
| 40 | int i = 0; | ||
| 41 | |||
| 42 | /* FIXME: Certain revisions of R300 can't recover here. Not sure of | ||
| 43 | the cause yet, but this workaround will mask the problem for now. | ||
| 44 | Other chips usually will pass at the very first test, so the | ||
| 45 | workaround shouldn't have any effect on them. */ | ||
| 46 | for (i = 0; | ||
| 47 | (i < 10000 && | ||
| 48 | RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R); | ||
| 49 | i++); | ||
| 50 | } | ||
| 51 | |||
| 52 | static void radeon_pll_write_update(struct drm_device *dev) | ||
| 53 | { | ||
| 54 | struct radeon_device *rdev = dev->dev_private; | ||
| 55 | |||
| 56 | while (RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_ATOMIC_UPDATE_R); | ||
| 57 | |||
| 58 | WREG32_PLL_P(RADEON_PPLL_REF_DIV, | ||
| 59 | RADEON_PPLL_ATOMIC_UPDATE_W, | ||
| 60 | ~(RADEON_PPLL_ATOMIC_UPDATE_W)); | ||
| 61 | } | ||
| 62 | |||
| 63 | static void radeon_pll2_wait_for_read_update_complete(struct drm_device *dev) | ||
| 64 | { | ||
| 65 | struct radeon_device *rdev = dev->dev_private; | ||
| 66 | int i = 0; | ||
| 67 | |||
| 68 | |||
| 69 | /* FIXME: Certain revisions of R300 can't recover here. Not sure of | ||
| 70 | the cause yet, but this workaround will mask the problem for now. | ||
| 71 | Other chips usually will pass at the very first test, so the | ||
| 72 | workaround shouldn't have any effect on them. */ | ||
| 73 | for (i = 0; | ||
| 74 | (i < 10000 && | ||
| 75 | RREG32_PLL(RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R); | ||
| 76 | i++); | ||
| 77 | } | ||
| 78 | |||
| 79 | static void radeon_pll2_write_update(struct drm_device *dev) | ||
| 80 | { | ||
| 81 | struct radeon_device *rdev = dev->dev_private; | ||
| 82 | |||
| 83 | while (RREG32_PLL(RADEON_P2PLL_REF_DIV) & RADEON_P2PLL_ATOMIC_UPDATE_R); | ||
| 84 | |||
| 85 | WREG32_PLL_P(RADEON_P2PLL_REF_DIV, | ||
| 86 | RADEON_P2PLL_ATOMIC_UPDATE_W, | ||
| 87 | ~(RADEON_P2PLL_ATOMIC_UPDATE_W)); | ||
| 88 | } | ||
| 89 | |||
| 90 | static uint8_t radeon_compute_pll_gain(uint16_t ref_freq, uint16_t ref_div, | ||
| 91 | uint16_t fb_div) | ||
| 92 | { | ||
| 93 | unsigned int vcoFreq; | ||
| 94 | |||
| 95 | if (!ref_div) | ||
| 96 | return 1; | ||
| 97 | |||
| 98 | vcoFreq = ((unsigned)ref_freq & fb_div) / ref_div; | ||
| 99 | |||
| 100 | /* | ||
| 101 | * This is horribly crude: the VCO frequency range is divided into | ||
| 102 | * 3 parts, each part having a fixed PLL gain value. | ||
| 103 | */ | ||
| 104 | if (vcoFreq >= 30000) | ||
| 105 | /* | ||
| 106 | * [300..max] MHz : 7 | ||
| 107 | */ | ||
| 108 | return 7; | ||
| 109 | else if (vcoFreq >= 18000) | ||
| 110 | /* | ||
| 111 | * [180..300) MHz : 4 | ||
| 112 | */ | ||
| 113 | return 4; | ||
| 114 | else | ||
| 115 | /* | ||
| 116 | * [0..180) MHz : 1 | ||
| 117 | */ | ||
| 118 | return 1; | ||
| 119 | } | ||
| 120 | |||
| 121 | void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) | ||
| 122 | { | ||
| 123 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 124 | struct drm_device *dev = crtc->dev; | ||
| 125 | struct radeon_device *rdev = dev->dev_private; | ||
| 126 | uint32_t mask; | ||
| 127 | |||
| 128 | if (radeon_crtc->crtc_id) | ||
| 129 | mask = (RADEON_CRTC2_EN | | ||
| 130 | RADEON_CRTC2_DISP_DIS | | ||
| 131 | RADEON_CRTC2_VSYNC_DIS | | ||
| 132 | RADEON_CRTC2_HSYNC_DIS | | ||
| 133 | RADEON_CRTC2_DISP_REQ_EN_B); | ||
| 134 | else | ||
| 135 | mask = (RADEON_CRTC_DISPLAY_DIS | | ||
| 136 | RADEON_CRTC_VSYNC_DIS | | ||
| 137 | RADEON_CRTC_HSYNC_DIS); | ||
| 138 | |||
| 139 | switch (mode) { | ||
| 140 | case DRM_MODE_DPMS_ON: | ||
| 141 | if (radeon_crtc->crtc_id) | ||
| 142 | WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~mask); | ||
| 143 | else { | ||
| 144 | WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN | | ||
| 145 | RADEON_CRTC_DISP_REQ_EN_B)); | ||
| 146 | WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask); | ||
| 147 | } | ||
| 148 | break; | ||
| 149 | case DRM_MODE_DPMS_STANDBY: | ||
| 150 | case DRM_MODE_DPMS_SUSPEND: | ||
| 151 | case DRM_MODE_DPMS_OFF: | ||
| 152 | if (radeon_crtc->crtc_id) | ||
| 153 | WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~mask); | ||
| 154 | else { | ||
| 155 | WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN | | ||
| 156 | RADEON_CRTC_DISP_REQ_EN_B)); | ||
| 157 | WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask); | ||
| 158 | } | ||
| 159 | break; | ||
| 160 | } | ||
| 161 | |||
| 162 | if (mode != DRM_MODE_DPMS_OFF) { | ||
| 163 | radeon_crtc_load_lut(crtc); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | /* properly set crtc bpp when using atombios */ | ||
| 168 | void radeon_legacy_atom_set_surface(struct drm_crtc *crtc) | ||
| 169 | { | ||
| 170 | struct drm_device *dev = crtc->dev; | ||
| 171 | struct radeon_device *rdev = dev->dev_private; | ||
| 172 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 173 | int format; | ||
| 174 | uint32_t crtc_gen_cntl; | ||
| 175 | uint32_t disp_merge_cntl; | ||
| 176 | uint32_t crtc_pitch; | ||
| 177 | |||
| 178 | switch (crtc->fb->bits_per_pixel) { | ||
| 179 | case 15: /* 555 */ | ||
| 180 | format = 3; | ||
| 181 | break; | ||
| 182 | case 16: /* 565 */ | ||
| 183 | format = 4; | ||
| 184 | break; | ||
| 185 | case 24: /* RGB */ | ||
| 186 | format = 5; | ||
| 187 | break; | ||
| 188 | case 32: /* xRGB */ | ||
| 189 | format = 6; | ||
| 190 | break; | ||
| 191 | default: | ||
| 192 | return; | ||
| 193 | } | ||
| 194 | |||
| 195 | crtc_pitch = ((((crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8)) * crtc->fb->bits_per_pixel) + | ||
| 196 | ((crtc->fb->bits_per_pixel * 8) - 1)) / | ||
| 197 | (crtc->fb->bits_per_pixel * 8)); | ||
| 198 | crtc_pitch |= crtc_pitch << 16; | ||
| 199 | |||
| 200 | WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch); | ||
| 201 | |||
| 202 | switch (radeon_crtc->crtc_id) { | ||
| 203 | case 0: | ||
| 204 | disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL); | ||
| 205 | disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; | ||
| 206 | WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl); | ||
| 207 | |||
| 208 | crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0xfffff0ff; | ||
| 209 | crtc_gen_cntl |= (format << 8); | ||
| 210 | crtc_gen_cntl |= RADEON_CRTC_EXT_DISP_EN; | ||
| 211 | WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); | ||
| 212 | break; | ||
| 213 | case 1: | ||
| 214 | disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL); | ||
| 215 | disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN; | ||
| 216 | WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl); | ||
| 217 | |||
| 218 | crtc_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0xfffff0ff; | ||
| 219 | crtc_gen_cntl |= (format << 8); | ||
| 220 | WREG32(RADEON_CRTC2_GEN_CNTL, crtc_gen_cntl); | ||
| 221 | WREG32(RADEON_FP_H2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_H_SYNC_STRT_WID)); | ||
| 222 | WREG32(RADEON_FP_V2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_V_SYNC_STRT_WID)); | ||
| 223 | break; | ||
| 224 | } | ||
| 225 | } | ||
| 226 | |||
| 227 | int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, | ||
| 228 | struct drm_framebuffer *old_fb) | ||
| 229 | { | ||
| 230 | struct drm_device *dev = crtc->dev; | ||
| 231 | struct radeon_device *rdev = dev->dev_private; | ||
| 232 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 233 | struct radeon_framebuffer *radeon_fb; | ||
| 234 | struct drm_gem_object *obj; | ||
| 235 | uint64_t base; | ||
| 236 | uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0; | ||
| 237 | uint32_t crtc_pitch, pitch_pixels; | ||
| 238 | |||
| 239 | DRM_DEBUG("\n"); | ||
| 240 | |||
| 241 | radeon_fb = to_radeon_framebuffer(crtc->fb); | ||
| 242 | |||
| 243 | obj = radeon_fb->obj; | ||
| 244 | if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &base)) { | ||
| 245 | return -EINVAL; | ||
| 246 | } | ||
| 247 | crtc_offset = (u32)base; | ||
| 248 | crtc_offset_cntl = 0; | ||
| 249 | |||
| 250 | pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8); | ||
| 251 | crtc_pitch = (((pitch_pixels * crtc->fb->bits_per_pixel) + | ||
| 252 | ((crtc->fb->bits_per_pixel * 8) - 1)) / | ||
| 253 | (crtc->fb->bits_per_pixel * 8)); | ||
| 254 | crtc_pitch |= crtc_pitch << 16; | ||
| 255 | |||
| 256 | /* TODO tiling */ | ||
| 257 | if (0) { | ||
| 258 | if (ASIC_IS_R300(rdev)) | ||
| 259 | crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN | | ||
| 260 | R300_CRTC_MICRO_TILE_BUFFER_DIS | | ||
| 261 | R300_CRTC_MACRO_TILE_EN); | ||
| 262 | else | ||
| 263 | crtc_offset_cntl |= RADEON_CRTC_TILE_EN; | ||
| 264 | } else { | ||
| 265 | if (ASIC_IS_R300(rdev)) | ||
| 266 | crtc_offset_cntl &= ~(R300_CRTC_X_Y_MODE_EN | | ||
| 267 | R300_CRTC_MICRO_TILE_BUFFER_DIS | | ||
| 268 | R300_CRTC_MACRO_TILE_EN); | ||
| 269 | else | ||
| 270 | crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN; | ||
| 271 | } | ||
| 272 | |||
| 273 | |||
| 274 | /* TODO more tiling */ | ||
| 275 | if (0) { | ||
| 276 | if (ASIC_IS_R300(rdev)) { | ||
| 277 | crtc_tile_x0_y0 = x | (y << 16); | ||
| 278 | base &= ~0x7ff; | ||
| 279 | } else { | ||
| 280 | int byteshift = crtc->fb->bits_per_pixel >> 4; | ||
| 281 | int tile_addr = (((y >> 3) * crtc->fb->width + x) >> (8 - byteshift)) << 11; | ||
| 282 | base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8); | ||
| 283 | crtc_offset_cntl |= (y % 16); | ||
| 284 | } | ||
| 285 | } else { | ||
| 286 | int offset = y * pitch_pixels + x; | ||
| 287 | switch (crtc->fb->bits_per_pixel) { | ||
| 288 | case 15: | ||
| 289 | case 16: | ||
| 290 | offset *= 2; | ||
| 291 | break; | ||
| 292 | case 24: | ||
| 293 | offset *= 3; | ||
| 294 | break; | ||
| 295 | case 32: | ||
| 296 | offset *= 4; | ||
| 297 | break; | ||
| 298 | default: | ||
| 299 | return false; | ||
| 300 | } | ||
| 301 | base += offset; | ||
| 302 | } | ||
| 303 | |||
| 304 | base &= ~7; | ||
| 305 | |||
| 306 | /* update sarea TODO */ | ||
| 307 | |||
| 308 | crtc_offset = (u32)base; | ||
| 309 | |||
| 310 | WREG32(RADEON_DISPLAY_BASE_ADDR + radeon_crtc->crtc_offset, rdev->mc.vram_location); | ||
| 311 | |||
| 312 | if (ASIC_IS_R300(rdev)) { | ||
| 313 | if (radeon_crtc->crtc_id) | ||
| 314 | WREG32(R300_CRTC2_TILE_X0_Y0, crtc_tile_x0_y0); | ||
| 315 | else | ||
| 316 | WREG32(R300_CRTC_TILE_X0_Y0, crtc_tile_x0_y0); | ||
| 317 | } | ||
| 318 | WREG32(RADEON_CRTC_OFFSET_CNTL + radeon_crtc->crtc_offset, crtc_offset_cntl); | ||
| 319 | WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset); | ||
| 320 | WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch); | ||
| 321 | |||
| 322 | if (old_fb && old_fb != crtc->fb) { | ||
| 323 | radeon_fb = to_radeon_framebuffer(old_fb); | ||
| 324 | radeon_gem_object_unpin(radeon_fb->obj); | ||
| 325 | } | ||
| 326 | return 0; | ||
| 327 | } | ||
| 328 | |||
| 329 | static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mode *mode) | ||
| 330 | { | ||
| 331 | struct drm_device *dev = crtc->dev; | ||
| 332 | struct radeon_device *rdev = dev->dev_private; | ||
| 333 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 334 | int format; | ||
| 335 | int hsync_start; | ||
| 336 | int hsync_wid; | ||
| 337 | int vsync_wid; | ||
| 338 | uint32_t crtc_h_total_disp; | ||
| 339 | uint32_t crtc_h_sync_strt_wid; | ||
| 340 | uint32_t crtc_v_total_disp; | ||
| 341 | uint32_t crtc_v_sync_strt_wid; | ||
| 342 | |||
| 343 | DRM_DEBUG("\n"); | ||
| 344 | |||
| 345 | switch (crtc->fb->bits_per_pixel) { | ||
| 346 | case 15: /* 555 */ | ||
| 347 | format = 3; | ||
| 348 | break; | ||
| 349 | case 16: /* 565 */ | ||
| 350 | format = 4; | ||
| 351 | break; | ||
| 352 | case 24: /* RGB */ | ||
| 353 | format = 5; | ||
| 354 | break; | ||
| 355 | case 32: /* xRGB */ | ||
| 356 | format = 6; | ||
| 357 | break; | ||
| 358 | default: | ||
| 359 | return false; | ||
| 360 | } | ||
| 361 | |||
| 362 | crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff) | ||
| 363 | | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); | ||
| 364 | |||
| 365 | hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; | ||
| 366 | if (!hsync_wid) | ||
| 367 | hsync_wid = 1; | ||
| 368 | hsync_start = mode->crtc_hsync_start - 8; | ||
| 369 | |||
| 370 | crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) | ||
| 371 | | ((hsync_wid & 0x3f) << 16) | ||
| 372 | | ((mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
| 373 | ? RADEON_CRTC_H_SYNC_POL | ||
| 374 | : 0)); | ||
| 375 | |||
| 376 | /* This works for double scan mode. */ | ||
| 377 | crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff) | ||
| 378 | | ((mode->crtc_vdisplay - 1) << 16)); | ||
| 379 | |||
| 380 | vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; | ||
| 381 | if (!vsync_wid) | ||
| 382 | vsync_wid = 1; | ||
| 383 | |||
| 384 | crtc_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff) | ||
| 385 | | ((vsync_wid & 0x1f) << 16) | ||
| 386 | | ((mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
| 387 | ? RADEON_CRTC_V_SYNC_POL | ||
| 388 | : 0)); | ||
| 389 | |||
| 390 | /* TODO -> Dell Server */ | ||
| 391 | if (0) { | ||
| 392 | uint32_t disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); | ||
| 393 | uint32_t tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); | ||
| 394 | uint32_t dac2_cntl = RREG32(RADEON_DAC_CNTL2); | ||
| 395 | uint32_t crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); | ||
| 396 | |||
| 397 | dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; | ||
| 398 | dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; | ||
| 399 | |||
| 400 | /* For CRT on DAC2, don't turn it on if BIOS didn't | ||
| 401 | enable it, even it's detected. | ||
| 402 | */ | ||
| 403 | disp_hw_debug |= RADEON_CRT2_DISP1_SEL; | ||
| 404 | tv_dac_cntl &= ~((1<<2) | (3<<8) | (7<<24) | (0xff<<16)); | ||
| 405 | tv_dac_cntl |= (0x03 | (2<<8) | (0x58<<16)); | ||
| 406 | |||
| 407 | WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); | ||
| 408 | WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); | ||
| 409 | WREG32(RADEON_DAC_CNTL2, dac2_cntl); | ||
| 410 | WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); | ||
| 411 | } | ||
| 412 | |||
| 413 | if (radeon_crtc->crtc_id) { | ||
| 414 | uint32_t crtc2_gen_cntl; | ||
| 415 | uint32_t disp2_merge_cntl; | ||
| 416 | |||
| 417 | /* check to see if TV DAC is enabled for another crtc and keep it enabled */ | ||
| 418 | if (RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_CRT2_ON) | ||
| 419 | crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON; | ||
| 420 | else | ||
| 421 | crtc2_gen_cntl = 0; | ||
| 422 | |||
| 423 | crtc2_gen_cntl |= ((format << 8) | ||
| 424 | | RADEON_CRTC2_VSYNC_DIS | ||
| 425 | | RADEON_CRTC2_HSYNC_DIS | ||
| 426 | | RADEON_CRTC2_DISP_DIS | ||
| 427 | | RADEON_CRTC2_DISP_REQ_EN_B | ||
| 428 | | ((mode->flags & DRM_MODE_FLAG_DBLSCAN) | ||
| 429 | ? RADEON_CRTC2_DBL_SCAN_EN | ||
| 430 | : 0) | ||
| 431 | | ((mode->flags & DRM_MODE_FLAG_CSYNC) | ||
| 432 | ? RADEON_CRTC2_CSYNC_EN | ||
| 433 | : 0) | ||
| 434 | | ((mode->flags & DRM_MODE_FLAG_INTERLACE) | ||
| 435 | ? RADEON_CRTC2_INTERLACE_EN | ||
| 436 | : 0)); | ||
| 437 | |||
| 438 | disp2_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL); | ||
| 439 | disp2_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN; | ||
| 440 | |||
| 441 | WREG32(RADEON_DISP2_MERGE_CNTL, disp2_merge_cntl); | ||
| 442 | WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); | ||
| 443 | } else { | ||
| 444 | uint32_t crtc_gen_cntl; | ||
| 445 | uint32_t crtc_ext_cntl; | ||
| 446 | uint32_t disp_merge_cntl; | ||
| 447 | |||
| 448 | crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN | ||
| 449 | | (format << 8) | ||
| 450 | | RADEON_CRTC_DISP_REQ_EN_B | ||
| 451 | | ((mode->flags & DRM_MODE_FLAG_DBLSCAN) | ||
| 452 | ? RADEON_CRTC_DBL_SCAN_EN | ||
| 453 | : 0) | ||
| 454 | | ((mode->flags & DRM_MODE_FLAG_CSYNC) | ||
| 455 | ? RADEON_CRTC_CSYNC_EN | ||
| 456 | : 0) | ||
| 457 | | ((mode->flags & DRM_MODE_FLAG_INTERLACE) | ||
| 458 | ? RADEON_CRTC_INTERLACE_EN | ||
| 459 | : 0)); | ||
| 460 | |||
| 461 | crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); | ||
| 462 | crtc_ext_cntl |= (RADEON_XCRT_CNT_EN | | ||
| 463 | RADEON_CRTC_VSYNC_DIS | | ||
| 464 | RADEON_CRTC_HSYNC_DIS | | ||
| 465 | RADEON_CRTC_DISPLAY_DIS); | ||
| 466 | |||
| 467 | disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL); | ||
| 468 | disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; | ||
| 469 | |||
| 470 | WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl); | ||
| 471 | WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); | ||
| 472 | WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); | ||
| 473 | } | ||
| 474 | |||
| 475 | WREG32(RADEON_CRTC_H_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_h_total_disp); | ||
| 476 | WREG32(RADEON_CRTC_H_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_h_sync_strt_wid); | ||
| 477 | WREG32(RADEON_CRTC_V_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_v_total_disp); | ||
| 478 | WREG32(RADEON_CRTC_V_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_v_sync_strt_wid); | ||
| 479 | |||
| 480 | return true; | ||
| 481 | } | ||
| 482 | |||
| 483 | static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | ||
| 484 | { | ||
| 485 | struct drm_device *dev = crtc->dev; | ||
| 486 | struct radeon_device *rdev = dev->dev_private; | ||
| 487 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
| 488 | struct drm_encoder *encoder; | ||
| 489 | uint32_t feedback_div = 0; | ||
| 490 | uint32_t frac_fb_div = 0; | ||
| 491 | uint32_t reference_div = 0; | ||
| 492 | uint32_t post_divider = 0; | ||
| 493 | uint32_t freq = 0; | ||
| 494 | uint8_t pll_gain; | ||
| 495 | int pll_flags = RADEON_PLL_LEGACY; | ||
| 496 | bool use_bios_divs = false; | ||
| 497 | /* PLL registers */ | ||
| 498 | uint32_t pll_ref_div = 0; | ||
| 499 | uint32_t pll_fb_post_div = 0; | ||
| 500 | uint32_t htotal_cntl = 0; | ||
| 501 | |||
| 502 | struct radeon_pll *pll; | ||
| 503 | |||
| 504 | struct { | ||
| 505 | int divider; | ||
| 506 | int bitvalue; | ||
| 507 | } *post_div, post_divs[] = { | ||
| 508 | /* From RAGE 128 VR/RAGE 128 GL Register | ||
| 509 | * Reference Manual (Technical Reference | ||
| 510 | * Manual P/N RRG-G04100-C Rev. 0.04), page | ||
| 511 | * 3-17 (PLL_DIV_[3:0]). | ||
| 512 | */ | ||
| 513 | { 1, 0 }, /* VCLK_SRC */ | ||
| 514 | { 2, 1 }, /* VCLK_SRC/2 */ | ||
| 515 | { 4, 2 }, /* VCLK_SRC/4 */ | ||
| 516 | { 8, 3 }, /* VCLK_SRC/8 */ | ||
| 517 | { 3, 4 }, /* VCLK_SRC/3 */ | ||
| 518 | { 16, 5 }, /* VCLK_SRC/16 */ | ||
| 519 | { 6, 6 }, /* VCLK_SRC/6 */ | ||
| 520 | { 12, 7 }, /* VCLK_SRC/12 */ | ||
| 521 | { 0, 0 } | ||
| 522 | }; | ||
| 523 | |||
| 524 | if (radeon_crtc->crtc_id) | ||
| 525 | pll = &rdev->clock.p2pll; | ||
| 526 | else | ||
| 527 | pll = &rdev->clock.p1pll; | ||
| 528 | |||
| 529 | if (mode->clock > 200000) /* range limits??? */ | ||
| 530 | pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; | ||
| 531 | else | ||
| 532 | pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; | ||
| 533 | |||
| 534 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 535 | if (encoder->crtc == crtc) { | ||
| 536 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) | ||
| 537 | pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; | ||
| 538 | if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { | ||
| 539 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 540 | struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv; | ||
| 541 | if (lvds) { | ||
| 542 | if (lvds->use_bios_dividers) { | ||
| 543 | pll_ref_div = lvds->panel_ref_divider; | ||
| 544 | pll_fb_post_div = (lvds->panel_fb_divider | | ||
| 545 | (lvds->panel_post_divider << 16)); | ||
| 546 | htotal_cntl = 0; | ||
| 547 | use_bios_divs = true; | ||
| 548 | } | ||
| 549 | } | ||
| 550 | pll_flags |= RADEON_PLL_USE_REF_DIV; | ||
| 551 | } | ||
| 552 | } | ||
| 553 | } | ||
| 554 | |||
| 555 | DRM_DEBUG("\n"); | ||
| 556 | |||
| 557 | if (!use_bios_divs) { | ||
| 558 | radeon_compute_pll(pll, mode->clock, | ||
| 559 | &freq, &feedback_div, &frac_fb_div, | ||
| 560 | &reference_div, &post_divider, | ||
| 561 | pll_flags); | ||
| 562 | |||
| 563 | for (post_div = &post_divs[0]; post_div->divider; ++post_div) { | ||
| 564 | if (post_div->divider == post_divider) | ||
| 565 | break; | ||
| 566 | } | ||
| 567 | |||
| 568 | if (!post_div->divider) | ||
| 569 | post_div = &post_divs[0]; | ||
| 570 | |||
| 571 | DRM_DEBUG("dc=%u, fd=%d, rd=%d, pd=%d\n", | ||
| 572 | (unsigned)freq, | ||
| 573 | feedback_div, | ||
| 574 | reference_div, | ||
| 575 | post_divider); | ||
| 576 | |||
| 577 | pll_ref_div = reference_div; | ||
| 578 | #if defined(__powerpc__) && (0) /* TODO */ | ||
| 579 | /* apparently programming this otherwise causes a hang??? */ | ||
| 580 | if (info->MacModel == RADEON_MAC_IBOOK) | ||
| 581 | pll_fb_post_div = 0x000600ad; | ||
| 582 | else | ||
| 583 | #endif | ||
| 584 | pll_fb_post_div = (feedback_div | (post_div->bitvalue << 16)); | ||
| 585 | |||
| 586 | htotal_cntl = mode->htotal & 0x7; | ||
| 587 | |||
| 588 | } | ||
| 589 | |||
| 590 | pll_gain = radeon_compute_pll_gain(pll->reference_freq, | ||
| 591 | pll_ref_div & 0x3ff, | ||
| 592 | pll_fb_post_div & 0x7ff); | ||
| 593 | |||
| 594 | if (radeon_crtc->crtc_id) { | ||
| 595 | uint32_t pixclks_cntl = ((RREG32_PLL(RADEON_PIXCLKS_CNTL) & | ||
| 596 | ~(RADEON_PIX2CLK_SRC_SEL_MASK)) | | ||
| 597 | RADEON_PIX2CLK_SRC_SEL_P2PLLCLK); | ||
| 598 | |||
| 599 | WREG32_PLL_P(RADEON_PIXCLKS_CNTL, | ||
| 600 | RADEON_PIX2CLK_SRC_SEL_CPUCLK, | ||
| 601 | ~(RADEON_PIX2CLK_SRC_SEL_MASK)); | ||
| 602 | |||
| 603 | WREG32_PLL_P(RADEON_P2PLL_CNTL, | ||
| 604 | RADEON_P2PLL_RESET | ||
| 605 | | RADEON_P2PLL_ATOMIC_UPDATE_EN | ||
| 606 | | ((uint32_t)pll_gain << RADEON_P2PLL_PVG_SHIFT), | ||
| 607 | ~(RADEON_P2PLL_RESET | ||
| 608 | | RADEON_P2PLL_ATOMIC_UPDATE_EN | ||
| 609 | | RADEON_P2PLL_PVG_MASK)); | ||
| 610 | |||
| 611 | WREG32_PLL_P(RADEON_P2PLL_REF_DIV, | ||
| 612 | pll_ref_div, | ||
| 613 | ~RADEON_P2PLL_REF_DIV_MASK); | ||
| 614 | |||
| 615 | WREG32_PLL_P(RADEON_P2PLL_DIV_0, | ||
| 616 | pll_fb_post_div, | ||
| 617 | ~RADEON_P2PLL_FB0_DIV_MASK); | ||
| 618 | |||
| 619 | WREG32_PLL_P(RADEON_P2PLL_DIV_0, | ||
| 620 | pll_fb_post_div, | ||
| 621 | ~RADEON_P2PLL_POST0_DIV_MASK); | ||
| 622 | |||
| 623 | radeon_pll2_write_update(dev); | ||
| 624 | radeon_pll2_wait_for_read_update_complete(dev); | ||
| 625 | |||
| 626 | WREG32_PLL(RADEON_HTOTAL2_CNTL, htotal_cntl); | ||
| 627 | |||
| 628 | WREG32_PLL_P(RADEON_P2PLL_CNTL, | ||
| 629 | 0, | ||
| 630 | ~(RADEON_P2PLL_RESET | ||
| 631 | | RADEON_P2PLL_SLEEP | ||
| 632 | | RADEON_P2PLL_ATOMIC_UPDATE_EN)); | ||
| 633 | |||
| 634 | DRM_DEBUG("Wrote2: 0x%08x 0x%08x 0x%08x (0x%08x)\n", | ||
| 635 | (unsigned)pll_ref_div, | ||
| 636 | (unsigned)pll_fb_post_div, | ||
| 637 | (unsigned)htotal_cntl, | ||
| 638 | RREG32_PLL(RADEON_P2PLL_CNTL)); | ||
| 639 | DRM_DEBUG("Wrote2: rd=%u, fd=%u, pd=%u\n", | ||
| 640 | (unsigned)pll_ref_div & RADEON_P2PLL_REF_DIV_MASK, | ||
| 641 | (unsigned)pll_fb_post_div & RADEON_P2PLL_FB0_DIV_MASK, | ||
| 642 | (unsigned)((pll_fb_post_div & | ||
| 643 | RADEON_P2PLL_POST0_DIV_MASK) >> 16)); | ||
| 644 | |||
| 645 | mdelay(50); /* Let the clock to lock */ | ||
| 646 | |||
| 647 | WREG32_PLL_P(RADEON_PIXCLKS_CNTL, | ||
| 648 | RADEON_PIX2CLK_SRC_SEL_P2PLLCLK, | ||
| 649 | ~(RADEON_PIX2CLK_SRC_SEL_MASK)); | ||
| 650 | |||
| 651 | WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); | ||
| 652 | } else { | ||
| 653 | if (rdev->flags & RADEON_IS_MOBILITY) { | ||
| 654 | /* A temporal workaround for the occational blanking on certain laptop panels. | ||
| 655 | This appears to related to the PLL divider registers (fail to lock?). | ||
| 656 | It occurs even when all dividers are the same with their old settings. | ||
| 657 | In this case we really don't need to fiddle with PLL registers. | ||
| 658 | By doing this we can avoid the blanking problem with some panels. | ||
| 659 | */ | ||
| 660 | if ((pll_ref_div == (RREG32_PLL(RADEON_PPLL_REF_DIV) & RADEON_PPLL_REF_DIV_MASK)) && | ||
| 661 | (pll_fb_post_div == (RREG32_PLL(RADEON_PPLL_DIV_3) & | ||
| 662 | (RADEON_PPLL_POST3_DIV_MASK | RADEON_PPLL_FB3_DIV_MASK)))) { | ||
| 663 | WREG32_P(RADEON_CLOCK_CNTL_INDEX, | ||
| 664 | RADEON_PLL_DIV_SEL, | ||
| 665 | ~(RADEON_PLL_DIV_SEL)); | ||
| 666 | r100_pll_errata_after_index(rdev); | ||
| 667 | return; | ||
| 668 | } | ||
| 669 | } | ||
| 670 | |||
| 671 | WREG32_PLL_P(RADEON_VCLK_ECP_CNTL, | ||
| 672 | RADEON_VCLK_SRC_SEL_CPUCLK, | ||
| 673 | ~(RADEON_VCLK_SRC_SEL_MASK)); | ||
| 674 | WREG32_PLL_P(RADEON_PPLL_CNTL, | ||
| 675 | RADEON_PPLL_RESET | ||
| 676 | | RADEON_PPLL_ATOMIC_UPDATE_EN | ||
| 677 | | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN | ||
| 678 | | ((uint32_t)pll_gain << RADEON_PPLL_PVG_SHIFT), | ||
| 679 | ~(RADEON_PPLL_RESET | ||
| 680 | | RADEON_PPLL_ATOMIC_UPDATE_EN | ||
| 681 | | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN | ||
| 682 | | RADEON_PPLL_PVG_MASK)); | ||
| 683 | |||
| 684 | WREG32_P(RADEON_CLOCK_CNTL_INDEX, | ||
| 685 | RADEON_PLL_DIV_SEL, | ||
| 686 | ~(RADEON_PLL_DIV_SEL)); | ||
| 687 | r100_pll_errata_after_index(rdev); | ||
| 688 | |||
| 689 | if (ASIC_IS_R300(rdev) || | ||
| 690 | (rdev->family == CHIP_RS300) || | ||
| 691 | (rdev->family == CHIP_RS400) || | ||
| 692 | (rdev->family == CHIP_RS480)) { | ||
| 693 | if (pll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { | ||
| 694 | /* When restoring console mode, use saved PPLL_REF_DIV | ||
| 695 | * setting. | ||
| 696 | */ | ||
| 697 | WREG32_PLL_P(RADEON_PPLL_REF_DIV, | ||
| 698 | pll_ref_div, | ||
| 699 | 0); | ||
| 700 | } else { | ||
| 701 | /* R300 uses ref_div_acc field as real ref divider */ | ||
| 702 | WREG32_PLL_P(RADEON_PPLL_REF_DIV, | ||
| 703 | (pll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), | ||
| 704 | ~R300_PPLL_REF_DIV_ACC_MASK); | ||
| 705 | } | ||
| 706 | } else | ||
| 707 | WREG32_PLL_P(RADEON_PPLL_REF_DIV, | ||
| 708 | pll_ref_div, | ||
| 709 | ~RADEON_PPLL_REF_DIV_MASK); | ||
| 710 | |||
| 711 | WREG32_PLL_P(RADEON_PPLL_DIV_3, | ||
| 712 | pll_fb_post_div, | ||
| 713 | ~RADEON_PPLL_FB3_DIV_MASK); | ||
| 714 | |||
| 715 | WREG32_PLL_P(RADEON_PPLL_DIV_3, | ||
| 716 | pll_fb_post_div, | ||
| 717 | ~RADEON_PPLL_POST3_DIV_MASK); | ||
| 718 | |||
| 719 | radeon_pll_write_update(dev); | ||
| 720 | radeon_pll_wait_for_read_update_complete(dev); | ||
| 721 | |||
| 722 | WREG32_PLL(RADEON_HTOTAL_CNTL, htotal_cntl); | ||
| 723 | |||
| 724 | WREG32_PLL_P(RADEON_PPLL_CNTL, | ||
| 725 | 0, | ||
| 726 | ~(RADEON_PPLL_RESET | ||
| 727 | | RADEON_PPLL_SLEEP | ||
| 728 | | RADEON_PPLL_ATOMIC_UPDATE_EN | ||
| 729 | | RADEON_PPLL_VGA_ATOMIC_UPDATE_EN)); | ||
| 730 | |||
| 731 | DRM_DEBUG("Wrote: 0x%08x 0x%08x 0x%08x (0x%08x)\n", | ||
| 732 | pll_ref_div, | ||
| 733 | pll_fb_post_div, | ||
| 734 | (unsigned)htotal_cntl, | ||
| 735 | RREG32_PLL(RADEON_PPLL_CNTL)); | ||
| 736 | DRM_DEBUG("Wrote: rd=%d, fd=%d, pd=%d\n", | ||
| 737 | pll_ref_div & RADEON_PPLL_REF_DIV_MASK, | ||
| 738 | pll_fb_post_div & RADEON_PPLL_FB3_DIV_MASK, | ||
| 739 | (pll_fb_post_div & RADEON_PPLL_POST3_DIV_MASK) >> 16); | ||
| 740 | |||
| 741 | mdelay(50); /* Let the clock to lock */ | ||
| 742 | |||
| 743 | WREG32_PLL_P(RADEON_VCLK_ECP_CNTL, | ||
| 744 | RADEON_VCLK_SRC_SEL_PPLLCLK, | ||
| 745 | ~(RADEON_VCLK_SRC_SEL_MASK)); | ||
| 746 | |||
| 747 | } | ||
| 748 | } | ||
| 749 | |||
| 750 | static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc, | ||
| 751 | struct drm_display_mode *mode, | ||
| 752 | struct drm_display_mode *adjusted_mode) | ||
| 753 | { | ||
| 754 | return true; | ||
| 755 | } | ||
| 756 | |||
| 757 | static int radeon_crtc_mode_set(struct drm_crtc *crtc, | ||
| 758 | struct drm_display_mode *mode, | ||
| 759 | struct drm_display_mode *adjusted_mode, | ||
| 760 | int x, int y, struct drm_framebuffer *old_fb) | ||
| 761 | { | ||
| 762 | |||
| 763 | DRM_DEBUG("\n"); | ||
| 764 | |||
| 765 | /* TODO TV */ | ||
| 766 | |||
| 767 | radeon_crtc_set_base(crtc, x, y, old_fb); | ||
| 768 | radeon_set_crtc_timing(crtc, adjusted_mode); | ||
| 769 | radeon_set_pll(crtc, adjusted_mode); | ||
| 770 | radeon_init_disp_bandwidth(crtc->dev); | ||
| 771 | |||
| 772 | return 0; | ||
| 773 | } | ||
| 774 | |||
| 775 | static void radeon_crtc_prepare(struct drm_crtc *crtc) | ||
| 776 | { | ||
| 777 | radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); | ||
| 778 | } | ||
| 779 | |||
| 780 | static void radeon_crtc_commit(struct drm_crtc *crtc) | ||
| 781 | { | ||
| 782 | radeon_crtc_dpms(crtc, DRM_MODE_DPMS_ON); | ||
| 783 | } | ||
| 784 | |||
| 785 | static const struct drm_crtc_helper_funcs legacy_helper_funcs = { | ||
| 786 | .dpms = radeon_crtc_dpms, | ||
| 787 | .mode_fixup = radeon_crtc_mode_fixup, | ||
| 788 | .mode_set = radeon_crtc_mode_set, | ||
| 789 | .mode_set_base = radeon_crtc_set_base, | ||
| 790 | .prepare = radeon_crtc_prepare, | ||
| 791 | .commit = radeon_crtc_commit, | ||
| 792 | }; | ||
| 793 | |||
| 794 | |||
| 795 | void radeon_legacy_init_crtc(struct drm_device *dev, | ||
| 796 | struct radeon_crtc *radeon_crtc) | ||
| 797 | { | ||
| 798 | if (radeon_crtc->crtc_id == 1) | ||
| 799 | radeon_crtc->crtc_offset = RADEON_CRTC2_H_TOTAL_DISP - RADEON_CRTC_H_TOTAL_DISP; | ||
| 800 | drm_crtc_helper_add(&radeon_crtc->base, &legacy_helper_funcs); | ||
| 801 | } | ||
| 802 | |||
| 803 | void radeon_init_disp_bw_legacy(struct drm_device *dev, | ||
| 804 | struct drm_display_mode *mode1, | ||
| 805 | uint32_t pixel_bytes1, | ||
| 806 | struct drm_display_mode *mode2, | ||
| 807 | uint32_t pixel_bytes2) | ||
| 808 | { | ||
| 809 | struct radeon_device *rdev = dev->dev_private; | ||
| 810 | fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff; | ||
| 811 | fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff; | ||
| 812 | fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff; | ||
| 813 | uint32_t temp, data, mem_trcd, mem_trp, mem_tras; | ||
| 814 | fixed20_12 memtcas_ff[8] = { | ||
| 815 | fixed_init(1), | ||
| 816 | fixed_init(2), | ||
| 817 | fixed_init(3), | ||
| 818 | fixed_init(0), | ||
| 819 | fixed_init_half(1), | ||
| 820 | fixed_init_half(2), | ||
| 821 | fixed_init(0), | ||
| 822 | }; | ||
| 823 | fixed20_12 memtcas_rs480_ff[8] = { | ||
| 824 | fixed_init(0), | ||
| 825 | fixed_init(1), | ||
| 826 | fixed_init(2), | ||
| 827 | fixed_init(3), | ||
| 828 | fixed_init(0), | ||
| 829 | fixed_init_half(1), | ||
| 830 | fixed_init_half(2), | ||
| 831 | fixed_init_half(3), | ||
| 832 | }; | ||
| 833 | fixed20_12 memtcas2_ff[8] = { | ||
| 834 | fixed_init(0), | ||
| 835 | fixed_init(1), | ||
| 836 | fixed_init(2), | ||
| 837 | fixed_init(3), | ||
| 838 | fixed_init(4), | ||
| 839 | fixed_init(5), | ||
| 840 | fixed_init(6), | ||
| 841 | fixed_init(7), | ||
| 842 | }; | ||
| 843 | fixed20_12 memtrbs[8] = { | ||
| 844 | fixed_init(1), | ||
| 845 | fixed_init_half(1), | ||
| 846 | fixed_init(2), | ||
| 847 | fixed_init_half(2), | ||
| 848 | fixed_init(3), | ||
| 849 | fixed_init_half(3), | ||
| 850 | fixed_init(4), | ||
| 851 | fixed_init_half(4) | ||
| 852 | }; | ||
| 853 | fixed20_12 memtrbs_r4xx[8] = { | ||
| 854 | fixed_init(4), | ||
| 855 | fixed_init(5), | ||
| 856 | fixed_init(6), | ||
| 857 | fixed_init(7), | ||
| 858 | fixed_init(8), | ||
| 859 | fixed_init(9), | ||
| 860 | fixed_init(10), | ||
| 861 | fixed_init(11) | ||
| 862 | }; | ||
| 863 | fixed20_12 min_mem_eff; | ||
| 864 | fixed20_12 mc_latency_sclk, mc_latency_mclk, k1; | ||
| 865 | fixed20_12 cur_latency_mclk, cur_latency_sclk; | ||
| 866 | fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate, | ||
| 867 | disp_drain_rate2, read_return_rate; | ||
| 868 | fixed20_12 time_disp1_drop_priority; | ||
| 869 | int c; | ||
| 870 | int cur_size = 16; /* in octawords */ | ||
| 871 | int critical_point = 0, critical_point2; | ||
| 872 | /* uint32_t read_return_rate, time_disp1_drop_priority; */ | ||
| 873 | int stop_req, max_stop_req; | ||
| 874 | |||
| 875 | min_mem_eff.full = rfixed_const_8(0); | ||
| 876 | /* get modes */ | ||
| 877 | if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) { | ||
| 878 | uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER); | ||
| 879 | mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT); | ||
| 880 | mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT); | ||
| 881 | /* check crtc enables */ | ||
| 882 | if (mode2) | ||
| 883 | mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); | ||
| 884 | if (mode1) | ||
| 885 | mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); | ||
| 886 | WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); | ||
| 887 | } | ||
| 888 | |||
| 889 | /* | ||
| 890 | * determine is there is enough bw for current mode | ||
| 891 | */ | ||
| 892 | mclk_ff.full = rfixed_const(rdev->clock.default_mclk); | ||
| 893 | temp_ff.full = rfixed_const(100); | ||
| 894 | mclk_ff.full = rfixed_div(mclk_ff, temp_ff); | ||
| 895 | sclk_ff.full = rfixed_const(rdev->clock.default_sclk); | ||
| 896 | sclk_ff.full = rfixed_div(sclk_ff, temp_ff); | ||
| 897 | |||
| 898 | temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); | ||
| 899 | temp_ff.full = rfixed_const(temp); | ||
| 900 | mem_bw.full = rfixed_mul(mclk_ff, temp_ff); | ||
| 901 | |||
| 902 | pix_clk.full = 0; | ||
| 903 | pix_clk2.full = 0; | ||
| 904 | peak_disp_bw.full = 0; | ||
| 905 | if (mode1) { | ||
| 906 | temp_ff.full = rfixed_const(1000); | ||
| 907 | pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */ | ||
| 908 | pix_clk.full = rfixed_div(pix_clk, temp_ff); | ||
| 909 | temp_ff.full = rfixed_const(pixel_bytes1); | ||
| 910 | peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff); | ||
| 911 | } | ||
| 912 | if (mode2) { | ||
| 913 | temp_ff.full = rfixed_const(1000); | ||
| 914 | pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */ | ||
| 915 | pix_clk2.full = rfixed_div(pix_clk2, temp_ff); | ||
| 916 | temp_ff.full = rfixed_const(pixel_bytes2); | ||
| 917 | peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff); | ||
| 918 | } | ||
| 919 | |||
| 920 | mem_bw.full = rfixed_mul(mem_bw, min_mem_eff); | ||
| 921 | if (peak_disp_bw.full >= mem_bw.full) { | ||
| 922 | DRM_ERROR("You may not have enough display bandwidth for current mode\n" | ||
| 923 | "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); | ||
| 924 | } | ||
| 925 | |||
| 926 | /* Get values from the EXT_MEM_CNTL register...converting its contents. */ | ||
| 927 | temp = RREG32(RADEON_MEM_TIMING_CNTL); | ||
| 928 | if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */ | ||
| 929 | mem_trcd = ((temp >> 2) & 0x3) + 1; | ||
| 930 | mem_trp = ((temp & 0x3)) + 1; | ||
| 931 | mem_tras = ((temp & 0x70) >> 4) + 1; | ||
| 932 | } else if (rdev->family == CHIP_R300 || | ||
| 933 | rdev->family == CHIP_R350) { /* r300, r350 */ | ||
| 934 | mem_trcd = (temp & 0x7) + 1; | ||
| 935 | mem_trp = ((temp >> 8) & 0x7) + 1; | ||
| 936 | mem_tras = ((temp >> 11) & 0xf) + 4; | ||
| 937 | } else if (rdev->family == CHIP_RV350 || | ||
| 938 | rdev->family <= CHIP_RV380) { | ||
| 939 | /* rv3x0 */ | ||
| 940 | mem_trcd = (temp & 0x7) + 3; | ||
| 941 | mem_trp = ((temp >> 8) & 0x7) + 3; | ||
| 942 | mem_tras = ((temp >> 11) & 0xf) + 6; | ||
| 943 | } else if (rdev->family == CHIP_R420 || | ||
| 944 | rdev->family == CHIP_R423 || | ||
| 945 | rdev->family == CHIP_RV410) { | ||
| 946 | /* r4xx */ | ||
| 947 | mem_trcd = (temp & 0xf) + 3; | ||
| 948 | if (mem_trcd > 15) | ||
| 949 | mem_trcd = 15; | ||
| 950 | mem_trp = ((temp >> 8) & 0xf) + 3; | ||
| 951 | if (mem_trp > 15) | ||
| 952 | mem_trp = 15; | ||
| 953 | mem_tras = ((temp >> 12) & 0x1f) + 6; | ||
| 954 | if (mem_tras > 31) | ||
| 955 | mem_tras = 31; | ||
| 956 | } else { /* RV200, R200 */ | ||
| 957 | mem_trcd = (temp & 0x7) + 1; | ||
| 958 | mem_trp = ((temp >> 8) & 0x7) + 1; | ||
| 959 | mem_tras = ((temp >> 12) & 0xf) + 4; | ||
| 960 | } | ||
| 961 | /* convert to FF */ | ||
| 962 | trcd_ff.full = rfixed_const(mem_trcd); | ||
| 963 | trp_ff.full = rfixed_const(mem_trp); | ||
| 964 | tras_ff.full = rfixed_const(mem_tras); | ||
| 965 | |||
| 966 | /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ | ||
| 967 | temp = RREG32(RADEON_MEM_SDRAM_MODE_REG); | ||
| 968 | data = (temp & (7 << 20)) >> 20; | ||
| 969 | if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) { | ||
| 970 | if (rdev->family == CHIP_RS480) /* don't think rs400 */ | ||
| 971 | tcas_ff = memtcas_rs480_ff[data]; | ||
| 972 | else | ||
| 973 | tcas_ff = memtcas_ff[data]; | ||
| 974 | } else | ||
| 975 | tcas_ff = memtcas2_ff[data]; | ||
| 976 | |||
| 977 | if (rdev->family == CHIP_RS400 || | ||
| 978 | rdev->family == CHIP_RS480) { | ||
| 979 | /* extra cas latency stored in bits 23-25 0-4 clocks */ | ||
| 980 | data = (temp >> 23) & 0x7; | ||
| 981 | if (data < 5) | ||
| 982 | tcas_ff.full += rfixed_const(data); | ||
| 983 | } | ||
| 984 | |||
| 985 | if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) { | ||
| 986 | /* on the R300, Tcas is included in Trbs. | ||
| 987 | */ | ||
| 988 | temp = RREG32(RADEON_MEM_CNTL); | ||
| 989 | data = (R300_MEM_NUM_CHANNELS_MASK & temp); | ||
| 990 | if (data == 1) { | ||
| 991 | if (R300_MEM_USE_CD_CH_ONLY & temp) { | ||
| 992 | temp = RREG32(R300_MC_IND_INDEX); | ||
| 993 | temp &= ~R300_MC_IND_ADDR_MASK; | ||
| 994 | temp |= R300_MC_READ_CNTL_CD_mcind; | ||
| 995 | WREG32(R300_MC_IND_INDEX, temp); | ||
| 996 | temp = RREG32(R300_MC_IND_DATA); | ||
| 997 | data = (R300_MEM_RBS_POSITION_C_MASK & temp); | ||
| 998 | } else { | ||
| 999 | temp = RREG32(R300_MC_READ_CNTL_AB); | ||
| 1000 | data = (R300_MEM_RBS_POSITION_A_MASK & temp); | ||
| 1001 | } | ||
| 1002 | } else { | ||
| 1003 | temp = RREG32(R300_MC_READ_CNTL_AB); | ||
| 1004 | data = (R300_MEM_RBS_POSITION_A_MASK & temp); | ||
| 1005 | } | ||
| 1006 | if (rdev->family == CHIP_RV410 || | ||
| 1007 | rdev->family == CHIP_R420 || | ||
| 1008 | rdev->family == CHIP_R423) | ||
| 1009 | trbs_ff = memtrbs_r4xx[data]; | ||
| 1010 | else | ||
| 1011 | trbs_ff = memtrbs[data]; | ||
| 1012 | tcas_ff.full += trbs_ff.full; | ||
| 1013 | } | ||
| 1014 | |||
| 1015 | sclk_eff_ff.full = sclk_ff.full; | ||
| 1016 | |||
| 1017 | if (rdev->flags & RADEON_IS_AGP) { | ||
| 1018 | fixed20_12 agpmode_ff; | ||
| 1019 | agpmode_ff.full = rfixed_const(radeon_agpmode); | ||
| 1020 | temp_ff.full = rfixed_const_666(16); | ||
| 1021 | sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff); | ||
| 1022 | } | ||
| 1023 | /* TODO PCIE lanes may affect this - agpmode == 16?? */ | ||
| 1024 | |||
| 1025 | if (ASIC_IS_R300(rdev)) { | ||
| 1026 | sclk_delay_ff.full = rfixed_const(250); | ||
| 1027 | } else { | ||
| 1028 | if ((rdev->family == CHIP_RV100) || | ||
| 1029 | rdev->flags & RADEON_IS_IGP) { | ||
| 1030 | if (rdev->mc.vram_is_ddr) | ||
| 1031 | sclk_delay_ff.full = rfixed_const(41); | ||
| 1032 | else | ||
| 1033 | sclk_delay_ff.full = rfixed_const(33); | ||
| 1034 | } else { | ||
| 1035 | if (rdev->mc.vram_width == 128) | ||
| 1036 | sclk_delay_ff.full = rfixed_const(57); | ||
| 1037 | else | ||
| 1038 | sclk_delay_ff.full = rfixed_const(41); | ||
| 1039 | } | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff); | ||
| 1043 | |||
| 1044 | if (rdev->mc.vram_is_ddr) { | ||
| 1045 | if (rdev->mc.vram_width == 32) { | ||
| 1046 | k1.full = rfixed_const(40); | ||
| 1047 | c = 3; | ||
| 1048 | } else { | ||
| 1049 | k1.full = rfixed_const(20); | ||
| 1050 | c = 1; | ||
| 1051 | } | ||
| 1052 | } else { | ||
| 1053 | k1.full = rfixed_const(40); | ||
| 1054 | c = 3; | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | temp_ff.full = rfixed_const(2); | ||
| 1058 | mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff); | ||
| 1059 | temp_ff.full = rfixed_const(c); | ||
| 1060 | mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff); | ||
| 1061 | temp_ff.full = rfixed_const(4); | ||
| 1062 | mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff); | ||
| 1063 | mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff); | ||
| 1064 | mc_latency_mclk.full += k1.full; | ||
| 1065 | |||
| 1066 | mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff); | ||
| 1067 | mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff); | ||
| 1068 | |||
| 1069 | /* | ||
| 1070 | HW cursor time assuming worst case of full size colour cursor. | ||
| 1071 | */ | ||
| 1072 | temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1)))); | ||
| 1073 | temp_ff.full += trcd_ff.full; | ||
| 1074 | if (temp_ff.full < tras_ff.full) | ||
| 1075 | temp_ff.full = tras_ff.full; | ||
| 1076 | cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff); | ||
| 1077 | |||
| 1078 | temp_ff.full = rfixed_const(cur_size); | ||
| 1079 | cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff); | ||
| 1080 | /* | ||
| 1081 | Find the total latency for the display data. | ||
| 1082 | */ | ||
| 1083 | disp_latency_overhead.full = rfixed_const(80); | ||
| 1084 | disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff); | ||
| 1085 | mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full; | ||
| 1086 | mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full; | ||
| 1087 | |||
| 1088 | if (mc_latency_mclk.full > mc_latency_sclk.full) | ||
| 1089 | disp_latency.full = mc_latency_mclk.full; | ||
| 1090 | else | ||
| 1091 | disp_latency.full = mc_latency_sclk.full; | ||
| 1092 | |||
| 1093 | /* setup Max GRPH_STOP_REQ default value */ | ||
| 1094 | if (ASIC_IS_RV100(rdev)) | ||
| 1095 | max_stop_req = 0x5c; | ||
| 1096 | else | ||
| 1097 | max_stop_req = 0x7c; | ||
| 1098 | |||
| 1099 | if (mode1) { | ||
| 1100 | /* CRTC1 | ||
| 1101 | Set GRPH_BUFFER_CNTL register using h/w defined optimal values. | ||
| 1102 | GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] | ||
| 1103 | */ | ||
| 1104 | stop_req = mode1->hdisplay * pixel_bytes1 / 16; | ||
| 1105 | |||
| 1106 | if (stop_req > max_stop_req) | ||
| 1107 | stop_req = max_stop_req; | ||
| 1108 | |||
| 1109 | /* | ||
| 1110 | Find the drain rate of the display buffer. | ||
| 1111 | */ | ||
| 1112 | temp_ff.full = rfixed_const((16/pixel_bytes1)); | ||
| 1113 | disp_drain_rate.full = rfixed_div(pix_clk, temp_ff); | ||
| 1114 | |||
| 1115 | /* | ||
| 1116 | Find the critical point of the display buffer. | ||
| 1117 | */ | ||
| 1118 | crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency); | ||
| 1119 | crit_point_ff.full += rfixed_const_half(0); | ||
| 1120 | |||
| 1121 | critical_point = rfixed_trunc(crit_point_ff); | ||
| 1122 | |||
| 1123 | if (rdev->disp_priority == 2) { | ||
| 1124 | critical_point = 0; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | /* | ||
| 1128 | The critical point should never be above max_stop_req-4. Setting | ||
| 1129 | GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. | ||
| 1130 | */ | ||
| 1131 | if (max_stop_req - critical_point < 4) | ||
| 1132 | critical_point = 0; | ||
| 1133 | |||
| 1134 | if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) { | ||
| 1135 | /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ | ||
| 1136 | critical_point = 0x10; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | temp = RREG32(RADEON_GRPH_BUFFER_CNTL); | ||
| 1140 | temp &= ~(RADEON_GRPH_STOP_REQ_MASK); | ||
| 1141 | temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); | ||
| 1142 | temp &= ~(RADEON_GRPH_START_REQ_MASK); | ||
| 1143 | if ((rdev->family == CHIP_R350) && | ||
| 1144 | (stop_req > 0x15)) { | ||
| 1145 | stop_req -= 0x10; | ||
| 1146 | } | ||
| 1147 | temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); | ||
| 1148 | temp |= RADEON_GRPH_BUFFER_SIZE; | ||
| 1149 | temp &= ~(RADEON_GRPH_CRITICAL_CNTL | | ||
| 1150 | RADEON_GRPH_CRITICAL_AT_SOF | | ||
| 1151 | RADEON_GRPH_STOP_CNTL); | ||
| 1152 | /* | ||
| 1153 | Write the result into the register. | ||
| 1154 | */ | ||
| 1155 | WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | | ||
| 1156 | (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); | ||
| 1157 | |||
| 1158 | #if 0 | ||
| 1159 | if ((rdev->family == CHIP_RS400) || | ||
| 1160 | (rdev->family == CHIP_RS480)) { | ||
| 1161 | /* attempt to program RS400 disp regs correctly ??? */ | ||
| 1162 | temp = RREG32(RS400_DISP1_REG_CNTL); | ||
| 1163 | temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK | | ||
| 1164 | RS400_DISP1_STOP_REQ_LEVEL_MASK); | ||
| 1165 | WREG32(RS400_DISP1_REQ_CNTL1, (temp | | ||
| 1166 | (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) | | ||
| 1167 | (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); | ||
| 1168 | temp = RREG32(RS400_DMIF_MEM_CNTL1); | ||
| 1169 | temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK | | ||
| 1170 | RS400_DISP1_CRITICAL_POINT_STOP_MASK); | ||
| 1171 | WREG32(RS400_DMIF_MEM_CNTL1, (temp | | ||
| 1172 | (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) | | ||
| 1173 | (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT))); | ||
| 1174 | } | ||
| 1175 | #endif | ||
| 1176 | |||
| 1177 | DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n", | ||
| 1178 | /* (unsigned int)info->SavedReg->grph_buffer_cntl, */ | ||
| 1179 | (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL)); | ||
| 1180 | } | ||
| 1181 | |||
| 1182 | if (mode2) { | ||
| 1183 | u32 grph2_cntl; | ||
| 1184 | stop_req = mode2->hdisplay * pixel_bytes2 / 16; | ||
| 1185 | |||
| 1186 | if (stop_req > max_stop_req) | ||
| 1187 | stop_req = max_stop_req; | ||
| 1188 | |||
| 1189 | /* | ||
| 1190 | Find the drain rate of the display buffer. | ||
| 1191 | */ | ||
| 1192 | temp_ff.full = rfixed_const((16/pixel_bytes2)); | ||
| 1193 | disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff); | ||
| 1194 | |||
| 1195 | grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL); | ||
| 1196 | grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK); | ||
| 1197 | grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); | ||
| 1198 | grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK); | ||
| 1199 | if ((rdev->family == CHIP_R350) && | ||
| 1200 | (stop_req > 0x15)) { | ||
| 1201 | stop_req -= 0x10; | ||
| 1202 | } | ||
| 1203 | grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); | ||
| 1204 | grph2_cntl |= RADEON_GRPH_BUFFER_SIZE; | ||
| 1205 | grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL | | ||
| 1206 | RADEON_GRPH_CRITICAL_AT_SOF | | ||
| 1207 | RADEON_GRPH_STOP_CNTL); | ||
| 1208 | |||
| 1209 | if ((rdev->family == CHIP_RS100) || | ||
| 1210 | (rdev->family == CHIP_RS200)) | ||
| 1211 | critical_point2 = 0; | ||
| 1212 | else { | ||
| 1213 | temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128; | ||
| 1214 | temp_ff.full = rfixed_const(temp); | ||
| 1215 | temp_ff.full = rfixed_mul(mclk_ff, temp_ff); | ||
| 1216 | if (sclk_ff.full < temp_ff.full) | ||
| 1217 | temp_ff.full = sclk_ff.full; | ||
| 1218 | |||
| 1219 | read_return_rate.full = temp_ff.full; | ||
| 1220 | |||
| 1221 | if (mode1) { | ||
| 1222 | temp_ff.full = read_return_rate.full - disp_drain_rate.full; | ||
| 1223 | time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff); | ||
| 1224 | } else { | ||
| 1225 | time_disp1_drop_priority.full = 0; | ||
| 1226 | } | ||
| 1227 | crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full; | ||
| 1228 | crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2); | ||
| 1229 | crit_point_ff.full += rfixed_const_half(0); | ||
| 1230 | |||
| 1231 | critical_point2 = rfixed_trunc(crit_point_ff); | ||
| 1232 | |||
| 1233 | if (rdev->disp_priority == 2) { | ||
| 1234 | critical_point2 = 0; | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | if (max_stop_req - critical_point2 < 4) | ||
| 1238 | critical_point2 = 0; | ||
| 1239 | |||
| 1240 | } | ||
| 1241 | |||
| 1242 | if (critical_point2 == 0 && rdev->family == CHIP_R300) { | ||
| 1243 | /* some R300 cards have problem with this set to 0 */ | ||
| 1244 | critical_point2 = 0x10; | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) | | ||
| 1248 | (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); | ||
| 1249 | |||
| 1250 | if ((rdev->family == CHIP_RS400) || | ||
| 1251 | (rdev->family == CHIP_RS480)) { | ||
| 1252 | #if 0 | ||
| 1253 | /* attempt to program RS400 disp2 regs correctly ??? */ | ||
| 1254 | temp = RREG32(RS400_DISP2_REQ_CNTL1); | ||
| 1255 | temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK | | ||
| 1256 | RS400_DISP2_STOP_REQ_LEVEL_MASK); | ||
| 1257 | WREG32(RS400_DISP2_REQ_CNTL1, (temp | | ||
| 1258 | (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) | | ||
| 1259 | (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); | ||
| 1260 | temp = RREG32(RS400_DISP2_REQ_CNTL2); | ||
| 1261 | temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK | | ||
| 1262 | RS400_DISP2_CRITICAL_POINT_STOP_MASK); | ||
| 1263 | WREG32(RS400_DISP2_REQ_CNTL2, (temp | | ||
| 1264 | (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) | | ||
| 1265 | (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT))); | ||
| 1266 | #endif | ||
| 1267 | WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC); | ||
| 1268 | WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000); | ||
| 1269 | WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC); | ||
| 1270 | WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC); | ||
| 1271 | } | ||
| 1272 | |||
| 1273 | DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n", | ||
| 1274 | (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); | ||
| 1275 | } | ||
| 1276 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c new file mode 100644 index 000000000000..2c2f42de1d4c --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c | |||
| @@ -0,0 +1,1288 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2007-8 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * copy of this software and associated documentation files (the "Software"), | ||
| 7 | * to deal in the Software without restriction, including without limitation | ||
| 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 10 | * Software is furnished to do so, subject to the following conditions: | ||
| 11 | * | ||
| 12 | * The above copyright notice and this permission notice shall be included in | ||
| 13 | * all copies or substantial portions of the Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 19 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 20 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 21 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: Dave Airlie | ||
| 24 | * Alex Deucher | ||
| 25 | */ | ||
| 26 | #include "drmP.h" | ||
| 27 | #include "drm_crtc_helper.h" | ||
| 28 | #include "radeon_drm.h" | ||
| 29 | #include "radeon.h" | ||
| 30 | #include "atom.h" | ||
| 31 | |||
| 32 | |||
| 33 | static void radeon_legacy_rmx_mode_set(struct drm_encoder *encoder, | ||
| 34 | struct drm_display_mode *mode, | ||
| 35 | struct drm_display_mode *adjusted_mode) | ||
| 36 | { | ||
| 37 | struct drm_device *dev = encoder->dev; | ||
| 38 | struct radeon_device *rdev = dev->dev_private; | ||
| 39 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 40 | int xres = mode->hdisplay; | ||
| 41 | int yres = mode->vdisplay; | ||
| 42 | bool hscale = true, vscale = true; | ||
| 43 | int hsync_wid; | ||
| 44 | int vsync_wid; | ||
| 45 | int hsync_start; | ||
| 46 | uint32_t scale, inc; | ||
| 47 | uint32_t fp_horz_stretch, fp_vert_stretch, crtc_more_cntl, fp_horz_vert_active; | ||
| 48 | uint32_t fp_h_sync_strt_wid, fp_v_sync_strt_wid, fp_crtc_h_total_disp, fp_crtc_v_total_disp; | ||
| 49 | struct radeon_native_mode *native_mode = &radeon_encoder->native_mode; | ||
| 50 | |||
| 51 | DRM_DEBUG("\n"); | ||
| 52 | |||
| 53 | fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) & | ||
| 54 | (RADEON_VERT_STRETCH_RESERVED | | ||
| 55 | RADEON_VERT_AUTO_RATIO_INC); | ||
| 56 | fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH) & | ||
| 57 | (RADEON_HORZ_FP_LOOP_STRETCH | | ||
| 58 | RADEON_HORZ_AUTO_RATIO_INC); | ||
| 59 | |||
| 60 | crtc_more_cntl = 0; | ||
| 61 | if ((rdev->family == CHIP_RS100) || | ||
| 62 | (rdev->family == CHIP_RS200)) { | ||
| 63 | /* This is to workaround the asic bug for RMX, some versions | ||
| 64 | of BIOS dosen't have this register initialized correctly. */ | ||
| 65 | crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN; | ||
| 66 | } | ||
| 67 | |||
| 68 | |||
| 69 | fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff) | ||
| 70 | | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); | ||
| 71 | |||
| 72 | hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; | ||
| 73 | if (!hsync_wid) | ||
| 74 | hsync_wid = 1; | ||
| 75 | hsync_start = mode->crtc_hsync_start - 8; | ||
| 76 | |||
| 77 | fp_h_sync_strt_wid = ((hsync_start & 0x1fff) | ||
| 78 | | ((hsync_wid & 0x3f) << 16) | ||
| 79 | | ((mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
| 80 | ? RADEON_CRTC_H_SYNC_POL | ||
| 81 | : 0)); | ||
| 82 | |||
| 83 | fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff) | ||
| 84 | | ((mode->crtc_vdisplay - 1) << 16)); | ||
| 85 | |||
| 86 | vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; | ||
| 87 | if (!vsync_wid) | ||
| 88 | vsync_wid = 1; | ||
| 89 | |||
| 90 | fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff) | ||
| 91 | | ((vsync_wid & 0x1f) << 16) | ||
| 92 | | ((mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
| 93 | ? RADEON_CRTC_V_SYNC_POL | ||
| 94 | : 0)); | ||
| 95 | |||
| 96 | fp_horz_vert_active = 0; | ||
| 97 | |||
| 98 | if (native_mode->panel_xres == 0 || | ||
| 99 | native_mode->panel_yres == 0) { | ||
| 100 | hscale = false; | ||
| 101 | vscale = false; | ||
| 102 | } else { | ||
| 103 | if (xres > native_mode->panel_xres) | ||
| 104 | xres = native_mode->panel_xres; | ||
| 105 | if (yres > native_mode->panel_yres) | ||
| 106 | yres = native_mode->panel_yres; | ||
| 107 | |||
| 108 | if (xres == native_mode->panel_xres) | ||
| 109 | hscale = false; | ||
| 110 | if (yres == native_mode->panel_yres) | ||
| 111 | vscale = false; | ||
| 112 | } | ||
| 113 | |||
| 114 | if (radeon_encoder->flags & RADEON_USE_RMX) { | ||
| 115 | if (radeon_encoder->rmx_type != RMX_CENTER) { | ||
| 116 | if (!hscale) | ||
| 117 | fp_horz_stretch |= ((xres/8-1) << 16); | ||
| 118 | else { | ||
| 119 | inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0; | ||
| 120 | scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX) | ||
| 121 | / native_mode->panel_xres + 1; | ||
| 122 | fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) | | ||
| 123 | RADEON_HORZ_STRETCH_BLEND | | ||
| 124 | RADEON_HORZ_STRETCH_ENABLE | | ||
| 125 | ((native_mode->panel_xres/8-1) << 16)); | ||
| 126 | } | ||
| 127 | |||
| 128 | if (!vscale) | ||
| 129 | fp_vert_stretch |= ((yres-1) << 12); | ||
| 130 | else { | ||
| 131 | inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0; | ||
| 132 | scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX) | ||
| 133 | / native_mode->panel_yres + 1; | ||
| 134 | fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) | | ||
| 135 | RADEON_VERT_STRETCH_ENABLE | | ||
| 136 | RADEON_VERT_STRETCH_BLEND | | ||
| 137 | ((native_mode->panel_yres-1) << 12)); | ||
| 138 | } | ||
| 139 | } else if (radeon_encoder->rmx_type == RMX_CENTER) { | ||
| 140 | int blank_width; | ||
| 141 | |||
| 142 | fp_horz_stretch |= ((xres/8-1) << 16); | ||
| 143 | fp_vert_stretch |= ((yres-1) << 12); | ||
| 144 | |||
| 145 | crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN | | ||
| 146 | RADEON_CRTC_AUTO_VERT_CENTER_EN); | ||
| 147 | |||
| 148 | blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8; | ||
| 149 | if (blank_width > 110) | ||
| 150 | blank_width = 110; | ||
| 151 | |||
| 152 | fp_crtc_h_total_disp = (((blank_width) & 0x3ff) | ||
| 153 | | ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16)); | ||
| 154 | |||
| 155 | hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8; | ||
| 156 | if (!hsync_wid) | ||
| 157 | hsync_wid = 1; | ||
| 158 | |||
| 159 | fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff) | ||
| 160 | | ((hsync_wid & 0x3f) << 16) | ||
| 161 | | ((mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
| 162 | ? RADEON_CRTC_H_SYNC_POL | ||
| 163 | : 0)); | ||
| 164 | |||
| 165 | fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff) | ||
| 166 | | ((mode->crtc_vdisplay - 1) << 16)); | ||
| 167 | |||
| 168 | vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start; | ||
| 169 | if (!vsync_wid) | ||
| 170 | vsync_wid = 1; | ||
| 171 | |||
| 172 | fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff) | ||
| 173 | | ((vsync_wid & 0x1f) << 16) | ||
| 174 | | ((mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
| 175 | ? RADEON_CRTC_V_SYNC_POL | ||
| 176 | : 0))); | ||
| 177 | |||
| 178 | fp_horz_vert_active = (((native_mode->panel_yres) & 0xfff) | | ||
| 179 | (((native_mode->panel_xres / 8) & 0x1ff) << 16)); | ||
| 180 | } | ||
| 181 | } else { | ||
| 182 | fp_horz_stretch |= ((xres/8-1) << 16); | ||
| 183 | fp_vert_stretch |= ((yres-1) << 12); | ||
| 184 | } | ||
| 185 | |||
| 186 | WREG32(RADEON_FP_HORZ_STRETCH, fp_horz_stretch); | ||
| 187 | WREG32(RADEON_FP_VERT_STRETCH, fp_vert_stretch); | ||
| 188 | WREG32(RADEON_CRTC_MORE_CNTL, crtc_more_cntl); | ||
| 189 | WREG32(RADEON_FP_HORZ_VERT_ACTIVE, fp_horz_vert_active); | ||
| 190 | WREG32(RADEON_FP_H_SYNC_STRT_WID, fp_h_sync_strt_wid); | ||
| 191 | WREG32(RADEON_FP_V_SYNC_STRT_WID, fp_v_sync_strt_wid); | ||
| 192 | WREG32(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp); | ||
| 193 | WREG32(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp); | ||
| 194 | |||
| 195 | } | ||
| 196 | |||
| 197 | static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) | ||
| 198 | { | ||
| 199 | struct drm_device *dev = encoder->dev; | ||
| 200 | struct radeon_device *rdev = dev->dev_private; | ||
| 201 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 202 | uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man; | ||
| 203 | int panel_pwr_delay = 2000; | ||
| 204 | DRM_DEBUG("\n"); | ||
| 205 | |||
| 206 | if (radeon_encoder->enc_priv) { | ||
| 207 | if (rdev->is_atom_bios) { | ||
| 208 | struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv; | ||
| 209 | panel_pwr_delay = lvds->panel_pwr_delay; | ||
| 210 | } else { | ||
| 211 | struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv; | ||
| 212 | panel_pwr_delay = lvds->panel_pwr_delay; | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 216 | switch (mode) { | ||
| 217 | case DRM_MODE_DPMS_ON: | ||
| 218 | disp_pwr_man = RREG32(RADEON_DISP_PWR_MAN); | ||
| 219 | disp_pwr_man |= RADEON_AUTO_PWRUP_EN; | ||
| 220 | WREG32(RADEON_DISP_PWR_MAN, disp_pwr_man); | ||
| 221 | lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); | ||
| 222 | lvds_pll_cntl |= RADEON_LVDS_PLL_EN; | ||
| 223 | WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); | ||
| 224 | udelay(1000); | ||
| 225 | |||
| 226 | lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); | ||
| 227 | lvds_pll_cntl &= ~RADEON_LVDS_PLL_RESET; | ||
| 228 | WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); | ||
| 229 | |||
| 230 | lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); | ||
| 231 | lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN | RADEON_LVDS_DIGON | RADEON_LVDS_BLON); | ||
| 232 | lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS); | ||
| 233 | udelay(panel_pwr_delay * 1000); | ||
| 234 | WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); | ||
| 235 | break; | ||
| 236 | case DRM_MODE_DPMS_STANDBY: | ||
| 237 | case DRM_MODE_DPMS_SUSPEND: | ||
| 238 | case DRM_MODE_DPMS_OFF: | ||
| 239 | pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); | ||
| 240 | WREG32_PLL_P(RADEON_PIXCLKS_CNTL, 0, ~RADEON_PIXCLK_LVDS_ALWAYS_ONb); | ||
| 241 | lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); | ||
| 242 | lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; | ||
| 243 | lvds_gen_cntl &= ~(RADEON_LVDS_ON | RADEON_LVDS_BLON | RADEON_LVDS_EN | RADEON_LVDS_DIGON); | ||
| 244 | udelay(panel_pwr_delay * 1000); | ||
| 245 | WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); | ||
| 246 | WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); | ||
| 247 | break; | ||
| 248 | } | ||
| 249 | |||
| 250 | if (rdev->is_atom_bios) | ||
| 251 | radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); | ||
| 252 | else | ||
| 253 | radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); | ||
| 254 | } | ||
| 255 | |||
| 256 | static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder) | ||
| 257 | { | ||
| 258 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 259 | |||
| 260 | if (rdev->is_atom_bios) | ||
| 261 | radeon_atom_output_lock(encoder, true); | ||
| 262 | else | ||
| 263 | radeon_combios_output_lock(encoder, true); | ||
| 264 | radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF); | ||
| 265 | } | ||
| 266 | |||
| 267 | static void radeon_legacy_lvds_commit(struct drm_encoder *encoder) | ||
| 268 | { | ||
| 269 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 270 | |||
| 271 | radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_ON); | ||
| 272 | if (rdev->is_atom_bios) | ||
| 273 | radeon_atom_output_lock(encoder, false); | ||
| 274 | else | ||
| 275 | radeon_combios_output_lock(encoder, false); | ||
| 276 | } | ||
| 277 | |||
| 278 | static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, | ||
| 279 | struct drm_display_mode *mode, | ||
| 280 | struct drm_display_mode *adjusted_mode) | ||
| 281 | { | ||
| 282 | struct drm_device *dev = encoder->dev; | ||
| 283 | struct radeon_device *rdev = dev->dev_private; | ||
| 284 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
| 285 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 286 | uint32_t lvds_pll_cntl, lvds_gen_cntl, lvds_ss_gen_cntl; | ||
| 287 | |||
| 288 | DRM_DEBUG("\n"); | ||
| 289 | |||
| 290 | if (radeon_crtc->crtc_id == 0) | ||
| 291 | radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); | ||
| 292 | |||
| 293 | lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); | ||
| 294 | lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN; | ||
| 295 | |||
| 296 | lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL); | ||
| 297 | if ((!rdev->is_atom_bios)) { | ||
| 298 | struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv; | ||
| 299 | if (lvds) { | ||
| 300 | DRM_DEBUG("bios LVDS_GEN_CNTL: 0x%x\n", lvds->lvds_gen_cntl); | ||
| 301 | lvds_gen_cntl = lvds->lvds_gen_cntl; | ||
| 302 | lvds_ss_gen_cntl &= ~((0xf << RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) | | ||
| 303 | (0xf << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT)); | ||
| 304 | lvds_ss_gen_cntl |= ((lvds->panel_digon_delay << RADEON_LVDS_PWRSEQ_DELAY1_SHIFT) | | ||
| 305 | (lvds->panel_blon_delay << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT)); | ||
| 306 | } else | ||
| 307 | lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); | ||
| 308 | } else | ||
| 309 | lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL); | ||
| 310 | lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS; | ||
| 311 | lvds_gen_cntl &= ~(RADEON_LVDS_ON | | ||
| 312 | RADEON_LVDS_BLON | | ||
| 313 | RADEON_LVDS_EN | | ||
| 314 | RADEON_LVDS_RST_FM); | ||
| 315 | |||
| 316 | if (ASIC_IS_R300(rdev)) | ||
| 317 | lvds_pll_cntl &= ~(R300_LVDS_SRC_SEL_MASK); | ||
| 318 | |||
| 319 | if (radeon_crtc->crtc_id == 0) { | ||
| 320 | if (ASIC_IS_R300(rdev)) { | ||
| 321 | if (radeon_encoder->flags & RADEON_USE_RMX) | ||
| 322 | lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX; | ||
| 323 | } else | ||
| 324 | lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2; | ||
| 325 | } else { | ||
| 326 | if (ASIC_IS_R300(rdev)) | ||
| 327 | lvds_pll_cntl |= R300_LVDS_SRC_SEL_CRTC2; | ||
| 328 | else | ||
| 329 | lvds_gen_cntl |= RADEON_LVDS_SEL_CRTC2; | ||
| 330 | } | ||
| 331 | |||
| 332 | WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl); | ||
| 333 | WREG32(RADEON_LVDS_PLL_CNTL, lvds_pll_cntl); | ||
| 334 | WREG32(RADEON_LVDS_SS_GEN_CNTL, lvds_ss_gen_cntl); | ||
| 335 | |||
| 336 | if (rdev->family == CHIP_RV410) | ||
| 337 | WREG32(RADEON_CLOCK_CNTL_INDEX, 0); | ||
| 338 | |||
| 339 | if (rdev->is_atom_bios) | ||
| 340 | radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | ||
| 341 | else | ||
| 342 | radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | ||
| 343 | } | ||
| 344 | |||
| 345 | static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder, | ||
| 346 | struct drm_display_mode *mode, | ||
| 347 | struct drm_display_mode *adjusted_mode) | ||
| 348 | { | ||
| 349 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 350 | |||
| 351 | drm_mode_set_crtcinfo(adjusted_mode, 0); | ||
| 352 | |||
| 353 | radeon_encoder->flags &= ~RADEON_USE_RMX; | ||
| 354 | |||
| 355 | if (radeon_encoder->rmx_type != RMX_OFF) | ||
| 356 | radeon_rmx_mode_fixup(encoder, mode, adjusted_mode); | ||
| 357 | |||
| 358 | return true; | ||
| 359 | } | ||
| 360 | |||
| 361 | static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = { | ||
| 362 | .dpms = radeon_legacy_lvds_dpms, | ||
| 363 | .mode_fixup = radeon_legacy_lvds_mode_fixup, | ||
| 364 | .prepare = radeon_legacy_lvds_prepare, | ||
| 365 | .mode_set = radeon_legacy_lvds_mode_set, | ||
| 366 | .commit = radeon_legacy_lvds_commit, | ||
| 367 | }; | ||
| 368 | |||
| 369 | |||
| 370 | static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = { | ||
| 371 | .destroy = radeon_enc_destroy, | ||
| 372 | }; | ||
| 373 | |||
| 374 | static bool radeon_legacy_primary_dac_mode_fixup(struct drm_encoder *encoder, | ||
| 375 | struct drm_display_mode *mode, | ||
| 376 | struct drm_display_mode *adjusted_mode) | ||
| 377 | { | ||
| 378 | |||
| 379 | drm_mode_set_crtcinfo(adjusted_mode, 0); | ||
| 380 | |||
| 381 | return true; | ||
| 382 | } | ||
| 383 | |||
| 384 | static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode) | ||
| 385 | { | ||
| 386 | struct drm_device *dev = encoder->dev; | ||
| 387 | struct radeon_device *rdev = dev->dev_private; | ||
| 388 | uint32_t crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); | ||
| 389 | uint32_t dac_cntl = RREG32(RADEON_DAC_CNTL); | ||
| 390 | uint32_t dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL); | ||
| 391 | |||
| 392 | DRM_DEBUG("\n"); | ||
| 393 | |||
| 394 | switch (mode) { | ||
| 395 | case DRM_MODE_DPMS_ON: | ||
| 396 | crtc_ext_cntl |= RADEON_CRTC_CRT_ON; | ||
| 397 | dac_cntl &= ~RADEON_DAC_PDWN; | ||
| 398 | dac_macro_cntl &= ~(RADEON_DAC_PDWN_R | | ||
| 399 | RADEON_DAC_PDWN_G | | ||
| 400 | RADEON_DAC_PDWN_B); | ||
| 401 | break; | ||
| 402 | case DRM_MODE_DPMS_STANDBY: | ||
| 403 | case DRM_MODE_DPMS_SUSPEND: | ||
| 404 | case DRM_MODE_DPMS_OFF: | ||
| 405 | crtc_ext_cntl &= ~RADEON_CRTC_CRT_ON; | ||
| 406 | dac_cntl |= RADEON_DAC_PDWN; | ||
| 407 | dac_macro_cntl |= (RADEON_DAC_PDWN_R | | ||
| 408 | RADEON_DAC_PDWN_G | | ||
| 409 | RADEON_DAC_PDWN_B); | ||
| 410 | break; | ||
| 411 | } | ||
| 412 | |||
| 413 | WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); | ||
| 414 | WREG32(RADEON_DAC_CNTL, dac_cntl); | ||
| 415 | WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); | ||
| 416 | |||
| 417 | if (rdev->is_atom_bios) | ||
| 418 | radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); | ||
| 419 | else | ||
| 420 | radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); | ||
| 421 | } | ||
| 422 | |||
| 423 | static void radeon_legacy_primary_dac_prepare(struct drm_encoder *encoder) | ||
| 424 | { | ||
| 425 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 426 | |||
| 427 | if (rdev->is_atom_bios) | ||
| 428 | radeon_atom_output_lock(encoder, true); | ||
| 429 | else | ||
| 430 | radeon_combios_output_lock(encoder, true); | ||
| 431 | radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_OFF); | ||
| 432 | } | ||
| 433 | |||
| 434 | static void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder) | ||
| 435 | { | ||
| 436 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 437 | |||
| 438 | radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_ON); | ||
| 439 | |||
| 440 | if (rdev->is_atom_bios) | ||
| 441 | radeon_atom_output_lock(encoder, false); | ||
| 442 | else | ||
| 443 | radeon_combios_output_lock(encoder, false); | ||
| 444 | } | ||
| 445 | |||
| 446 | static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder, | ||
| 447 | struct drm_display_mode *mode, | ||
| 448 | struct drm_display_mode *adjusted_mode) | ||
| 449 | { | ||
| 450 | struct drm_device *dev = encoder->dev; | ||
| 451 | struct radeon_device *rdev = dev->dev_private; | ||
| 452 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
| 453 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 454 | uint32_t disp_output_cntl, dac_cntl, dac2_cntl, dac_macro_cntl; | ||
| 455 | |||
| 456 | DRM_DEBUG("\n"); | ||
| 457 | |||
| 458 | if (radeon_crtc->crtc_id == 0) | ||
| 459 | radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); | ||
| 460 | |||
| 461 | if (radeon_crtc->crtc_id == 0) { | ||
| 462 | if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) { | ||
| 463 | disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) & | ||
| 464 | ~(RADEON_DISP_DAC_SOURCE_MASK); | ||
| 465 | WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); | ||
| 466 | } else { | ||
| 467 | dac2_cntl = RREG32(RADEON_DAC_CNTL2) & ~(RADEON_DAC2_DAC_CLK_SEL); | ||
| 468 | WREG32(RADEON_DAC_CNTL2, dac2_cntl); | ||
| 469 | } | ||
| 470 | } else { | ||
| 471 | if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) { | ||
| 472 | disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) & | ||
| 473 | ~(RADEON_DISP_DAC_SOURCE_MASK); | ||
| 474 | disp_output_cntl |= RADEON_DISP_DAC_SOURCE_CRTC2; | ||
| 475 | WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); | ||
| 476 | } else { | ||
| 477 | dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC_CLK_SEL; | ||
| 478 | WREG32(RADEON_DAC_CNTL2, dac2_cntl); | ||
| 479 | } | ||
| 480 | } | ||
| 481 | |||
| 482 | dac_cntl = (RADEON_DAC_MASK_ALL | | ||
| 483 | RADEON_DAC_VGA_ADR_EN | | ||
| 484 | /* TODO 6-bits */ | ||
| 485 | RADEON_DAC_8BIT_EN); | ||
| 486 | |||
| 487 | WREG32_P(RADEON_DAC_CNTL, | ||
| 488 | dac_cntl, | ||
| 489 | RADEON_DAC_RANGE_CNTL | | ||
| 490 | RADEON_DAC_BLANKING); | ||
| 491 | |||
| 492 | if (radeon_encoder->enc_priv) { | ||
| 493 | struct radeon_encoder_primary_dac *p_dac = (struct radeon_encoder_primary_dac *)radeon_encoder->enc_priv; | ||
| 494 | dac_macro_cntl = p_dac->ps2_pdac_adj; | ||
| 495 | } else | ||
| 496 | dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL); | ||
| 497 | dac_macro_cntl |= RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | RADEON_DAC_PDWN_B; | ||
| 498 | WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); | ||
| 499 | |||
| 500 | if (rdev->is_atom_bios) | ||
| 501 | radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | ||
| 502 | else | ||
| 503 | radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | ||
| 504 | } | ||
| 505 | |||
| 506 | static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_encoder *encoder, | ||
| 507 | struct drm_connector *connector) | ||
| 508 | { | ||
| 509 | struct drm_device *dev = encoder->dev; | ||
| 510 | struct radeon_device *rdev = dev->dev_private; | ||
| 511 | uint32_t vclk_ecp_cntl, crtc_ext_cntl; | ||
| 512 | uint32_t dac_ext_cntl, dac_cntl, dac_macro_cntl, tmp; | ||
| 513 | enum drm_connector_status found = connector_status_disconnected; | ||
| 514 | bool color = true; | ||
| 515 | |||
| 516 | /* save the regs we need */ | ||
| 517 | vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL); | ||
| 518 | crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); | ||
| 519 | dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL); | ||
| 520 | dac_cntl = RREG32(RADEON_DAC_CNTL); | ||
| 521 | dac_macro_cntl = RREG32(RADEON_DAC_MACRO_CNTL); | ||
| 522 | |||
| 523 | tmp = vclk_ecp_cntl & | ||
| 524 | ~(RADEON_PIXCLK_ALWAYS_ONb | RADEON_PIXCLK_DAC_ALWAYS_ONb); | ||
| 525 | WREG32_PLL(RADEON_VCLK_ECP_CNTL, tmp); | ||
| 526 | |||
| 527 | tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; | ||
| 528 | WREG32(RADEON_CRTC_EXT_CNTL, tmp); | ||
| 529 | |||
| 530 | tmp = RADEON_DAC_FORCE_BLANK_OFF_EN | | ||
| 531 | RADEON_DAC_FORCE_DATA_EN; | ||
| 532 | |||
| 533 | if (color) | ||
| 534 | tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB; | ||
| 535 | else | ||
| 536 | tmp |= RADEON_DAC_FORCE_DATA_SEL_G; | ||
| 537 | |||
| 538 | if (ASIC_IS_R300(rdev)) | ||
| 539 | tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); | ||
| 540 | else | ||
| 541 | tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); | ||
| 542 | |||
| 543 | WREG32(RADEON_DAC_EXT_CNTL, tmp); | ||
| 544 | |||
| 545 | tmp = dac_cntl & ~(RADEON_DAC_RANGE_CNTL_MASK | RADEON_DAC_PDWN); | ||
| 546 | tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; | ||
| 547 | WREG32(RADEON_DAC_CNTL, tmp); | ||
| 548 | |||
| 549 | tmp &= ~(RADEON_DAC_PDWN_R | | ||
| 550 | RADEON_DAC_PDWN_G | | ||
| 551 | RADEON_DAC_PDWN_B); | ||
| 552 | |||
| 553 | WREG32(RADEON_DAC_MACRO_CNTL, tmp); | ||
| 554 | |||
| 555 | udelay(2000); | ||
| 556 | |||
| 557 | if (RREG32(RADEON_DAC_CNTL) & RADEON_DAC_CMP_OUTPUT) | ||
| 558 | found = connector_status_connected; | ||
| 559 | |||
| 560 | /* restore the regs we used */ | ||
| 561 | WREG32(RADEON_DAC_CNTL, dac_cntl); | ||
| 562 | WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); | ||
| 563 | WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl); | ||
| 564 | WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); | ||
| 565 | WREG32_PLL(RADEON_VCLK_ECP_CNTL, vclk_ecp_cntl); | ||
| 566 | |||
| 567 | return found; | ||
| 568 | } | ||
| 569 | |||
| 570 | static const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_funcs = { | ||
| 571 | .dpms = radeon_legacy_primary_dac_dpms, | ||
| 572 | .mode_fixup = radeon_legacy_primary_dac_mode_fixup, | ||
| 573 | .prepare = radeon_legacy_primary_dac_prepare, | ||
| 574 | .mode_set = radeon_legacy_primary_dac_mode_set, | ||
| 575 | .commit = radeon_legacy_primary_dac_commit, | ||
| 576 | .detect = radeon_legacy_primary_dac_detect, | ||
| 577 | }; | ||
| 578 | |||
| 579 | |||
| 580 | static const struct drm_encoder_funcs radeon_legacy_primary_dac_enc_funcs = { | ||
| 581 | .destroy = radeon_enc_destroy, | ||
| 582 | }; | ||
| 583 | |||
| 584 | static bool radeon_legacy_tmds_int_mode_fixup(struct drm_encoder *encoder, | ||
| 585 | struct drm_display_mode *mode, | ||
| 586 | struct drm_display_mode *adjusted_mode) | ||
| 587 | { | ||
| 588 | |||
| 589 | drm_mode_set_crtcinfo(adjusted_mode, 0); | ||
| 590 | |||
| 591 | return true; | ||
| 592 | } | ||
| 593 | |||
| 594 | static void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode) | ||
| 595 | { | ||
| 596 | struct drm_device *dev = encoder->dev; | ||
| 597 | struct radeon_device *rdev = dev->dev_private; | ||
| 598 | uint32_t fp_gen_cntl = RREG32(RADEON_FP_GEN_CNTL); | ||
| 599 | DRM_DEBUG("\n"); | ||
| 600 | |||
| 601 | switch (mode) { | ||
| 602 | case DRM_MODE_DPMS_ON: | ||
| 603 | fp_gen_cntl |= (RADEON_FP_FPON | RADEON_FP_TMDS_EN); | ||
| 604 | break; | ||
| 605 | case DRM_MODE_DPMS_STANDBY: | ||
| 606 | case DRM_MODE_DPMS_SUSPEND: | ||
| 607 | case DRM_MODE_DPMS_OFF: | ||
| 608 | fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); | ||
| 609 | break; | ||
| 610 | } | ||
| 611 | |||
| 612 | WREG32(RADEON_FP_GEN_CNTL, fp_gen_cntl); | ||
| 613 | |||
| 614 | if (rdev->is_atom_bios) | ||
| 615 | radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); | ||
| 616 | else | ||
| 617 | radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); | ||
| 618 | } | ||
| 619 | |||
| 620 | static void radeon_legacy_tmds_int_prepare(struct drm_encoder *encoder) | ||
| 621 | { | ||
| 622 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 623 | |||
| 624 | if (rdev->is_atom_bios) | ||
| 625 | radeon_atom_output_lock(encoder, true); | ||
| 626 | else | ||
| 627 | radeon_combios_output_lock(encoder, true); | ||
| 628 | radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_OFF); | ||
| 629 | } | ||
| 630 | |||
| 631 | static void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder) | ||
| 632 | { | ||
| 633 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 634 | |||
| 635 | radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_ON); | ||
| 636 | |||
| 637 | if (rdev->is_atom_bios) | ||
| 638 | radeon_atom_output_lock(encoder, true); | ||
| 639 | else | ||
| 640 | radeon_combios_output_lock(encoder, true); | ||
| 641 | } | ||
| 642 | |||
| 643 | static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder, | ||
| 644 | struct drm_display_mode *mode, | ||
| 645 | struct drm_display_mode *adjusted_mode) | ||
| 646 | { | ||
| 647 | struct drm_device *dev = encoder->dev; | ||
| 648 | struct radeon_device *rdev = dev->dev_private; | ||
| 649 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
| 650 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 651 | uint32_t tmp, tmds_pll_cntl, tmds_transmitter_cntl, fp_gen_cntl; | ||
| 652 | int i; | ||
| 653 | |||
| 654 | DRM_DEBUG("\n"); | ||
| 655 | |||
| 656 | if (radeon_crtc->crtc_id == 0) | ||
| 657 | radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); | ||
| 658 | |||
| 659 | tmp = tmds_pll_cntl = RREG32(RADEON_TMDS_PLL_CNTL); | ||
| 660 | tmp &= 0xfffff; | ||
| 661 | if (rdev->family == CHIP_RV280) { | ||
| 662 | /* bit 22 of TMDS_PLL_CNTL is read-back inverted */ | ||
| 663 | tmp ^= (1 << 22); | ||
| 664 | tmds_pll_cntl ^= (1 << 22); | ||
| 665 | } | ||
| 666 | |||
| 667 | if (radeon_encoder->enc_priv) { | ||
| 668 | struct radeon_encoder_int_tmds *tmds = (struct radeon_encoder_int_tmds *)radeon_encoder->enc_priv; | ||
| 669 | |||
| 670 | for (i = 0; i < 4; i++) { | ||
| 671 | if (tmds->tmds_pll[i].freq == 0) | ||
| 672 | break; | ||
| 673 | if ((uint32_t)(mode->clock / 10) < tmds->tmds_pll[i].freq) { | ||
| 674 | tmp = tmds->tmds_pll[i].value ; | ||
| 675 | break; | ||
| 676 | } | ||
| 677 | } | ||
| 678 | } | ||
| 679 | |||
| 680 | if (ASIC_IS_R300(rdev) || (rdev->family == CHIP_RV280)) { | ||
| 681 | if (tmp & 0xfff00000) | ||
| 682 | tmds_pll_cntl = tmp; | ||
| 683 | else { | ||
| 684 | tmds_pll_cntl &= 0xfff00000; | ||
| 685 | tmds_pll_cntl |= tmp; | ||
| 686 | } | ||
| 687 | } else | ||
| 688 | tmds_pll_cntl = tmp; | ||
| 689 | |||
| 690 | tmds_transmitter_cntl = RREG32(RADEON_TMDS_TRANSMITTER_CNTL) & | ||
| 691 | ~(RADEON_TMDS_TRANSMITTER_PLLRST); | ||
| 692 | |||
| 693 | if (rdev->family == CHIP_R200 || | ||
| 694 | rdev->family == CHIP_R100 || | ||
| 695 | ASIC_IS_R300(rdev)) | ||
| 696 | tmds_transmitter_cntl &= ~(RADEON_TMDS_TRANSMITTER_PLLEN); | ||
| 697 | else /* RV chips got this bit reversed */ | ||
| 698 | tmds_transmitter_cntl |= RADEON_TMDS_TRANSMITTER_PLLEN; | ||
| 699 | |||
| 700 | fp_gen_cntl = (RREG32(RADEON_FP_GEN_CNTL) | | ||
| 701 | (RADEON_FP_CRTC_DONT_SHADOW_VPAR | | ||
| 702 | RADEON_FP_CRTC_DONT_SHADOW_HEND)); | ||
| 703 | |||
| 704 | fp_gen_cntl &= ~(RADEON_FP_FPON | RADEON_FP_TMDS_EN); | ||
| 705 | |||
| 706 | if (1) /* FIXME rgbBits == 8 */ | ||
| 707 | fp_gen_cntl |= RADEON_FP_PANEL_FORMAT; /* 24 bit format */ | ||
| 708 | else | ||
| 709 | fp_gen_cntl &= ~RADEON_FP_PANEL_FORMAT;/* 18 bit format */ | ||
| 710 | |||
| 711 | if (radeon_crtc->crtc_id == 0) { | ||
| 712 | if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) { | ||
| 713 | fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; | ||
| 714 | if (radeon_encoder->flags & RADEON_USE_RMX) | ||
| 715 | fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; | ||
| 716 | else | ||
| 717 | fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; | ||
| 718 | } else | ||
| 719 | fp_gen_cntl |= RADEON_FP_SEL_CRTC1; | ||
| 720 | } else { | ||
| 721 | if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) { | ||
| 722 | fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; | ||
| 723 | fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC2; | ||
| 724 | } else | ||
| 725 | fp_gen_cntl |= RADEON_FP_SEL_CRTC2; | ||
| 726 | } | ||
| 727 | |||
| 728 | WREG32(RADEON_TMDS_PLL_CNTL, tmds_pll_cntl); | ||
| 729 | WREG32(RADEON_TMDS_TRANSMITTER_CNTL, tmds_transmitter_cntl); | ||
| 730 | WREG32(RADEON_FP_GEN_CNTL, fp_gen_cntl); | ||
| 731 | |||
| 732 | if (rdev->is_atom_bios) | ||
| 733 | radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | ||
| 734 | else | ||
| 735 | radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | ||
| 736 | } | ||
| 737 | |||
| 738 | static const struct drm_encoder_helper_funcs radeon_legacy_tmds_int_helper_funcs = { | ||
| 739 | .dpms = radeon_legacy_tmds_int_dpms, | ||
| 740 | .mode_fixup = radeon_legacy_tmds_int_mode_fixup, | ||
| 741 | .prepare = radeon_legacy_tmds_int_prepare, | ||
| 742 | .mode_set = radeon_legacy_tmds_int_mode_set, | ||
| 743 | .commit = radeon_legacy_tmds_int_commit, | ||
| 744 | }; | ||
| 745 | |||
| 746 | |||
| 747 | static const struct drm_encoder_funcs radeon_legacy_tmds_int_enc_funcs = { | ||
| 748 | .destroy = radeon_enc_destroy, | ||
| 749 | }; | ||
| 750 | |||
| 751 | static bool radeon_legacy_tmds_ext_mode_fixup(struct drm_encoder *encoder, | ||
| 752 | struct drm_display_mode *mode, | ||
| 753 | struct drm_display_mode *adjusted_mode) | ||
| 754 | { | ||
| 755 | |||
| 756 | drm_mode_set_crtcinfo(adjusted_mode, 0); | ||
| 757 | |||
| 758 | return true; | ||
| 759 | } | ||
| 760 | |||
| 761 | static void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode) | ||
| 762 | { | ||
| 763 | struct drm_device *dev = encoder->dev; | ||
| 764 | struct radeon_device *rdev = dev->dev_private; | ||
| 765 | uint32_t fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); | ||
| 766 | DRM_DEBUG("\n"); | ||
| 767 | |||
| 768 | switch (mode) { | ||
| 769 | case DRM_MODE_DPMS_ON: | ||
| 770 | fp2_gen_cntl &= ~RADEON_FP2_BLANK_EN; | ||
| 771 | fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); | ||
| 772 | break; | ||
| 773 | case DRM_MODE_DPMS_STANDBY: | ||
| 774 | case DRM_MODE_DPMS_SUSPEND: | ||
| 775 | case DRM_MODE_DPMS_OFF: | ||
| 776 | fp2_gen_cntl |= RADEON_FP2_BLANK_EN; | ||
| 777 | fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); | ||
| 778 | break; | ||
| 779 | } | ||
| 780 | |||
| 781 | WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); | ||
| 782 | |||
| 783 | if (rdev->is_atom_bios) | ||
| 784 | radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); | ||
| 785 | else | ||
| 786 | radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); | ||
| 787 | } | ||
| 788 | |||
| 789 | static void radeon_legacy_tmds_ext_prepare(struct drm_encoder *encoder) | ||
| 790 | { | ||
| 791 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 792 | |||
| 793 | if (rdev->is_atom_bios) | ||
| 794 | radeon_atom_output_lock(encoder, true); | ||
| 795 | else | ||
| 796 | radeon_combios_output_lock(encoder, true); | ||
| 797 | radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_OFF); | ||
| 798 | } | ||
| 799 | |||
| 800 | static void radeon_legacy_tmds_ext_commit(struct drm_encoder *encoder) | ||
| 801 | { | ||
| 802 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 803 | radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_ON); | ||
| 804 | |||
| 805 | if (rdev->is_atom_bios) | ||
| 806 | radeon_atom_output_lock(encoder, false); | ||
| 807 | else | ||
| 808 | radeon_combios_output_lock(encoder, false); | ||
| 809 | } | ||
| 810 | |||
| 811 | static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, | ||
| 812 | struct drm_display_mode *mode, | ||
| 813 | struct drm_display_mode *adjusted_mode) | ||
| 814 | { | ||
| 815 | struct drm_device *dev = encoder->dev; | ||
| 816 | struct radeon_device *rdev = dev->dev_private; | ||
| 817 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
| 818 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 819 | uint32_t fp2_gen_cntl; | ||
| 820 | |||
| 821 | DRM_DEBUG("\n"); | ||
| 822 | |||
| 823 | if (radeon_crtc->crtc_id == 0) | ||
| 824 | radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); | ||
| 825 | |||
| 826 | if (rdev->is_atom_bios) { | ||
| 827 | radeon_encoder->pixel_clock = adjusted_mode->clock; | ||
| 828 | atombios_external_tmds_setup(encoder, ATOM_ENABLE); | ||
| 829 | fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); | ||
| 830 | } else { | ||
| 831 | fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); | ||
| 832 | |||
| 833 | if (1) /* FIXME rgbBits == 8 */ | ||
| 834 | fp2_gen_cntl |= RADEON_FP2_PANEL_FORMAT; /* 24 bit format, */ | ||
| 835 | else | ||
| 836 | fp2_gen_cntl &= ~RADEON_FP2_PANEL_FORMAT;/* 18 bit format, */ | ||
| 837 | |||
| 838 | fp2_gen_cntl &= ~(RADEON_FP2_ON | | ||
| 839 | RADEON_FP2_DVO_EN | | ||
| 840 | RADEON_FP2_DVO_RATE_SEL_SDR); | ||
| 841 | |||
| 842 | /* XXX: these are oem specific */ | ||
| 843 | if (ASIC_IS_R300(rdev)) { | ||
| 844 | if ((dev->pdev->device == 0x4850) && | ||
| 845 | (dev->pdev->subsystem_vendor == 0x1028) && | ||
| 846 | (dev->pdev->subsystem_device == 0x2001)) /* Dell Inspiron 8600 */ | ||
| 847 | fp2_gen_cntl |= R300_FP2_DVO_CLOCK_MODE_SINGLE; | ||
| 848 | else | ||
| 849 | fp2_gen_cntl |= RADEON_FP2_PAD_FLOP_EN | R300_FP2_DVO_CLOCK_MODE_SINGLE; | ||
| 850 | |||
| 851 | /*if (mode->clock > 165000) | ||
| 852 | fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;*/ | ||
| 853 | } | ||
| 854 | } | ||
| 855 | |||
| 856 | if (radeon_crtc->crtc_id == 0) { | ||
| 857 | if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) { | ||
| 858 | fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; | ||
| 859 | if (radeon_encoder->flags & RADEON_USE_RMX) | ||
| 860 | fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; | ||
| 861 | else | ||
| 862 | fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1; | ||
| 863 | } else | ||
| 864 | fp2_gen_cntl &= ~RADEON_FP2_SRC_SEL_CRTC2; | ||
| 865 | } else { | ||
| 866 | if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) { | ||
| 867 | fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; | ||
| 868 | fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; | ||
| 869 | } else | ||
| 870 | fp2_gen_cntl |= RADEON_FP2_SRC_SEL_CRTC2; | ||
| 871 | } | ||
| 872 | |||
| 873 | WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); | ||
| 874 | |||
| 875 | if (rdev->is_atom_bios) | ||
| 876 | radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | ||
| 877 | else | ||
| 878 | radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | ||
| 879 | } | ||
| 880 | |||
| 881 | static const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs = { | ||
| 882 | .dpms = radeon_legacy_tmds_ext_dpms, | ||
| 883 | .mode_fixup = radeon_legacy_tmds_ext_mode_fixup, | ||
| 884 | .prepare = radeon_legacy_tmds_ext_prepare, | ||
| 885 | .mode_set = radeon_legacy_tmds_ext_mode_set, | ||
| 886 | .commit = radeon_legacy_tmds_ext_commit, | ||
| 887 | }; | ||
| 888 | |||
| 889 | |||
| 890 | static const struct drm_encoder_funcs radeon_legacy_tmds_ext_enc_funcs = { | ||
| 891 | .destroy = radeon_enc_destroy, | ||
| 892 | }; | ||
| 893 | |||
| 894 | static bool radeon_legacy_tv_dac_mode_fixup(struct drm_encoder *encoder, | ||
| 895 | struct drm_display_mode *mode, | ||
| 896 | struct drm_display_mode *adjusted_mode) | ||
| 897 | { | ||
| 898 | |||
| 899 | drm_mode_set_crtcinfo(adjusted_mode, 0); | ||
| 900 | |||
| 901 | return true; | ||
| 902 | } | ||
| 903 | |||
| 904 | static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode) | ||
| 905 | { | ||
| 906 | struct drm_device *dev = encoder->dev; | ||
| 907 | struct radeon_device *rdev = dev->dev_private; | ||
| 908 | uint32_t fp2_gen_cntl = 0, crtc2_gen_cntl = 0, tv_dac_cntl = 0; | ||
| 909 | /* uint32_t tv_master_cntl = 0; */ | ||
| 910 | |||
| 911 | DRM_DEBUG("\n"); | ||
| 912 | |||
| 913 | if (rdev->family == CHIP_R200) | ||
| 914 | fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); | ||
| 915 | else { | ||
| 916 | crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); | ||
| 917 | /* FIXME TV */ | ||
| 918 | /* tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL); */ | ||
| 919 | tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); | ||
| 920 | } | ||
| 921 | |||
| 922 | switch (mode) { | ||
| 923 | case DRM_MODE_DPMS_ON: | ||
| 924 | if (rdev->family == CHIP_R200) { | ||
| 925 | fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN); | ||
| 926 | } else { | ||
| 927 | crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON; | ||
| 928 | /* tv_master_cntl |= RADEON_TV_ON; */ | ||
| 929 | if (rdev->family == CHIP_R420 || | ||
| 930 | rdev->family == CHIP_R423 || | ||
| 931 | rdev->family == CHIP_RV410) | ||
| 932 | tv_dac_cntl &= ~(R420_TV_DAC_RDACPD | | ||
| 933 | R420_TV_DAC_GDACPD | | ||
| 934 | R420_TV_DAC_BDACPD | | ||
| 935 | RADEON_TV_DAC_BGSLEEP); | ||
| 936 | else | ||
| 937 | tv_dac_cntl &= ~(RADEON_TV_DAC_RDACPD | | ||
| 938 | RADEON_TV_DAC_GDACPD | | ||
| 939 | RADEON_TV_DAC_BDACPD | | ||
| 940 | RADEON_TV_DAC_BGSLEEP); | ||
| 941 | } | ||
| 942 | break; | ||
| 943 | case DRM_MODE_DPMS_STANDBY: | ||
| 944 | case DRM_MODE_DPMS_SUSPEND: | ||
| 945 | case DRM_MODE_DPMS_OFF: | ||
| 946 | if (rdev->family == CHIP_R200) | ||
| 947 | fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN); | ||
| 948 | else { | ||
| 949 | crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON; | ||
| 950 | /* tv_master_cntl &= ~RADEON_TV_ON; */ | ||
| 951 | if (rdev->family == CHIP_R420 || | ||
| 952 | rdev->family == CHIP_R423 || | ||
| 953 | rdev->family == CHIP_RV410) | ||
| 954 | tv_dac_cntl |= (R420_TV_DAC_RDACPD | | ||
| 955 | R420_TV_DAC_GDACPD | | ||
| 956 | R420_TV_DAC_BDACPD | | ||
| 957 | RADEON_TV_DAC_BGSLEEP); | ||
| 958 | else | ||
| 959 | tv_dac_cntl |= (RADEON_TV_DAC_RDACPD | | ||
| 960 | RADEON_TV_DAC_GDACPD | | ||
| 961 | RADEON_TV_DAC_BDACPD | | ||
| 962 | RADEON_TV_DAC_BGSLEEP); | ||
| 963 | } | ||
| 964 | break; | ||
| 965 | } | ||
| 966 | |||
| 967 | if (rdev->family == CHIP_R200) { | ||
| 968 | WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); | ||
| 969 | } else { | ||
| 970 | WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); | ||
| 971 | /* WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); */ | ||
| 972 | WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); | ||
| 973 | } | ||
| 974 | |||
| 975 | if (rdev->is_atom_bios) | ||
| 976 | radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); | ||
| 977 | else | ||
| 978 | radeon_combios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); | ||
| 979 | } | ||
| 980 | |||
| 981 | static void radeon_legacy_tv_dac_prepare(struct drm_encoder *encoder) | ||
| 982 | { | ||
| 983 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 984 | |||
| 985 | if (rdev->is_atom_bios) | ||
| 986 | radeon_atom_output_lock(encoder, true); | ||
| 987 | else | ||
| 988 | radeon_combios_output_lock(encoder, true); | ||
| 989 | radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_OFF); | ||
| 990 | } | ||
| 991 | |||
| 992 | static void radeon_legacy_tv_dac_commit(struct drm_encoder *encoder) | ||
| 993 | { | ||
| 994 | struct radeon_device *rdev = encoder->dev->dev_private; | ||
| 995 | |||
| 996 | radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_ON); | ||
| 997 | |||
| 998 | if (rdev->is_atom_bios) | ||
| 999 | radeon_atom_output_lock(encoder, true); | ||
| 1000 | else | ||
| 1001 | radeon_combios_output_lock(encoder, true); | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, | ||
| 1005 | struct drm_display_mode *mode, | ||
| 1006 | struct drm_display_mode *adjusted_mode) | ||
| 1007 | { | ||
| 1008 | struct drm_device *dev = encoder->dev; | ||
| 1009 | struct radeon_device *rdev = dev->dev_private; | ||
| 1010 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); | ||
| 1011 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
| 1012 | uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0; | ||
| 1013 | uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0; | ||
| 1014 | |||
| 1015 | DRM_DEBUG("\n"); | ||
| 1016 | |||
| 1017 | if (radeon_crtc->crtc_id == 0) | ||
| 1018 | radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode); | ||
| 1019 | |||
| 1020 | if (rdev->family != CHIP_R200) { | ||
| 1021 | tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); | ||
| 1022 | if (rdev->family == CHIP_R420 || | ||
| 1023 | rdev->family == CHIP_R423 || | ||
| 1024 | rdev->family == CHIP_RV410) { | ||
| 1025 | tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK | | ||
| 1026 | RADEON_TV_DAC_BGADJ_MASK | | ||
| 1027 | R420_TV_DAC_DACADJ_MASK | | ||
| 1028 | R420_TV_DAC_RDACPD | | ||
| 1029 | R420_TV_DAC_GDACPD | | ||
| 1030 | R420_TV_DAC_GDACPD | | ||
| 1031 | R420_TV_DAC_TVENABLE); | ||
| 1032 | } else { | ||
| 1033 | tv_dac_cntl &= ~(RADEON_TV_DAC_STD_MASK | | ||
| 1034 | RADEON_TV_DAC_BGADJ_MASK | | ||
| 1035 | RADEON_TV_DAC_DACADJ_MASK | | ||
| 1036 | RADEON_TV_DAC_RDACPD | | ||
| 1037 | RADEON_TV_DAC_GDACPD | | ||
| 1038 | RADEON_TV_DAC_GDACPD); | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | /* FIXME TV */ | ||
| 1042 | if (radeon_encoder->enc_priv) { | ||
| 1043 | struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; | ||
| 1044 | tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | | ||
| 1045 | RADEON_TV_DAC_NHOLD | | ||
| 1046 | RADEON_TV_DAC_STD_PS2 | | ||
| 1047 | tv_dac->ps2_tvdac_adj); | ||
| 1048 | } else | ||
| 1049 | tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | | ||
| 1050 | RADEON_TV_DAC_NHOLD | | ||
| 1051 | RADEON_TV_DAC_STD_PS2); | ||
| 1052 | |||
| 1053 | WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | if (ASIC_IS_R300(rdev)) { | ||
| 1057 | gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1; | ||
| 1058 | disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); | ||
| 1059 | } else if (rdev->family == CHIP_R200) | ||
| 1060 | fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); | ||
| 1061 | else | ||
| 1062 | disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); | ||
| 1063 | |||
| 1064 | dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC2_CLK_SEL; | ||
| 1065 | |||
| 1066 | if (radeon_crtc->crtc_id == 0) { | ||
| 1067 | if (ASIC_IS_R300(rdev)) { | ||
| 1068 | disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; | ||
| 1069 | disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC; | ||
| 1070 | } else if (rdev->family == CHIP_R200) { | ||
| 1071 | fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | | ||
| 1072 | RADEON_FP2_DVO_RATE_SEL_SDR); | ||
| 1073 | } else | ||
| 1074 | disp_hw_debug |= RADEON_CRT2_DISP1_SEL; | ||
| 1075 | } else { | ||
| 1076 | if (ASIC_IS_R300(rdev)) { | ||
| 1077 | disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK; | ||
| 1078 | disp_output_cntl |= RADEON_DISP_TVDAC_SOURCE_CRTC2; | ||
| 1079 | } else if (rdev->family == CHIP_R200) { | ||
| 1080 | fp2_gen_cntl &= ~(R200_FP2_SOURCE_SEL_MASK | | ||
| 1081 | RADEON_FP2_DVO_RATE_SEL_SDR); | ||
| 1082 | fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC2; | ||
| 1083 | } else | ||
| 1084 | disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL; | ||
| 1085 | } | ||
| 1086 | |||
| 1087 | WREG32(RADEON_DAC_CNTL2, dac2_cntl); | ||
| 1088 | |||
| 1089 | if (ASIC_IS_R300(rdev)) { | ||
| 1090 | WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); | ||
| 1091 | WREG32(RADEON_DISP_TV_OUT_CNTL, disp_output_cntl); | ||
| 1092 | } else if (rdev->family == CHIP_R200) | ||
| 1093 | WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); | ||
| 1094 | else | ||
| 1095 | WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); | ||
| 1096 | |||
| 1097 | if (rdev->is_atom_bios) | ||
| 1098 | radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | ||
| 1099 | else | ||
| 1100 | radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id); | ||
| 1101 | |||
| 1102 | } | ||
| 1103 | |||
| 1104 | static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder, | ||
| 1105 | struct drm_connector *connector) | ||
| 1106 | { | ||
| 1107 | struct drm_device *dev = encoder->dev; | ||
| 1108 | struct radeon_device *rdev = dev->dev_private; | ||
| 1109 | uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; | ||
| 1110 | uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp; | ||
| 1111 | enum drm_connector_status found = connector_status_disconnected; | ||
| 1112 | bool color = true; | ||
| 1113 | |||
| 1114 | /* FIXME tv */ | ||
| 1115 | |||
| 1116 | /* save the regs we need */ | ||
| 1117 | pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); | ||
| 1118 | gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0; | ||
| 1119 | disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0; | ||
| 1120 | disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG); | ||
| 1121 | crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); | ||
| 1122 | tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); | ||
| 1123 | dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL); | ||
| 1124 | dac_cntl2 = RREG32(RADEON_DAC_CNTL2); | ||
| 1125 | |||
| 1126 | tmp = pixclks_cntl & ~(RADEON_PIX2CLK_ALWAYS_ONb | ||
| 1127 | | RADEON_PIX2CLK_DAC_ALWAYS_ONb); | ||
| 1128 | WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); | ||
| 1129 | |||
| 1130 | if (ASIC_IS_R300(rdev)) | ||
| 1131 | WREG32_P(RADEON_GPIOPAD_A, 1, ~1); | ||
| 1132 | |||
| 1133 | tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; | ||
| 1134 | tmp |= RADEON_CRTC2_CRT2_ON | | ||
| 1135 | (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); | ||
| 1136 | |||
| 1137 | WREG32(RADEON_CRTC2_GEN_CNTL, tmp); | ||
| 1138 | |||
| 1139 | if (ASIC_IS_R300(rdev)) { | ||
| 1140 | tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; | ||
| 1141 | tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; | ||
| 1142 | WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); | ||
| 1143 | } else { | ||
| 1144 | tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; | ||
| 1145 | WREG32(RADEON_DISP_HW_DEBUG, tmp); | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | tmp = RADEON_TV_DAC_NBLANK | | ||
| 1149 | RADEON_TV_DAC_NHOLD | | ||
| 1150 | RADEON_TV_MONITOR_DETECT_EN | | ||
| 1151 | RADEON_TV_DAC_STD_PS2; | ||
| 1152 | |||
| 1153 | WREG32(RADEON_TV_DAC_CNTL, tmp); | ||
| 1154 | |||
| 1155 | tmp = RADEON_DAC2_FORCE_BLANK_OFF_EN | | ||
| 1156 | RADEON_DAC2_FORCE_DATA_EN; | ||
| 1157 | |||
| 1158 | if (color) | ||
| 1159 | tmp |= RADEON_DAC_FORCE_DATA_SEL_RGB; | ||
| 1160 | else | ||
| 1161 | tmp |= RADEON_DAC_FORCE_DATA_SEL_G; | ||
| 1162 | |||
| 1163 | if (ASIC_IS_R300(rdev)) | ||
| 1164 | tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); | ||
| 1165 | else | ||
| 1166 | tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); | ||
| 1167 | |||
| 1168 | WREG32(RADEON_DAC_EXT_CNTL, tmp); | ||
| 1169 | |||
| 1170 | tmp = dac_cntl2 | RADEON_DAC2_DAC2_CLK_SEL | RADEON_DAC2_CMP_EN; | ||
| 1171 | WREG32(RADEON_DAC_CNTL2, tmp); | ||
| 1172 | |||
| 1173 | udelay(10000); | ||
| 1174 | |||
| 1175 | if (ASIC_IS_R300(rdev)) { | ||
| 1176 | if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUT_B) | ||
| 1177 | found = connector_status_connected; | ||
| 1178 | } else { | ||
| 1179 | if (RREG32(RADEON_DAC_CNTL2) & RADEON_DAC2_CMP_OUTPUT) | ||
| 1180 | found = connector_status_connected; | ||
| 1181 | } | ||
| 1182 | |||
| 1183 | /* restore regs we used */ | ||
| 1184 | WREG32(RADEON_DAC_CNTL2, dac_cntl2); | ||
| 1185 | WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl); | ||
| 1186 | WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); | ||
| 1187 | WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); | ||
| 1188 | |||
| 1189 | if (ASIC_IS_R300(rdev)) { | ||
| 1190 | WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); | ||
| 1191 | WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); | ||
| 1192 | } else { | ||
| 1193 | WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); | ||
| 1194 | } | ||
| 1195 | WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); | ||
| 1196 | |||
| 1197 | /* return found; */ | ||
| 1198 | return connector_status_disconnected; | ||
| 1199 | |||
| 1200 | } | ||
| 1201 | |||
| 1202 | static const struct drm_encoder_helper_funcs radeon_legacy_tv_dac_helper_funcs = { | ||
| 1203 | .dpms = radeon_legacy_tv_dac_dpms, | ||
| 1204 | .mode_fixup = radeon_legacy_tv_dac_mode_fixup, | ||
| 1205 | .prepare = radeon_legacy_tv_dac_prepare, | ||
| 1206 | .mode_set = radeon_legacy_tv_dac_mode_set, | ||
| 1207 | .commit = radeon_legacy_tv_dac_commit, | ||
| 1208 | .detect = radeon_legacy_tv_dac_detect, | ||
| 1209 | }; | ||
| 1210 | |||
| 1211 | |||
| 1212 | static const struct drm_encoder_funcs radeon_legacy_tv_dac_enc_funcs = { | ||
| 1213 | .destroy = radeon_enc_destroy, | ||
| 1214 | }; | ||
| 1215 | |||
| 1216 | void | ||
| 1217 | radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device) | ||
| 1218 | { | ||
| 1219 | struct radeon_device *rdev = dev->dev_private; | ||
| 1220 | struct drm_encoder *encoder; | ||
| 1221 | struct radeon_encoder *radeon_encoder; | ||
| 1222 | |||
| 1223 | /* see if we already added it */ | ||
| 1224 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
| 1225 | radeon_encoder = to_radeon_encoder(encoder); | ||
| 1226 | if (radeon_encoder->encoder_id == encoder_id) { | ||
| 1227 | radeon_encoder->devices |= supported_device; | ||
| 1228 | return; | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | } | ||
| 1232 | |||
| 1233 | /* add a new one */ | ||
| 1234 | radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL); | ||
| 1235 | if (!radeon_encoder) | ||
| 1236 | return; | ||
| 1237 | |||
| 1238 | encoder = &radeon_encoder->base; | ||
| 1239 | encoder->possible_crtcs = 0x3; | ||
| 1240 | encoder->possible_clones = 0; | ||
| 1241 | |||
| 1242 | radeon_encoder->enc_priv = NULL; | ||
| 1243 | |||
| 1244 | radeon_encoder->encoder_id = encoder_id; | ||
| 1245 | radeon_encoder->devices = supported_device; | ||
| 1246 | |||
| 1247 | switch (radeon_encoder->encoder_id) { | ||
| 1248 | case ENCODER_OBJECT_ID_INTERNAL_LVDS: | ||
| 1249 | drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs, DRM_MODE_ENCODER_LVDS); | ||
| 1250 | drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs); | ||
| 1251 | if (rdev->is_atom_bios) | ||
| 1252 | radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder); | ||
| 1253 | else | ||
| 1254 | radeon_encoder->enc_priv = radeon_combios_get_lvds_info(radeon_encoder); | ||
| 1255 | radeon_encoder->rmx_type = RMX_FULL; | ||
| 1256 | break; | ||
| 1257 | case ENCODER_OBJECT_ID_INTERNAL_TMDS1: | ||
| 1258 | drm_encoder_init(dev, encoder, &radeon_legacy_tmds_int_enc_funcs, DRM_MODE_ENCODER_TMDS); | ||
| 1259 | drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs); | ||
| 1260 | if (rdev->is_atom_bios) | ||
| 1261 | radeon_encoder->enc_priv = radeon_atombios_get_tmds_info(radeon_encoder); | ||
| 1262 | else | ||
| 1263 | radeon_encoder->enc_priv = radeon_combios_get_tmds_info(radeon_encoder); | ||
| 1264 | break; | ||
| 1265 | case ENCODER_OBJECT_ID_INTERNAL_DAC1: | ||
| 1266 | drm_encoder_init(dev, encoder, &radeon_legacy_primary_dac_enc_funcs, DRM_MODE_ENCODER_DAC); | ||
| 1267 | drm_encoder_helper_add(encoder, &radeon_legacy_primary_dac_helper_funcs); | ||
| 1268 | if (rdev->is_atom_bios) | ||
| 1269 | radeon_encoder->enc_priv = radeon_atombios_get_primary_dac_info(radeon_encoder); | ||
| 1270 | else | ||
| 1271 | radeon_encoder->enc_priv = radeon_combios_get_primary_dac_info(radeon_encoder); | ||
| 1272 | break; | ||
| 1273 | case ENCODER_OBJECT_ID_INTERNAL_DAC2: | ||
| 1274 | drm_encoder_init(dev, encoder, &radeon_legacy_tv_dac_enc_funcs, DRM_MODE_ENCODER_TVDAC); | ||
| 1275 | drm_encoder_helper_add(encoder, &radeon_legacy_tv_dac_helper_funcs); | ||
| 1276 | if (rdev->is_atom_bios) | ||
| 1277 | radeon_encoder->enc_priv = radeon_atombios_get_tv_dac_info(radeon_encoder); | ||
| 1278 | else | ||
| 1279 | radeon_encoder->enc_priv = radeon_combios_get_tv_dac_info(radeon_encoder); | ||
| 1280 | break; | ||
| 1281 | case ENCODER_OBJECT_ID_INTERNAL_DVO1: | ||
| 1282 | drm_encoder_init(dev, encoder, &radeon_legacy_tmds_ext_enc_funcs, DRM_MODE_ENCODER_TMDS); | ||
| 1283 | drm_encoder_helper_add(encoder, &radeon_legacy_tmds_ext_helper_funcs); | ||
| 1284 | if (!rdev->is_atom_bios) | ||
| 1285 | radeon_combios_get_ext_tmds_info(radeon_encoder); | ||
| 1286 | break; | ||
| 1287 | } | ||
| 1288 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h new file mode 100644 index 000000000000..9173b687462b --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
| @@ -0,0 +1,398 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and | ||
| 3 | * VA Linux Systems Inc., Fremont, California. | ||
| 4 | * Copyright 2008 Red Hat Inc. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Original Authors: | ||
| 25 | * Kevin E. Martin, Rickard E. Faith, Alan Hourihane | ||
| 26 | * | ||
| 27 | * Kernel port Author: Dave Airlie | ||
| 28 | */ | ||
| 29 | |||
| 30 | #ifndef RADEON_MODE_H | ||
| 31 | #define RADEON_MODE_H | ||
| 32 | |||
| 33 | #include <drm_crtc.h> | ||
| 34 | #include <drm_mode.h> | ||
| 35 | #include <drm_edid.h> | ||
| 36 | #include <linux/i2c.h> | ||
| 37 | #include <linux/i2c-id.h> | ||
| 38 | #include <linux/i2c-algo-bit.h> | ||
| 39 | |||
| 40 | #define to_radeon_crtc(x) container_of(x, struct radeon_crtc, base) | ||
| 41 | #define to_radeon_connector(x) container_of(x, struct radeon_connector, base) | ||
| 42 | #define to_radeon_encoder(x) container_of(x, struct radeon_encoder, base) | ||
| 43 | #define to_radeon_framebuffer(x) container_of(x, struct radeon_framebuffer, base) | ||
| 44 | |||
| 45 | enum radeon_connector_type { | ||
| 46 | CONNECTOR_NONE, | ||
| 47 | CONNECTOR_VGA, | ||
| 48 | CONNECTOR_DVI_I, | ||
| 49 | CONNECTOR_DVI_D, | ||
| 50 | CONNECTOR_DVI_A, | ||
| 51 | CONNECTOR_STV, | ||
| 52 | CONNECTOR_CTV, | ||
| 53 | CONNECTOR_LVDS, | ||
| 54 | CONNECTOR_DIGITAL, | ||
| 55 | CONNECTOR_SCART, | ||
| 56 | CONNECTOR_HDMI_TYPE_A, | ||
| 57 | CONNECTOR_HDMI_TYPE_B, | ||
| 58 | CONNECTOR_0XC, | ||
| 59 | CONNECTOR_0XD, | ||
| 60 | CONNECTOR_DIN, | ||
| 61 | CONNECTOR_DISPLAY_PORT, | ||
| 62 | CONNECTOR_UNSUPPORTED | ||
| 63 | }; | ||
| 64 | |||
| 65 | enum radeon_dvi_type { | ||
| 66 | DVI_AUTO, | ||
| 67 | DVI_DIGITAL, | ||
| 68 | DVI_ANALOG | ||
| 69 | }; | ||
| 70 | |||
| 71 | enum radeon_rmx_type { | ||
| 72 | RMX_OFF, | ||
| 73 | RMX_FULL, | ||
| 74 | RMX_CENTER, | ||
| 75 | RMX_ASPECT | ||
| 76 | }; | ||
| 77 | |||
| 78 | enum radeon_tv_std { | ||
| 79 | TV_STD_NTSC, | ||
| 80 | TV_STD_PAL, | ||
| 81 | TV_STD_PAL_M, | ||
| 82 | TV_STD_PAL_60, | ||
| 83 | TV_STD_NTSC_J, | ||
| 84 | TV_STD_SCART_PAL, | ||
| 85 | TV_STD_SECAM, | ||
| 86 | TV_STD_PAL_CN, | ||
| 87 | }; | ||
| 88 | |||
| 89 | struct radeon_i2c_bus_rec { | ||
| 90 | bool valid; | ||
| 91 | uint32_t mask_clk_reg; | ||
| 92 | uint32_t mask_data_reg; | ||
| 93 | uint32_t a_clk_reg; | ||
| 94 | uint32_t a_data_reg; | ||
| 95 | uint32_t put_clk_reg; | ||
| 96 | uint32_t put_data_reg; | ||
| 97 | uint32_t get_clk_reg; | ||
| 98 | uint32_t get_data_reg; | ||
| 99 | uint32_t mask_clk_mask; | ||
| 100 | uint32_t mask_data_mask; | ||
| 101 | uint32_t put_clk_mask; | ||
| 102 | uint32_t put_data_mask; | ||
| 103 | uint32_t get_clk_mask; | ||
| 104 | uint32_t get_data_mask; | ||
| 105 | uint32_t a_clk_mask; | ||
| 106 | uint32_t a_data_mask; | ||
| 107 | }; | ||
| 108 | |||
| 109 | struct radeon_tmds_pll { | ||
| 110 | uint32_t freq; | ||
| 111 | uint32_t value; | ||
| 112 | }; | ||
| 113 | |||
| 114 | #define RADEON_MAX_BIOS_CONNECTOR 16 | ||
| 115 | |||
| 116 | #define RADEON_PLL_USE_BIOS_DIVS (1 << 0) | ||
| 117 | #define RADEON_PLL_NO_ODD_POST_DIV (1 << 1) | ||
| 118 | #define RADEON_PLL_USE_REF_DIV (1 << 2) | ||
| 119 | #define RADEON_PLL_LEGACY (1 << 3) | ||
| 120 | #define RADEON_PLL_PREFER_LOW_REF_DIV (1 << 4) | ||
| 121 | #define RADEON_PLL_PREFER_HIGH_REF_DIV (1 << 5) | ||
| 122 | #define RADEON_PLL_PREFER_LOW_FB_DIV (1 << 6) | ||
| 123 | #define RADEON_PLL_PREFER_HIGH_FB_DIV (1 << 7) | ||
| 124 | #define RADEON_PLL_PREFER_LOW_POST_DIV (1 << 8) | ||
| 125 | #define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9) | ||
| 126 | #define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10) | ||
| 127 | |||
| 128 | struct radeon_pll { | ||
| 129 | uint16_t reference_freq; | ||
| 130 | uint16_t reference_div; | ||
| 131 | uint32_t pll_in_min; | ||
| 132 | uint32_t pll_in_max; | ||
| 133 | uint32_t pll_out_min; | ||
| 134 | uint32_t pll_out_max; | ||
| 135 | uint16_t xclk; | ||
| 136 | |||
| 137 | uint32_t min_ref_div; | ||
| 138 | uint32_t max_ref_div; | ||
| 139 | uint32_t min_post_div; | ||
| 140 | uint32_t max_post_div; | ||
| 141 | uint32_t min_feedback_div; | ||
| 142 | uint32_t max_feedback_div; | ||
| 143 | uint32_t min_frac_feedback_div; | ||
| 144 | uint32_t max_frac_feedback_div; | ||
| 145 | uint32_t best_vco; | ||
| 146 | }; | ||
| 147 | |||
| 148 | struct radeon_i2c_chan { | ||
| 149 | struct drm_device *dev; | ||
| 150 | struct i2c_adapter adapter; | ||
| 151 | struct i2c_algo_bit_data algo; | ||
| 152 | struct radeon_i2c_bus_rec rec; | ||
| 153 | }; | ||
| 154 | |||
| 155 | /* mostly for macs, but really any system without connector tables */ | ||
| 156 | enum radeon_connector_table { | ||
| 157 | CT_NONE, | ||
| 158 | CT_GENERIC, | ||
| 159 | CT_IBOOK, | ||
| 160 | CT_POWERBOOK_EXTERNAL, | ||
| 161 | CT_POWERBOOK_INTERNAL, | ||
| 162 | CT_POWERBOOK_VGA, | ||
| 163 | CT_MINI_EXTERNAL, | ||
| 164 | CT_MINI_INTERNAL, | ||
| 165 | CT_IMAC_G5_ISIGHT, | ||
| 166 | CT_EMAC, | ||
| 167 | }; | ||
| 168 | |||
| 169 | struct radeon_mode_info { | ||
| 170 | struct atom_context *atom_context; | ||
| 171 | enum radeon_connector_table connector_table; | ||
| 172 | bool mode_config_initialized; | ||
| 173 | }; | ||
| 174 | |||
| 175 | struct radeon_crtc { | ||
| 176 | struct drm_crtc base; | ||
| 177 | int crtc_id; | ||
| 178 | u16 lut_r[256], lut_g[256], lut_b[256]; | ||
| 179 | bool enabled; | ||
| 180 | bool can_tile; | ||
| 181 | uint32_t crtc_offset; | ||
| 182 | struct radeon_framebuffer *fbdev_fb; | ||
| 183 | struct drm_mode_set mode_set; | ||
| 184 | struct drm_gem_object *cursor_bo; | ||
| 185 | uint64_t cursor_addr; | ||
| 186 | int cursor_width; | ||
| 187 | int cursor_height; | ||
| 188 | }; | ||
| 189 | |||
| 190 | #define RADEON_USE_RMX 1 | ||
| 191 | |||
| 192 | struct radeon_native_mode { | ||
| 193 | /* preferred mode */ | ||
| 194 | uint32_t panel_xres, panel_yres; | ||
| 195 | uint32_t hoverplus, hsync_width; | ||
| 196 | uint32_t hblank; | ||
| 197 | uint32_t voverplus, vsync_width; | ||
| 198 | uint32_t vblank; | ||
| 199 | uint32_t dotclock; | ||
| 200 | uint32_t flags; | ||
| 201 | }; | ||
| 202 | |||
| 203 | struct radeon_encoder_primary_dac { | ||
| 204 | /* legacy primary dac */ | ||
| 205 | uint32_t ps2_pdac_adj; | ||
| 206 | }; | ||
| 207 | |||
| 208 | struct radeon_encoder_lvds { | ||
| 209 | /* legacy lvds */ | ||
| 210 | uint16_t panel_vcc_delay; | ||
| 211 | uint8_t panel_pwr_delay; | ||
| 212 | uint8_t panel_digon_delay; | ||
| 213 | uint8_t panel_blon_delay; | ||
| 214 | uint16_t panel_ref_divider; | ||
| 215 | uint8_t panel_post_divider; | ||
| 216 | uint16_t panel_fb_divider; | ||
| 217 | bool use_bios_dividers; | ||
| 218 | uint32_t lvds_gen_cntl; | ||
| 219 | /* panel mode */ | ||
| 220 | struct radeon_native_mode native_mode; | ||
| 221 | }; | ||
| 222 | |||
| 223 | struct radeon_encoder_tv_dac { | ||
| 224 | /* legacy tv dac */ | ||
| 225 | uint32_t ps2_tvdac_adj; | ||
| 226 | uint32_t ntsc_tvdac_adj; | ||
| 227 | uint32_t pal_tvdac_adj; | ||
| 228 | |||
| 229 | enum radeon_tv_std tv_std; | ||
| 230 | }; | ||
| 231 | |||
| 232 | struct radeon_encoder_int_tmds { | ||
| 233 | /* legacy int tmds */ | ||
| 234 | struct radeon_tmds_pll tmds_pll[4]; | ||
| 235 | }; | ||
| 236 | |||
| 237 | struct radeon_encoder_atom_dig { | ||
| 238 | /* atom dig */ | ||
| 239 | bool coherent_mode; | ||
| 240 | int dig_block; | ||
| 241 | /* atom lvds */ | ||
| 242 | uint32_t lvds_misc; | ||
| 243 | uint16_t panel_pwr_delay; | ||
| 244 | /* panel mode */ | ||
| 245 | struct radeon_native_mode native_mode; | ||
| 246 | }; | ||
| 247 | |||
| 248 | struct radeon_encoder { | ||
| 249 | struct drm_encoder base; | ||
| 250 | uint32_t encoder_id; | ||
| 251 | uint32_t devices; | ||
| 252 | uint32_t flags; | ||
| 253 | uint32_t pixel_clock; | ||
| 254 | enum radeon_rmx_type rmx_type; | ||
| 255 | struct radeon_native_mode native_mode; | ||
| 256 | void *enc_priv; | ||
| 257 | }; | ||
| 258 | |||
| 259 | struct radeon_connector_atom_dig { | ||
| 260 | uint32_t igp_lane_info; | ||
| 261 | bool linkb; | ||
| 262 | }; | ||
| 263 | |||
| 264 | struct radeon_connector { | ||
| 265 | struct drm_connector base; | ||
| 266 | uint32_t connector_id; | ||
| 267 | uint32_t devices; | ||
| 268 | struct radeon_i2c_chan *ddc_bus; | ||
| 269 | int use_digital; | ||
| 270 | void *con_priv; | ||
| 271 | }; | ||
| 272 | |||
| 273 | struct radeon_framebuffer { | ||
| 274 | struct drm_framebuffer base; | ||
| 275 | struct drm_gem_object *obj; | ||
| 276 | }; | ||
| 277 | |||
| 278 | extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, | ||
| 279 | struct radeon_i2c_bus_rec *rec, | ||
| 280 | const char *name); | ||
| 281 | extern void radeon_i2c_destroy(struct radeon_i2c_chan *i2c); | ||
| 282 | extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); | ||
| 283 | extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); | ||
| 284 | |||
| 285 | extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector); | ||
| 286 | |||
| 287 | extern void radeon_compute_pll(struct radeon_pll *pll, | ||
| 288 | uint64_t freq, | ||
| 289 | uint32_t *dot_clock_p, | ||
| 290 | uint32_t *fb_div_p, | ||
| 291 | uint32_t *frac_fb_div_p, | ||
| 292 | uint32_t *ref_div_p, | ||
| 293 | uint32_t *post_div_p, | ||
| 294 | int flags); | ||
| 295 | |||
| 296 | struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index); | ||
| 297 | struct drm_encoder *radeon_encoder_legacy_primary_dac_add(struct drm_device *dev, int bios_index, int with_tv); | ||
| 298 | struct drm_encoder *radeon_encoder_legacy_tv_dac_add(struct drm_device *dev, int bios_index, int with_tv); | ||
| 299 | struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, int bios_index); | ||
| 300 | struct drm_encoder *radeon_encoder_legacy_tmds_ext_add(struct drm_device *dev, int bios_index); | ||
| 301 | extern void atombios_external_tmds_setup(struct drm_encoder *encoder, int action); | ||
| 302 | extern int atombios_get_encoder_mode(struct drm_encoder *encoder); | ||
| 303 | |||
| 304 | extern void radeon_crtc_load_lut(struct drm_crtc *crtc); | ||
| 305 | extern int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, | ||
| 306 | struct drm_framebuffer *old_fb); | ||
| 307 | extern int atombios_crtc_mode_set(struct drm_crtc *crtc, | ||
| 308 | struct drm_display_mode *mode, | ||
| 309 | struct drm_display_mode *adjusted_mode, | ||
| 310 | int x, int y, | ||
| 311 | struct drm_framebuffer *old_fb); | ||
| 312 | extern void atombios_crtc_dpms(struct drm_crtc *crtc, int mode); | ||
| 313 | |||
| 314 | extern int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, | ||
| 315 | struct drm_framebuffer *old_fb); | ||
| 316 | extern void radeon_legacy_atom_set_surface(struct drm_crtc *crtc); | ||
| 317 | |||
| 318 | extern int radeon_crtc_cursor_set(struct drm_crtc *crtc, | ||
| 319 | struct drm_file *file_priv, | ||
| 320 | uint32_t handle, | ||
| 321 | uint32_t width, | ||
| 322 | uint32_t height); | ||
| 323 | extern int radeon_crtc_cursor_move(struct drm_crtc *crtc, | ||
| 324 | int x, int y); | ||
| 325 | |||
| 326 | extern bool radeon_atom_get_clock_info(struct drm_device *dev); | ||
| 327 | extern bool radeon_combios_get_clock_info(struct drm_device *dev); | ||
| 328 | extern struct radeon_encoder_atom_dig * | ||
| 329 | radeon_atombios_get_lvds_info(struct radeon_encoder *encoder); | ||
| 330 | extern struct radeon_encoder_int_tmds * | ||
| 331 | radeon_atombios_get_tmds_info(struct radeon_encoder *encoder); | ||
| 332 | extern struct radeon_encoder_primary_dac * | ||
| 333 | radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder); | ||
| 334 | extern struct radeon_encoder_tv_dac * | ||
| 335 | radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder); | ||
| 336 | extern struct radeon_encoder_lvds * | ||
| 337 | radeon_combios_get_lvds_info(struct radeon_encoder *encoder); | ||
| 338 | extern struct radeon_encoder_int_tmds * | ||
| 339 | radeon_combios_get_tmds_info(struct radeon_encoder *encoder); | ||
| 340 | extern void radeon_combios_get_ext_tmds_info(struct radeon_encoder *encoder); | ||
| 341 | extern struct radeon_encoder_tv_dac * | ||
| 342 | radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder); | ||
| 343 | extern struct radeon_encoder_primary_dac * | ||
| 344 | radeon_combios_get_primary_dac_info(struct radeon_encoder *encoder); | ||
| 345 | extern void radeon_combios_output_lock(struct drm_encoder *encoder, bool lock); | ||
| 346 | extern void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev); | ||
| 347 | extern void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock); | ||
| 348 | extern void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev); | ||
| 349 | extern void | ||
| 350 | radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc); | ||
| 351 | extern void | ||
| 352 | radeon_atombios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on); | ||
| 353 | extern void | ||
| 354 | radeon_combios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc); | ||
| 355 | extern void | ||
| 356 | radeon_combios_encoder_dpms_scratch_regs(struct drm_encoder *encoder, bool on); | ||
| 357 | extern void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, | ||
| 358 | u16 blue, int regno); | ||
| 359 | struct drm_framebuffer *radeon_framebuffer_create(struct drm_device *dev, | ||
| 360 | struct drm_mode_fb_cmd *mode_cmd, | ||
| 361 | struct drm_gem_object *obj); | ||
| 362 | |||
| 363 | int radeonfb_probe(struct drm_device *dev); | ||
| 364 | |||
| 365 | int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb); | ||
| 366 | bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev); | ||
| 367 | bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev); | ||
| 368 | void radeon_atombios_init_crtc(struct drm_device *dev, | ||
| 369 | struct radeon_crtc *radeon_crtc); | ||
| 370 | void radeon_legacy_init_crtc(struct drm_device *dev, | ||
| 371 | struct radeon_crtc *radeon_crtc); | ||
| 372 | void radeon_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state); | ||
| 373 | |||
| 374 | void radeon_get_clock_info(struct drm_device *dev); | ||
| 375 | |||
| 376 | extern bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev); | ||
| 377 | extern bool radeon_get_atom_connector_info_from_supported_devices_table(struct drm_device *dev); | ||
| 378 | |||
| 379 | void radeon_rmx_mode_fixup(struct drm_encoder *encoder, | ||
| 380 | struct drm_display_mode *mode, | ||
| 381 | struct drm_display_mode *adjusted_mode); | ||
| 382 | void radeon_enc_destroy(struct drm_encoder *encoder); | ||
| 383 | void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj); | ||
| 384 | void radeon_combios_asic_init(struct drm_device *dev); | ||
| 385 | extern int radeon_static_clocks_init(struct drm_device *dev); | ||
| 386 | void radeon_init_disp_bw_legacy(struct drm_device *dev, | ||
| 387 | struct drm_display_mode *mode1, | ||
| 388 | uint32_t pixel_bytes1, | ||
| 389 | struct drm_display_mode *mode2, | ||
| 390 | uint32_t pixel_bytes2); | ||
| 391 | void radeon_init_disp_bw_avivo(struct drm_device *dev, | ||
| 392 | struct drm_display_mode *mode1, | ||
| 393 | uint32_t pixel_bytes1, | ||
| 394 | struct drm_display_mode *mode2, | ||
| 395 | uint32_t pixel_bytes2); | ||
| 396 | void radeon_init_disp_bandwidth(struct drm_device *dev); | ||
| 397 | |||
| 398 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c new file mode 100644 index 000000000000..983e8df5e000 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
| @@ -0,0 +1,511 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2009 Jerome Glisse. | ||
| 3 | * All Rights Reserved. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * 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, sub license, 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 16 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 17 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 18 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 19 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 20 | * | ||
| 21 | * The above copyright notice and this permission notice (including the | ||
| 22 | * next paragraph) shall be included in all copies or substantial portions | ||
| 23 | * of the Software. | ||
| 24 | * | ||
| 25 | */ | ||
| 26 | /* | ||
| 27 | * Authors: | ||
| 28 | * Jerome Glisse <glisse@freedesktop.org> | ||
| 29 | * Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> | ||
| 30 | * Dave Airlie | ||
| 31 | */ | ||
| 32 | #include <linux/list.h> | ||
| 33 | #include <drm/drmP.h> | ||
| 34 | #include "radeon_drm.h" | ||
| 35 | #include "radeon.h" | ||
| 36 | |||
| 37 | struct radeon_object { | ||
| 38 | struct ttm_buffer_object tobj; | ||
| 39 | struct list_head list; | ||
| 40 | struct radeon_device *rdev; | ||
| 41 | struct drm_gem_object *gobj; | ||
| 42 | struct ttm_bo_kmap_obj kmap; | ||
| 43 | unsigned pin_count; | ||
| 44 | uint64_t gpu_addr; | ||
| 45 | void *kptr; | ||
| 46 | bool is_iomem; | ||
| 47 | }; | ||
| 48 | |||
| 49 | int radeon_ttm_init(struct radeon_device *rdev); | ||
| 50 | void radeon_ttm_fini(struct radeon_device *rdev); | ||
| 51 | |||
| 52 | /* | ||
| 53 | * To exclude mutual BO access we rely on bo_reserve exclusion, as all | ||
| 54 | * function are calling it. | ||
| 55 | */ | ||
| 56 | |||
| 57 | static int radeon_object_reserve(struct radeon_object *robj, bool interruptible) | ||
| 58 | { | ||
| 59 | return ttm_bo_reserve(&robj->tobj, interruptible, false, false, 0); | ||
| 60 | } | ||
| 61 | |||
| 62 | static void radeon_object_unreserve(struct radeon_object *robj) | ||
| 63 | { | ||
| 64 | ttm_bo_unreserve(&robj->tobj); | ||
| 65 | } | ||
| 66 | |||
| 67 | static void radeon_ttm_object_object_destroy(struct ttm_buffer_object *tobj) | ||
| 68 | { | ||
| 69 | struct radeon_object *robj; | ||
| 70 | |||
| 71 | robj = container_of(tobj, struct radeon_object, tobj); | ||
| 72 | list_del_init(&robj->list); | ||
| 73 | kfree(robj); | ||
| 74 | } | ||
| 75 | |||
| 76 | static inline void radeon_object_gpu_addr(struct radeon_object *robj) | ||
| 77 | { | ||
| 78 | /* Default gpu address */ | ||
| 79 | robj->gpu_addr = 0xFFFFFFFFFFFFFFFFULL; | ||
| 80 | if (robj->tobj.mem.mm_node == NULL) { | ||
| 81 | return; | ||
| 82 | } | ||
| 83 | robj->gpu_addr = ((u64)robj->tobj.mem.mm_node->start) << PAGE_SHIFT; | ||
| 84 | switch (robj->tobj.mem.mem_type) { | ||
| 85 | case TTM_PL_VRAM: | ||
| 86 | robj->gpu_addr += (u64)robj->rdev->mc.vram_location; | ||
| 87 | break; | ||
| 88 | case TTM_PL_TT: | ||
| 89 | robj->gpu_addr += (u64)robj->rdev->mc.gtt_location; | ||
| 90 | break; | ||
| 91 | default: | ||
| 92 | DRM_ERROR("Unknown placement %d\n", robj->tobj.mem.mem_type); | ||
| 93 | robj->gpu_addr = 0xFFFFFFFFFFFFFFFFULL; | ||
| 94 | return; | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | static inline uint32_t radeon_object_flags_from_domain(uint32_t domain) | ||
| 99 | { | ||
| 100 | uint32_t flags = 0; | ||
| 101 | if (domain & RADEON_GEM_DOMAIN_VRAM) { | ||
| 102 | flags |= TTM_PL_FLAG_VRAM; | ||
| 103 | } | ||
| 104 | if (domain & RADEON_GEM_DOMAIN_GTT) { | ||
| 105 | flags |= TTM_PL_FLAG_TT; | ||
| 106 | } | ||
| 107 | if (domain & RADEON_GEM_DOMAIN_CPU) { | ||
| 108 | flags |= TTM_PL_FLAG_SYSTEM; | ||
| 109 | } | ||
| 110 | if (!flags) { | ||
| 111 | flags |= TTM_PL_FLAG_SYSTEM; | ||
| 112 | } | ||
| 113 | return flags; | ||
| 114 | } | ||
| 115 | |||
| 116 | int radeon_object_create(struct radeon_device *rdev, | ||
| 117 | struct drm_gem_object *gobj, | ||
| 118 | unsigned long size, | ||
| 119 | bool kernel, | ||
| 120 | uint32_t domain, | ||
| 121 | bool interruptible, | ||
| 122 | struct radeon_object **robj_ptr) | ||
| 123 | { | ||
| 124 | struct radeon_object *robj; | ||
| 125 | enum ttm_bo_type type; | ||
| 126 | uint32_t flags; | ||
| 127 | int r; | ||
| 128 | |||
| 129 | if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) { | ||
| 130 | rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; | ||
| 131 | } | ||
| 132 | if (kernel) { | ||
| 133 | type = ttm_bo_type_kernel; | ||
| 134 | } else { | ||
| 135 | type = ttm_bo_type_device; | ||
| 136 | } | ||
| 137 | *robj_ptr = NULL; | ||
| 138 | robj = kzalloc(sizeof(struct radeon_object), GFP_KERNEL); | ||
| 139 | if (robj == NULL) { | ||
| 140 | return -ENOMEM; | ||
| 141 | } | ||
| 142 | robj->rdev = rdev; | ||
| 143 | robj->gobj = gobj; | ||
| 144 | INIT_LIST_HEAD(&robj->list); | ||
| 145 | |||
| 146 | flags = radeon_object_flags_from_domain(domain); | ||
| 147 | r = ttm_buffer_object_init(&rdev->mman.bdev, &robj->tobj, size, type, flags, | ||
| 148 | 0, 0, false, NULL, size, | ||
| 149 | &radeon_ttm_object_object_destroy); | ||
| 150 | if (unlikely(r != 0)) { | ||
| 151 | /* ttm call radeon_ttm_object_object_destroy if error happen */ | ||
| 152 | DRM_ERROR("Failed to allocate TTM object (%ld, 0x%08X, %u)\n", | ||
| 153 | size, flags, 0); | ||
| 154 | return r; | ||
| 155 | } | ||
| 156 | *robj_ptr = robj; | ||
| 157 | if (gobj) { | ||
| 158 | list_add_tail(&robj->list, &rdev->gem.objects); | ||
| 159 | } | ||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | int radeon_object_kmap(struct radeon_object *robj, void **ptr) | ||
| 164 | { | ||
| 165 | int r; | ||
| 166 | |||
| 167 | spin_lock(&robj->tobj.lock); | ||
| 168 | if (robj->kptr) { | ||
| 169 | if (ptr) { | ||
| 170 | *ptr = robj->kptr; | ||
| 171 | } | ||
| 172 | spin_unlock(&robj->tobj.lock); | ||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | spin_unlock(&robj->tobj.lock); | ||
| 176 | r = ttm_bo_kmap(&robj->tobj, 0, robj->tobj.num_pages, &robj->kmap); | ||
| 177 | if (r) { | ||
| 178 | return r; | ||
| 179 | } | ||
| 180 | spin_lock(&robj->tobj.lock); | ||
| 181 | robj->kptr = ttm_kmap_obj_virtual(&robj->kmap, &robj->is_iomem); | ||
| 182 | spin_unlock(&robj->tobj.lock); | ||
| 183 | if (ptr) { | ||
| 184 | *ptr = robj->kptr; | ||
| 185 | } | ||
| 186 | return 0; | ||
| 187 | } | ||
| 188 | |||
| 189 | void radeon_object_kunmap(struct radeon_object *robj) | ||
| 190 | { | ||
| 191 | spin_lock(&robj->tobj.lock); | ||
| 192 | if (robj->kptr == NULL) { | ||
| 193 | spin_unlock(&robj->tobj.lock); | ||
| 194 | return; | ||
| 195 | } | ||
| 196 | robj->kptr = NULL; | ||
| 197 | spin_unlock(&robj->tobj.lock); | ||
| 198 | ttm_bo_kunmap(&robj->kmap); | ||
| 199 | } | ||
| 200 | |||
| 201 | void radeon_object_unref(struct radeon_object **robj) | ||
| 202 | { | ||
| 203 | struct ttm_buffer_object *tobj; | ||
| 204 | |||
| 205 | if ((*robj) == NULL) { | ||
| 206 | return; | ||
| 207 | } | ||
| 208 | tobj = &((*robj)->tobj); | ||
| 209 | ttm_bo_unref(&tobj); | ||
| 210 | if (tobj == NULL) { | ||
| 211 | *robj = NULL; | ||
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 215 | int radeon_object_mmap(struct radeon_object *robj, uint64_t *offset) | ||
| 216 | { | ||
| 217 | *offset = robj->tobj.addr_space_offset; | ||
| 218 | return 0; | ||
| 219 | } | ||
| 220 | |||
| 221 | int radeon_object_pin(struct radeon_object *robj, uint32_t domain, | ||
| 222 | uint64_t *gpu_addr) | ||
| 223 | { | ||
| 224 | uint32_t flags; | ||
| 225 | uint32_t tmp; | ||
| 226 | void *fbptr; | ||
| 227 | int r; | ||
| 228 | |||
| 229 | flags = radeon_object_flags_from_domain(domain); | ||
| 230 | spin_lock(&robj->tobj.lock); | ||
| 231 | if (robj->pin_count) { | ||
| 232 | robj->pin_count++; | ||
| 233 | if (gpu_addr != NULL) { | ||
| 234 | *gpu_addr = robj->gpu_addr; | ||
| 235 | } | ||
| 236 | spin_unlock(&robj->tobj.lock); | ||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | spin_unlock(&robj->tobj.lock); | ||
| 240 | r = radeon_object_reserve(robj, false); | ||
| 241 | if (unlikely(r != 0)) { | ||
| 242 | DRM_ERROR("radeon: failed to reserve object for pinning it.\n"); | ||
| 243 | return r; | ||
| 244 | } | ||
| 245 | if (robj->rdev->fbdev_robj == robj) { | ||
| 246 | mutex_lock(&robj->rdev->fbdev_info->lock); | ||
| 247 | radeon_object_kunmap(robj); | ||
| 248 | } | ||
| 249 | tmp = robj->tobj.mem.placement; | ||
| 250 | ttm_flag_masked(&tmp, flags, TTM_PL_MASK_MEM); | ||
| 251 | robj->tobj.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT | TTM_PL_MASK_CACHING; | ||
| 252 | r = ttm_buffer_object_validate(&robj->tobj, | ||
| 253 | robj->tobj.proposed_placement, | ||
| 254 | false, false); | ||
| 255 | radeon_object_gpu_addr(robj); | ||
| 256 | if (gpu_addr != NULL) { | ||
| 257 | *gpu_addr = robj->gpu_addr; | ||
| 258 | } | ||
| 259 | robj->pin_count = 1; | ||
| 260 | if (unlikely(r != 0)) { | ||
| 261 | DRM_ERROR("radeon: failed to pin object.\n"); | ||
| 262 | } | ||
| 263 | radeon_object_unreserve(robj); | ||
| 264 | if (robj->rdev->fbdev_robj == robj) { | ||
| 265 | if (!r) { | ||
| 266 | r = radeon_object_kmap(robj, &fbptr); | ||
| 267 | } | ||
| 268 | if (!r) { | ||
| 269 | robj->rdev->fbdev_info->screen_base = fbptr; | ||
| 270 | robj->rdev->fbdev_info->fix.smem_start = (unsigned long)fbptr; | ||
| 271 | } | ||
| 272 | mutex_unlock(&robj->rdev->fbdev_info->lock); | ||
| 273 | } | ||
| 274 | return r; | ||
| 275 | } | ||
| 276 | |||
| 277 | void radeon_object_unpin(struct radeon_object *robj) | ||
| 278 | { | ||
| 279 | uint32_t flags; | ||
| 280 | void *fbptr; | ||
| 281 | int r; | ||
| 282 | |||
| 283 | spin_lock(&robj->tobj.lock); | ||
| 284 | if (!robj->pin_count) { | ||
| 285 | spin_unlock(&robj->tobj.lock); | ||
| 286 | printk(KERN_WARNING "Unpin not necessary for %p !\n", robj); | ||
| 287 | return; | ||
| 288 | } | ||
| 289 | robj->pin_count--; | ||
| 290 | if (robj->pin_count) { | ||
| 291 | spin_unlock(&robj->tobj.lock); | ||
| 292 | return; | ||
| 293 | } | ||
| 294 | spin_unlock(&robj->tobj.lock); | ||
| 295 | r = radeon_object_reserve(robj, false); | ||
| 296 | if (unlikely(r != 0)) { | ||
| 297 | DRM_ERROR("radeon: failed to reserve object for unpinning it.\n"); | ||
| 298 | return; | ||
| 299 | } | ||
| 300 | if (robj->rdev->fbdev_robj == robj) { | ||
| 301 | mutex_lock(&robj->rdev->fbdev_info->lock); | ||
| 302 | radeon_object_kunmap(robj); | ||
| 303 | } | ||
| 304 | flags = robj->tobj.mem.placement; | ||
| 305 | robj->tobj.proposed_placement = flags & ~TTM_PL_FLAG_NO_EVICT; | ||
| 306 | r = ttm_buffer_object_validate(&robj->tobj, | ||
| 307 | robj->tobj.proposed_placement, | ||
| 308 | false, false); | ||
| 309 | if (unlikely(r != 0)) { | ||
| 310 | DRM_ERROR("radeon: failed to unpin buffer.\n"); | ||
| 311 | } | ||
| 312 | radeon_object_unreserve(robj); | ||
| 313 | if (robj->rdev->fbdev_robj == robj) { | ||
| 314 | if (!r) { | ||
| 315 | r = radeon_object_kmap(robj, &fbptr); | ||
| 316 | } | ||
| 317 | if (!r) { | ||
| 318 | robj->rdev->fbdev_info->screen_base = fbptr; | ||
| 319 | robj->rdev->fbdev_info->fix.smem_start = (unsigned long)fbptr; | ||
| 320 | } | ||
| 321 | mutex_unlock(&robj->rdev->fbdev_info->lock); | ||
| 322 | } | ||
| 323 | } | ||
| 324 | |||
| 325 | int radeon_object_wait(struct radeon_object *robj) | ||
| 326 | { | ||
| 327 | int r = 0; | ||
| 328 | |||
| 329 | /* FIXME: should use block reservation instead */ | ||
| 330 | r = radeon_object_reserve(robj, true); | ||
| 331 | if (unlikely(r != 0)) { | ||
| 332 | DRM_ERROR("radeon: failed to reserve object for waiting.\n"); | ||
| 333 | return r; | ||
| 334 | } | ||
| 335 | spin_lock(&robj->tobj.lock); | ||
| 336 | if (robj->tobj.sync_obj) { | ||
| 337 | r = ttm_bo_wait(&robj->tobj, true, false, false); | ||
| 338 | } | ||
| 339 | spin_unlock(&robj->tobj.lock); | ||
| 340 | radeon_object_unreserve(robj); | ||
| 341 | return r; | ||
| 342 | } | ||
| 343 | |||
| 344 | int radeon_object_evict_vram(struct radeon_device *rdev) | ||
| 345 | { | ||
| 346 | if (rdev->flags & RADEON_IS_IGP) { | ||
| 347 | /* Useless to evict on IGP chips */ | ||
| 348 | return 0; | ||
| 349 | } | ||
| 350 | return ttm_bo_evict_mm(&rdev->mman.bdev, TTM_PL_VRAM); | ||
| 351 | } | ||
| 352 | |||
| 353 | void radeon_object_force_delete(struct radeon_device *rdev) | ||
| 354 | { | ||
| 355 | struct radeon_object *robj, *n; | ||
| 356 | struct drm_gem_object *gobj; | ||
| 357 | |||
| 358 | if (list_empty(&rdev->gem.objects)) { | ||
| 359 | return; | ||
| 360 | } | ||
| 361 | DRM_ERROR("Userspace still has active objects !\n"); | ||
| 362 | list_for_each_entry_safe(robj, n, &rdev->gem.objects, list) { | ||
| 363 | mutex_lock(&rdev->ddev->struct_mutex); | ||
| 364 | gobj = robj->gobj; | ||
| 365 | DRM_ERROR("Force free for (%p,%p,%lu,%lu)\n", | ||
| 366 | gobj, robj, (unsigned long)gobj->size, | ||
| 367 | *((unsigned long *)&gobj->refcount)); | ||
| 368 | list_del_init(&robj->list); | ||
| 369 | radeon_object_unref(&robj); | ||
| 370 | gobj->driver_private = NULL; | ||
| 371 | drm_gem_object_unreference(gobj); | ||
| 372 | mutex_unlock(&rdev->ddev->struct_mutex); | ||
| 373 | } | ||
| 374 | } | ||
| 375 | |||
| 376 | int radeon_object_init(struct radeon_device *rdev) | ||
| 377 | { | ||
| 378 | return radeon_ttm_init(rdev); | ||
| 379 | } | ||
| 380 | |||
| 381 | void radeon_object_fini(struct radeon_device *rdev) | ||
| 382 | { | ||
| 383 | radeon_ttm_fini(rdev); | ||
| 384 | } | ||
| 385 | |||
| 386 | void radeon_object_list_add_object(struct radeon_object_list *lobj, | ||
| 387 | struct list_head *head) | ||
| 388 | { | ||
| 389 | if (lobj->wdomain) { | ||
| 390 | list_add(&lobj->list, head); | ||
| 391 | } else { | ||
| 392 | list_add_tail(&lobj->list, head); | ||
| 393 | } | ||
| 394 | } | ||
| 395 | |||
| 396 | int radeon_object_list_reserve(struct list_head *head) | ||
| 397 | { | ||
| 398 | struct radeon_object_list *lobj; | ||
| 399 | struct list_head *i; | ||
| 400 | int r; | ||
| 401 | |||
| 402 | list_for_each(i, head) { | ||
| 403 | lobj = list_entry(i, struct radeon_object_list, list); | ||
| 404 | if (!lobj->robj->pin_count) { | ||
| 405 | r = radeon_object_reserve(lobj->robj, true); | ||
| 406 | if (unlikely(r != 0)) { | ||
| 407 | DRM_ERROR("radeon: failed to reserve object.\n"); | ||
| 408 | return r; | ||
| 409 | } | ||
| 410 | } else { | ||
| 411 | } | ||
| 412 | } | ||
| 413 | return 0; | ||
| 414 | } | ||
| 415 | |||
| 416 | void radeon_object_list_unreserve(struct list_head *head) | ||
| 417 | { | ||
| 418 | struct radeon_object_list *lobj; | ||
| 419 | struct list_head *i; | ||
| 420 | |||
| 421 | list_for_each(i, head) { | ||
| 422 | lobj = list_entry(i, struct radeon_object_list, list); | ||
| 423 | if (!lobj->robj->pin_count) { | ||
| 424 | radeon_object_unreserve(lobj->robj); | ||
| 425 | } else { | ||
| 426 | } | ||
| 427 | } | ||
| 428 | } | ||
| 429 | |||
| 430 | int radeon_object_list_validate(struct list_head *head, void *fence) | ||
| 431 | { | ||
| 432 | struct radeon_object_list *lobj; | ||
| 433 | struct radeon_object *robj; | ||
| 434 | struct radeon_fence *old_fence = NULL; | ||
| 435 | struct list_head *i; | ||
| 436 | uint32_t flags; | ||
| 437 | int r; | ||
| 438 | |||
| 439 | r = radeon_object_list_reserve(head); | ||
| 440 | if (unlikely(r != 0)) { | ||
| 441 | radeon_object_list_unreserve(head); | ||
| 442 | return r; | ||
| 443 | } | ||
| 444 | list_for_each(i, head) { | ||
| 445 | lobj = list_entry(i, struct radeon_object_list, list); | ||
| 446 | robj = lobj->robj; | ||
| 447 | if (lobj->wdomain) { | ||
| 448 | flags = radeon_object_flags_from_domain(lobj->wdomain); | ||
| 449 | flags |= TTM_PL_FLAG_TT; | ||
| 450 | } else { | ||
| 451 | flags = radeon_object_flags_from_domain(lobj->rdomain); | ||
| 452 | flags |= TTM_PL_FLAG_TT; | ||
| 453 | flags |= TTM_PL_FLAG_VRAM; | ||
| 454 | } | ||
| 455 | if (!robj->pin_count) { | ||
| 456 | robj->tobj.proposed_placement = flags | TTM_PL_MASK_CACHING; | ||
| 457 | r = ttm_buffer_object_validate(&robj->tobj, | ||
| 458 | robj->tobj.proposed_placement, | ||
| 459 | true, false); | ||
| 460 | if (unlikely(r)) { | ||
| 461 | radeon_object_list_unreserve(head); | ||
| 462 | DRM_ERROR("radeon: failed to validate.\n"); | ||
| 463 | return r; | ||
| 464 | } | ||
| 465 | radeon_object_gpu_addr(robj); | ||
| 466 | } | ||
| 467 | lobj->gpu_offset = robj->gpu_addr; | ||
| 468 | if (fence) { | ||
| 469 | old_fence = (struct radeon_fence *)robj->tobj.sync_obj; | ||
| 470 | robj->tobj.sync_obj = radeon_fence_ref(fence); | ||
| 471 | robj->tobj.sync_obj_arg = NULL; | ||
| 472 | } | ||
| 473 | if (old_fence) { | ||
| 474 | radeon_fence_unref(&old_fence); | ||
| 475 | } | ||
| 476 | } | ||
| 477 | return 0; | ||
| 478 | } | ||
| 479 | |||
| 480 | void radeon_object_list_unvalidate(struct list_head *head) | ||
| 481 | { | ||
| 482 | struct radeon_object_list *lobj; | ||
| 483 | struct radeon_fence *old_fence = NULL; | ||
| 484 | struct list_head *i; | ||
| 485 | |||
| 486 | list_for_each(i, head) { | ||
| 487 | lobj = list_entry(i, struct radeon_object_list, list); | ||
| 488 | old_fence = (struct radeon_fence *)lobj->robj->tobj.sync_obj; | ||
| 489 | lobj->robj->tobj.sync_obj = NULL; | ||
| 490 | if (old_fence) { | ||
| 491 | radeon_fence_unref(&old_fence); | ||
| 492 | } | ||
| 493 | } | ||
| 494 | radeon_object_list_unreserve(head); | ||
| 495 | } | ||
| 496 | |||
| 497 | void radeon_object_list_clean(struct list_head *head) | ||
| 498 | { | ||
| 499 | radeon_object_list_unreserve(head); | ||
| 500 | } | ||
| 501 | |||
| 502 | int radeon_object_fbdev_mmap(struct radeon_object *robj, | ||
| 503 | struct vm_area_struct *vma) | ||
| 504 | { | ||
| 505 | return ttm_fbdev_mmap(vma, &robj->tobj); | ||
| 506 | } | ||
| 507 | |||
| 508 | unsigned long radeon_object_size(struct radeon_object *robj) | ||
| 509 | { | ||
| 510 | return robj->tobj.num_pages << PAGE_SHIFT; | ||
| 511 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h new file mode 100644 index 000000000000..473e4775dc5a --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_object.h | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #ifndef __RADEON_OBJECT_H__ | ||
| 29 | #define __RADEON_OBJECT_H__ | ||
| 30 | |||
| 31 | #include <ttm/ttm_bo_api.h> | ||
| 32 | #include <ttm/ttm_bo_driver.h> | ||
| 33 | #include <ttm/ttm_placement.h> | ||
| 34 | #include <ttm/ttm_module.h> | ||
| 35 | |||
| 36 | /* | ||
| 37 | * TTM. | ||
| 38 | */ | ||
| 39 | struct radeon_mman { | ||
| 40 | struct ttm_global_reference mem_global_ref; | ||
| 41 | bool mem_global_referenced; | ||
| 42 | struct ttm_bo_device bdev; | ||
| 43 | }; | ||
| 44 | |||
| 45 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h new file mode 100644 index 000000000000..6d3d90406a24 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_reg.h | |||
| @@ -0,0 +1,3570 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and | ||
| 3 | * VA Linux Systems Inc., Fremont, California. | ||
| 4 | * | ||
| 5 | * All Rights Reserved. | ||
| 6 | * | ||
| 7 | * Permission is hereby granted, free of charge, to any person obtaining | ||
| 8 | * a copy of this software and associated documentation files (the | ||
| 9 | * "Software"), to deal in the Software without restriction, including | ||
| 10 | * without limitation on the rights to use, copy, modify, merge, | ||
| 11 | * publish, distribute, sublicense, and/or sell copies of the Software, | ||
| 12 | * and to permit persons to whom the Software is furnished to do so, | ||
| 13 | * subject to the following conditions: | ||
| 14 | * | ||
| 15 | * The above copyright notice and this permission notice (including the | ||
| 16 | * next paragraph) shall be included in all copies or substantial | ||
| 17 | * portions of the Software. | ||
| 18 | * | ||
| 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
| 20 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||
| 21 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
| 22 | * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR | ||
| 23 | * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
| 24 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 26 | * DEALINGS IN THE SOFTWARE. | ||
| 27 | */ | ||
| 28 | |||
| 29 | /* | ||
| 30 | * Authors: | ||
| 31 | * Kevin E. Martin <martin@xfree86.org> | ||
| 32 | * Rickard E. Faith <faith@valinux.com> | ||
| 33 | * Alan Hourihane <alanh@fairlite.demon.co.uk> | ||
| 34 | * | ||
| 35 | * References: | ||
| 36 | * | ||
| 37 | * !!!! FIXME !!!! | ||
| 38 | * RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical | ||
| 39 | * Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April | ||
| 40 | * 1999. | ||
| 41 | * | ||
| 42 | * !!!! FIXME !!!! | ||
| 43 | * RAGE 128 Software Development Manual (Technical Reference Manual P/N | ||
| 44 | * SDK-G04000 Rev. 0.01), ATI Technologies: June 1999. | ||
| 45 | * | ||
| 46 | */ | ||
| 47 | |||
| 48 | /* !!!! FIXME !!!! NOTE: THIS FILE HAS BEEN CONVERTED FROM r128_reg.h | ||
| 49 | * AND CONTAINS REGISTERS AND REGISTER DEFINITIONS THAT ARE NOT CORRECT | ||
| 50 | * ON THE RADEON. A FULL AUDIT OF THIS CODE IS NEEDED! */ | ||
| 51 | #ifndef _RADEON_REG_H_ | ||
| 52 | #define _RADEON_REG_H_ | ||
| 53 | |||
| 54 | #include "r300_reg.h" | ||
| 55 | #include "r500_reg.h" | ||
| 56 | #include "r600_reg.h" | ||
| 57 | |||
| 58 | |||
| 59 | #define RADEON_MC_AGP_LOCATION 0x014c | ||
| 60 | #define RADEON_MC_AGP_START_MASK 0x0000FFFF | ||
| 61 | #define RADEON_MC_AGP_START_SHIFT 0 | ||
| 62 | #define RADEON_MC_AGP_TOP_MASK 0xFFFF0000 | ||
| 63 | #define RADEON_MC_AGP_TOP_SHIFT 16 | ||
| 64 | #define RADEON_MC_FB_LOCATION 0x0148 | ||
| 65 | #define RADEON_MC_FB_START_MASK 0x0000FFFF | ||
| 66 | #define RADEON_MC_FB_START_SHIFT 0 | ||
| 67 | #define RADEON_MC_FB_TOP_MASK 0xFFFF0000 | ||
| 68 | #define RADEON_MC_FB_TOP_SHIFT 16 | ||
| 69 | #define RADEON_AGP_BASE_2 0x015c /* r200+ only */ | ||
| 70 | #define RADEON_AGP_BASE 0x0170 | ||
| 71 | |||
| 72 | #define ATI_DATATYPE_VQ 0 | ||
| 73 | #define ATI_DATATYPE_CI4 1 | ||
| 74 | #define ATI_DATATYPE_CI8 2 | ||
| 75 | #define ATI_DATATYPE_ARGB1555 3 | ||
| 76 | #define ATI_DATATYPE_RGB565 4 | ||
| 77 | #define ATI_DATATYPE_RGB888 5 | ||
| 78 | #define ATI_DATATYPE_ARGB8888 6 | ||
| 79 | #define ATI_DATATYPE_RGB332 7 | ||
| 80 | #define ATI_DATATYPE_Y8 8 | ||
| 81 | #define ATI_DATATYPE_RGB8 9 | ||
| 82 | #define ATI_DATATYPE_CI16 10 | ||
| 83 | #define ATI_DATATYPE_VYUY_422 11 | ||
| 84 | #define ATI_DATATYPE_YVYU_422 12 | ||
| 85 | #define ATI_DATATYPE_AYUV_444 14 | ||
| 86 | #define ATI_DATATYPE_ARGB4444 15 | ||
| 87 | |||
| 88 | /* Registers for 2D/Video/Overlay */ | ||
| 89 | #define RADEON_ADAPTER_ID 0x0f2c /* PCI */ | ||
| 90 | #define RADEON_AGP_BASE 0x0170 | ||
| 91 | #define RADEON_AGP_CNTL 0x0174 | ||
| 92 | # define RADEON_AGP_APER_SIZE_256MB (0x00 << 0) | ||
| 93 | # define RADEON_AGP_APER_SIZE_128MB (0x20 << 0) | ||
| 94 | # define RADEON_AGP_APER_SIZE_64MB (0x30 << 0) | ||
| 95 | # define RADEON_AGP_APER_SIZE_32MB (0x38 << 0) | ||
| 96 | # define RADEON_AGP_APER_SIZE_16MB (0x3c << 0) | ||
| 97 | # define RADEON_AGP_APER_SIZE_8MB (0x3e << 0) | ||
| 98 | # define RADEON_AGP_APER_SIZE_4MB (0x3f << 0) | ||
| 99 | # define RADEON_AGP_APER_SIZE_MASK (0x3f << 0) | ||
| 100 | #define RADEON_STATUS_PCI_CONFIG 0x06 | ||
| 101 | # define RADEON_CAP_LIST 0x100000 | ||
| 102 | #define RADEON_CAPABILITIES_PTR_PCI_CONFIG 0x34 /* offset in PCI config*/ | ||
| 103 | # define RADEON_CAP_PTR_MASK 0xfc /* mask off reserved bits of CAP_PTR */ | ||
| 104 | # define RADEON_CAP_ID_NULL 0x00 /* End of capability list */ | ||
| 105 | # define RADEON_CAP_ID_AGP 0x02 /* AGP capability ID */ | ||
| 106 | # define RADEON_CAP_ID_EXP 0x10 /* PCI Express */ | ||
| 107 | #define RADEON_AGP_COMMAND 0x0f60 /* PCI */ | ||
| 108 | #define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config*/ | ||
| 109 | # define RADEON_AGP_ENABLE (1<<8) | ||
| 110 | #define RADEON_AGP_PLL_CNTL 0x000b /* PLL */ | ||
| 111 | #define RADEON_AGP_STATUS 0x0f5c /* PCI */ | ||
| 112 | # define RADEON_AGP_1X_MODE 0x01 | ||
| 113 | # define RADEON_AGP_2X_MODE 0x02 | ||
| 114 | # define RADEON_AGP_4X_MODE 0x04 | ||
| 115 | # define RADEON_AGP_FW_MODE 0x10 | ||
| 116 | # define RADEON_AGP_MODE_MASK 0x17 | ||
| 117 | # define RADEON_AGPv3_MODE 0x08 | ||
| 118 | # define RADEON_AGPv3_4X_MODE 0x01 | ||
| 119 | # define RADEON_AGPv3_8X_MODE 0x02 | ||
| 120 | #define RADEON_ATTRDR 0x03c1 /* VGA */ | ||
| 121 | #define RADEON_ATTRDW 0x03c0 /* VGA */ | ||
| 122 | #define RADEON_ATTRX 0x03c0 /* VGA */ | ||
| 123 | #define RADEON_AUX_SC_CNTL 0x1660 | ||
| 124 | # define RADEON_AUX1_SC_EN (1 << 0) | ||
| 125 | # define RADEON_AUX1_SC_MODE_OR (0 << 1) | ||
| 126 | # define RADEON_AUX1_SC_MODE_NAND (1 << 1) | ||
| 127 | # define RADEON_AUX2_SC_EN (1 << 2) | ||
| 128 | # define RADEON_AUX2_SC_MODE_OR (0 << 3) | ||
| 129 | # define RADEON_AUX2_SC_MODE_NAND (1 << 3) | ||
| 130 | # define RADEON_AUX3_SC_EN (1 << 4) | ||
| 131 | # define RADEON_AUX3_SC_MODE_OR (0 << 5) | ||
| 132 | # define RADEON_AUX3_SC_MODE_NAND (1 << 5) | ||
| 133 | #define RADEON_AUX1_SC_BOTTOM 0x1670 | ||
| 134 | #define RADEON_AUX1_SC_LEFT 0x1664 | ||
| 135 | #define RADEON_AUX1_SC_RIGHT 0x1668 | ||
| 136 | #define RADEON_AUX1_SC_TOP 0x166c | ||
| 137 | #define RADEON_AUX2_SC_BOTTOM 0x1680 | ||
| 138 | #define RADEON_AUX2_SC_LEFT 0x1674 | ||
| 139 | #define RADEON_AUX2_SC_RIGHT 0x1678 | ||
| 140 | #define RADEON_AUX2_SC_TOP 0x167c | ||
| 141 | #define RADEON_AUX3_SC_BOTTOM 0x1690 | ||
| 142 | #define RADEON_AUX3_SC_LEFT 0x1684 | ||
| 143 | #define RADEON_AUX3_SC_RIGHT 0x1688 | ||
| 144 | #define RADEON_AUX3_SC_TOP 0x168c | ||
| 145 | #define RADEON_AUX_WINDOW_HORZ_CNTL 0x02d8 | ||
| 146 | #define RADEON_AUX_WINDOW_VERT_CNTL 0x02dc | ||
| 147 | |||
| 148 | #define RADEON_BASE_CODE 0x0f0b | ||
| 149 | #define RADEON_BIOS_0_SCRATCH 0x0010 | ||
| 150 | # define RADEON_FP_PANEL_SCALABLE (1 << 16) | ||
| 151 | # define RADEON_FP_PANEL_SCALE_EN (1 << 17) | ||
| 152 | # define RADEON_FP_CHIP_SCALE_EN (1 << 18) | ||
| 153 | # define RADEON_DRIVER_BRIGHTNESS_EN (1 << 26) | ||
| 154 | # define RADEON_DISPLAY_ROT_MASK (3 << 28) | ||
| 155 | # define RADEON_DISPLAY_ROT_00 (0 << 28) | ||
| 156 | # define RADEON_DISPLAY_ROT_90 (1 << 28) | ||
| 157 | # define RADEON_DISPLAY_ROT_180 (2 << 28) | ||
| 158 | # define RADEON_DISPLAY_ROT_270 (3 << 28) | ||
| 159 | #define RADEON_BIOS_1_SCRATCH 0x0014 | ||
| 160 | #define RADEON_BIOS_2_SCRATCH 0x0018 | ||
| 161 | #define RADEON_BIOS_3_SCRATCH 0x001c | ||
| 162 | #define RADEON_BIOS_4_SCRATCH 0x0020 | ||
| 163 | # define RADEON_CRT1_ATTACHED_MASK (3 << 0) | ||
| 164 | # define RADEON_CRT1_ATTACHED_MONO (1 << 0) | ||
| 165 | # define RADEON_CRT1_ATTACHED_COLOR (2 << 0) | ||
| 166 | # define RADEON_LCD1_ATTACHED (1 << 2) | ||
| 167 | # define RADEON_DFP1_ATTACHED (1 << 3) | ||
| 168 | # define RADEON_TV1_ATTACHED_MASK (3 << 4) | ||
| 169 | # define RADEON_TV1_ATTACHED_COMP (1 << 4) | ||
| 170 | # define RADEON_TV1_ATTACHED_SVIDEO (2 << 4) | ||
| 171 | # define RADEON_CRT2_ATTACHED_MASK (3 << 8) | ||
| 172 | # define RADEON_CRT2_ATTACHED_MONO (1 << 8) | ||
| 173 | # define RADEON_CRT2_ATTACHED_COLOR (2 << 8) | ||
| 174 | # define RADEON_DFP2_ATTACHED (1 << 11) | ||
| 175 | #define RADEON_BIOS_5_SCRATCH 0x0024 | ||
| 176 | # define RADEON_LCD1_ON (1 << 0) | ||
| 177 | # define RADEON_CRT1_ON (1 << 1) | ||
| 178 | # define RADEON_TV1_ON (1 << 2) | ||
| 179 | # define RADEON_DFP1_ON (1 << 3) | ||
| 180 | # define RADEON_CRT2_ON (1 << 5) | ||
| 181 | # define RADEON_CV1_ON (1 << 6) | ||
| 182 | # define RADEON_DFP2_ON (1 << 7) | ||
| 183 | # define RADEON_LCD1_CRTC_MASK (1 << 8) | ||
| 184 | # define RADEON_LCD1_CRTC_SHIFT 8 | ||
| 185 | # define RADEON_CRT1_CRTC_MASK (1 << 9) | ||
| 186 | # define RADEON_CRT1_CRTC_SHIFT 9 | ||
| 187 | # define RADEON_TV1_CRTC_MASK (1 << 10) | ||
| 188 | # define RADEON_TV1_CRTC_SHIFT 10 | ||
| 189 | # define RADEON_DFP1_CRTC_MASK (1 << 11) | ||
| 190 | # define RADEON_DFP1_CRTC_SHIFT 11 | ||
| 191 | # define RADEON_CRT2_CRTC_MASK (1 << 12) | ||
| 192 | # define RADEON_CRT2_CRTC_SHIFT 12 | ||
| 193 | # define RADEON_CV1_CRTC_MASK (1 << 13) | ||
| 194 | # define RADEON_CV1_CRTC_SHIFT 13 | ||
| 195 | # define RADEON_DFP2_CRTC_MASK (1 << 14) | ||
| 196 | # define RADEON_DFP2_CRTC_SHIFT 14 | ||
| 197 | # define RADEON_ACC_REQ_LCD1 (1 << 16) | ||
| 198 | # define RADEON_ACC_REQ_CRT1 (1 << 17) | ||
| 199 | # define RADEON_ACC_REQ_TV1 (1 << 18) | ||
| 200 | # define RADEON_ACC_REQ_DFP1 (1 << 19) | ||
| 201 | # define RADEON_ACC_REQ_CRT2 (1 << 21) | ||
| 202 | # define RADEON_ACC_REQ_TV2 (1 << 22) | ||
| 203 | # define RADEON_ACC_REQ_DFP2 (1 << 23) | ||
| 204 | #define RADEON_BIOS_6_SCRATCH 0x0028 | ||
| 205 | # define RADEON_ACC_MODE_CHANGE (1 << 2) | ||
| 206 | # define RADEON_EXT_DESKTOP_MODE (1 << 3) | ||
| 207 | # define RADEON_LCD_DPMS_ON (1 << 20) | ||
| 208 | # define RADEON_CRT_DPMS_ON (1 << 21) | ||
| 209 | # define RADEON_TV_DPMS_ON (1 << 22) | ||
| 210 | # define RADEON_DFP_DPMS_ON (1 << 23) | ||
| 211 | # define RADEON_DPMS_MASK (3 << 24) | ||
| 212 | # define RADEON_DPMS_ON (0 << 24) | ||
| 213 | # define RADEON_DPMS_STANDBY (1 << 24) | ||
| 214 | # define RADEON_DPMS_SUSPEND (2 << 24) | ||
| 215 | # define RADEON_DPMS_OFF (3 << 24) | ||
| 216 | # define RADEON_SCREEN_BLANKING (1 << 26) | ||
| 217 | # define RADEON_DRIVER_CRITICAL (1 << 27) | ||
| 218 | # define RADEON_DISPLAY_SWITCHING_DIS (1 << 30) | ||
| 219 | #define RADEON_BIOS_7_SCRATCH 0x002c | ||
| 220 | # define RADEON_SYS_HOTKEY (1 << 10) | ||
| 221 | # define RADEON_DRV_LOADED (1 << 12) | ||
| 222 | #define RADEON_BIOS_ROM 0x0f30 /* PCI */ | ||
| 223 | #define RADEON_BIST 0x0f0f /* PCI */ | ||
| 224 | #define RADEON_BRUSH_DATA0 0x1480 | ||
| 225 | #define RADEON_BRUSH_DATA1 0x1484 | ||
| 226 | #define RADEON_BRUSH_DATA10 0x14a8 | ||
| 227 | #define RADEON_BRUSH_DATA11 0x14ac | ||
| 228 | #define RADEON_BRUSH_DATA12 0x14b0 | ||
| 229 | #define RADEON_BRUSH_DATA13 0x14b4 | ||
| 230 | #define RADEON_BRUSH_DATA14 0x14b8 | ||
| 231 | #define RADEON_BRUSH_DATA15 0x14bc | ||
| 232 | #define RADEON_BRUSH_DATA16 0x14c0 | ||
| 233 | #define RADEON_BRUSH_DATA17 0x14c4 | ||
| 234 | #define RADEON_BRUSH_DATA18 0x14c8 | ||
| 235 | #define RADEON_BRUSH_DATA19 0x14cc | ||
| 236 | #define RADEON_BRUSH_DATA2 0x1488 | ||
| 237 | #define RADEON_BRUSH_DATA20 0x14d0 | ||
| 238 | #define RADEON_BRUSH_DATA21 0x14d4 | ||
| 239 | #define RADEON_BRUSH_DATA22 0x14d8 | ||
| 240 | #define RADEON_BRUSH_DATA23 0x14dc | ||
| 241 | #define RADEON_BRUSH_DATA24 0x14e0 | ||
| 242 | #define RADEON_BRUSH_DATA25 0x14e4 | ||
| 243 | #define RADEON_BRUSH_DATA26 0x14e8 | ||
| 244 | #define RADEON_BRUSH_DATA27 0x14ec | ||
| 245 | #define RADEON_BRUSH_DATA28 0x14f0 | ||
| 246 | #define RADEON_BRUSH_DATA29 0x14f4 | ||
| 247 | #define RADEON_BRUSH_DATA3 0x148c | ||
| 248 | #define RADEON_BRUSH_DATA30 0x14f8 | ||
| 249 | #define RADEON_BRUSH_DATA31 0x14fc | ||
| 250 | #define RADEON_BRUSH_DATA32 0x1500 | ||
| 251 | #define RADEON_BRUSH_DATA33 0x1504 | ||
| 252 | #define RADEON_BRUSH_DATA34 0x1508 | ||
| 253 | #define RADEON_BRUSH_DATA35 0x150c | ||
| 254 | #define RADEON_BRUSH_DATA36 0x1510 | ||
| 255 | #define RADEON_BRUSH_DATA37 0x1514 | ||
| 256 | #define RADEON_BRUSH_DATA38 0x1518 | ||
| 257 | #define RADEON_BRUSH_DATA39 0x151c | ||
| 258 | #define RADEON_BRUSH_DATA4 0x1490 | ||
| 259 | #define RADEON_BRUSH_DATA40 0x1520 | ||
| 260 | #define RADEON_BRUSH_DATA41 0x1524 | ||
| 261 | #define RADEON_BRUSH_DATA42 0x1528 | ||
| 262 | #define RADEON_BRUSH_DATA43 0x152c | ||
| 263 | #define RADEON_BRUSH_DATA44 0x1530 | ||
| 264 | #define RADEON_BRUSH_DATA45 0x1534 | ||
| 265 | #define RADEON_BRUSH_DATA46 0x1538 | ||
| 266 | #define RADEON_BRUSH_DATA47 0x153c | ||
| 267 | #define RADEON_BRUSH_DATA48 0x1540 | ||
| 268 | #define RADEON_BRUSH_DATA49 0x1544 | ||
| 269 | #define RADEON_BRUSH_DATA5 0x1494 | ||
| 270 | #define RADEON_BRUSH_DATA50 0x1548 | ||
| 271 | #define RADEON_BRUSH_DATA51 0x154c | ||
| 272 | #define RADEON_BRUSH_DATA52 0x1550 | ||
| 273 | #define RADEON_BRUSH_DATA53 0x1554 | ||
| 274 | #define RADEON_BRUSH_DATA54 0x1558 | ||
| 275 | #define RADEON_BRUSH_DATA55 0x155c | ||
| 276 | #define RADEON_BRUSH_DATA56 0x1560 | ||
| 277 | #define RADEON_BRUSH_DATA57 0x1564 | ||
| 278 | #define RADEON_BRUSH_DATA58 0x1568 | ||
| 279 | #define RADEON_BRUSH_DATA59 0x156c | ||
| 280 | #define RADEON_BRUSH_DATA6 0x1498 | ||
| 281 | #define RADEON_BRUSH_DATA60 0x1570 | ||
| 282 | #define RADEON_BRUSH_DATA61 0x1574 | ||
| 283 | #define RADEON_BRUSH_DATA62 0x1578 | ||
| 284 | #define RADEON_BRUSH_DATA63 0x157c | ||
| 285 | #define RADEON_BRUSH_DATA7 0x149c | ||
| 286 | #define RADEON_BRUSH_DATA8 0x14a0 | ||
| 287 | #define RADEON_BRUSH_DATA9 0x14a4 | ||
| 288 | #define RADEON_BRUSH_SCALE 0x1470 | ||
| 289 | #define RADEON_BRUSH_Y_X 0x1474 | ||
| 290 | #define RADEON_BUS_CNTL 0x0030 | ||
| 291 | # define RADEON_BUS_MASTER_DIS (1 << 6) | ||
| 292 | # define RADEON_BUS_BIOS_DIS_ROM (1 << 12) | ||
| 293 | # define RADEON_BUS_RD_DISCARD_EN (1 << 24) | ||
| 294 | # define RADEON_BUS_RD_ABORT_EN (1 << 25) | ||
| 295 | # define RADEON_BUS_MSTR_DISCONNECT_EN (1 << 28) | ||
| 296 | # define RADEON_BUS_WRT_BURST (1 << 29) | ||
| 297 | # define RADEON_BUS_READ_BURST (1 << 30) | ||
| 298 | #define RADEON_BUS_CNTL1 0x0034 | ||
| 299 | # define RADEON_BUS_WAIT_ON_LOCK_EN (1 << 4) | ||
| 300 | |||
| 301 | /* #define RADEON_PCIE_INDEX 0x0030 */ | ||
| 302 | /* #define RADEON_PCIE_DATA 0x0034 */ | ||
| 303 | #define RADEON_PCIE_LC_LINK_WIDTH_CNTL 0xa2 /* PCIE */ | ||
| 304 | # define RADEON_PCIE_LC_LINK_WIDTH_SHIFT 0 | ||
| 305 | # define RADEON_PCIE_LC_LINK_WIDTH_MASK 0x7 | ||
| 306 | # define RADEON_PCIE_LC_LINK_WIDTH_X0 0 | ||
| 307 | # define RADEON_PCIE_LC_LINK_WIDTH_X1 1 | ||
| 308 | # define RADEON_PCIE_LC_LINK_WIDTH_X2 2 | ||
| 309 | # define RADEON_PCIE_LC_LINK_WIDTH_X4 3 | ||
| 310 | # define RADEON_PCIE_LC_LINK_WIDTH_X8 4 | ||
| 311 | # define RADEON_PCIE_LC_LINK_WIDTH_X12 5 | ||
| 312 | # define RADEON_PCIE_LC_LINK_WIDTH_X16 6 | ||
| 313 | # define RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT 4 | ||
| 314 | # define RADEON_PCIE_LC_LINK_WIDTH_RD_MASK 0x70 | ||
| 315 | # define RADEON_PCIE_LC_RECONFIG_NOW (1 << 8) | ||
| 316 | # define RADEON_PCIE_LC_RECONFIG_LATER (1 << 9) | ||
| 317 | # define RADEON_PCIE_LC_SHORT_RECONFIG_EN (1 << 10) | ||
| 318 | |||
| 319 | #define RADEON_CACHE_CNTL 0x1724 | ||
| 320 | #define RADEON_CACHE_LINE 0x0f0c /* PCI */ | ||
| 321 | #define RADEON_CAPABILITIES_ID 0x0f50 /* PCI */ | ||
| 322 | #define RADEON_CAPABILITIES_PTR 0x0f34 /* PCI */ | ||
| 323 | #define RADEON_CLK_PIN_CNTL 0x0001 /* PLL */ | ||
| 324 | # define RADEON_DONT_USE_XTALIN (1 << 4) | ||
| 325 | # define RADEON_SCLK_DYN_START_CNTL (1 << 15) | ||
| 326 | #define RADEON_CLOCK_CNTL_DATA 0x000c | ||
| 327 | #define RADEON_CLOCK_CNTL_INDEX 0x0008 | ||
| 328 | # define RADEON_PLL_WR_EN (1 << 7) | ||
| 329 | # define RADEON_PLL_DIV_SEL (3 << 8) | ||
| 330 | # define RADEON_PLL2_DIV_SEL_MASK (~(3 << 8)) | ||
| 331 | #define RADEON_CLK_PWRMGT_CNTL 0x0014 | ||
| 332 | # define RADEON_ENGIN_DYNCLK_MODE (1 << 12) | ||
| 333 | # define RADEON_ACTIVE_HILO_LAT_MASK (3 << 13) | ||
| 334 | # define RADEON_ACTIVE_HILO_LAT_SHIFT 13 | ||
| 335 | # define RADEON_DISP_DYN_STOP_LAT_MASK (1 << 12) | ||
| 336 | # define RADEON_MC_BUSY (1 << 16) | ||
| 337 | # define RADEON_DLL_READY (1 << 19) | ||
| 338 | # define RADEON_CG_NO1_DEBUG_0 (1 << 24) | ||
| 339 | # define RADEON_CG_NO1_DEBUG_MASK (0x1f << 24) | ||
| 340 | # define RADEON_DYN_STOP_MODE_MASK (7 << 21) | ||
| 341 | # define RADEON_TVPLL_PWRMGT_OFF (1 << 30) | ||
| 342 | # define RADEON_TVCLK_TURNOFF (1 << 31) | ||
| 343 | #define RADEON_PLL_PWRMGT_CNTL 0x0015 /* PLL */ | ||
| 344 | # define RADEON_TCL_BYPASS_DISABLE (1 << 20) | ||
| 345 | #define RADEON_CLR_CMP_CLR_3D 0x1a24 | ||
| 346 | #define RADEON_CLR_CMP_CLR_DST 0x15c8 | ||
| 347 | #define RADEON_CLR_CMP_CLR_SRC 0x15c4 | ||
| 348 | #define RADEON_CLR_CMP_CNTL 0x15c0 | ||
| 349 | # define RADEON_SRC_CMP_EQ_COLOR (4 << 0) | ||
| 350 | # define RADEON_SRC_CMP_NEQ_COLOR (5 << 0) | ||
| 351 | # define RADEON_CLR_CMP_SRC_SOURCE (1 << 24) | ||
| 352 | #define RADEON_CLR_CMP_MASK 0x15cc | ||
| 353 | # define RADEON_CLR_CMP_MSK 0xffffffff | ||
| 354 | #define RADEON_CLR_CMP_MASK_3D 0x1A28 | ||
| 355 | #define RADEON_COMMAND 0x0f04 /* PCI */ | ||
| 356 | #define RADEON_COMPOSITE_SHADOW_ID 0x1a0c | ||
| 357 | #define RADEON_CONFIG_APER_0_BASE 0x0100 | ||
| 358 | #define RADEON_CONFIG_APER_1_BASE 0x0104 | ||
| 359 | #define RADEON_CONFIG_APER_SIZE 0x0108 | ||
| 360 | #define RADEON_CONFIG_BONDS 0x00e8 | ||
| 361 | #define RADEON_CONFIG_CNTL 0x00e0 | ||
| 362 | # define RADEON_CFG_ATI_REV_A11 (0 << 16) | ||
| 363 | # define RADEON_CFG_ATI_REV_A12 (1 << 16) | ||
| 364 | # define RADEON_CFG_ATI_REV_A13 (2 << 16) | ||
| 365 | # define RADEON_CFG_ATI_REV_ID_MASK (0xf << 16) | ||
| 366 | #define RADEON_CONFIG_MEMSIZE 0x00f8 | ||
| 367 | #define RADEON_CONFIG_MEMSIZE_EMBEDDED 0x0114 | ||
| 368 | #define RADEON_CONFIG_REG_1_BASE 0x010c | ||
| 369 | #define RADEON_CONFIG_REG_APER_SIZE 0x0110 | ||
| 370 | #define RADEON_CONFIG_XSTRAP 0x00e4 | ||
| 371 | #define RADEON_CONSTANT_COLOR_C 0x1d34 | ||
| 372 | # define RADEON_CONSTANT_COLOR_MASK 0x00ffffff | ||
| 373 | # define RADEON_CONSTANT_COLOR_ONE 0x00ffffff | ||
| 374 | # define RADEON_CONSTANT_COLOR_ZERO 0x00000000 | ||
| 375 | #define RADEON_CRC_CMDFIFO_ADDR 0x0740 | ||
| 376 | #define RADEON_CRC_CMDFIFO_DOUT 0x0744 | ||
| 377 | #define RADEON_GRPH_BUFFER_CNTL 0x02f0 | ||
| 378 | # define RADEON_GRPH_START_REQ_MASK (0x7f) | ||
| 379 | # define RADEON_GRPH_START_REQ_SHIFT 0 | ||
| 380 | # define RADEON_GRPH_STOP_REQ_MASK (0x7f<<8) | ||
| 381 | # define RADEON_GRPH_STOP_REQ_SHIFT 8 | ||
| 382 | # define RADEON_GRPH_CRITICAL_POINT_MASK (0x7f<<16) | ||
| 383 | # define RADEON_GRPH_CRITICAL_POINT_SHIFT 16 | ||
| 384 | # define RADEON_GRPH_CRITICAL_CNTL (1<<28) | ||
| 385 | # define RADEON_GRPH_BUFFER_SIZE (1<<29) | ||
| 386 | # define RADEON_GRPH_CRITICAL_AT_SOF (1<<30) | ||
| 387 | # define RADEON_GRPH_STOP_CNTL (1<<31) | ||
| 388 | #define RADEON_GRPH2_BUFFER_CNTL 0x03f0 | ||
| 389 | # define RADEON_GRPH2_START_REQ_MASK (0x7f) | ||
| 390 | # define RADEON_GRPH2_START_REQ_SHIFT 0 | ||
| 391 | # define RADEON_GRPH2_STOP_REQ_MASK (0x7f<<8) | ||
| 392 | # define RADEON_GRPH2_STOP_REQ_SHIFT 8 | ||
| 393 | # define RADEON_GRPH2_CRITICAL_POINT_MASK (0x7f<<16) | ||
| 394 | # define RADEON_GRPH2_CRITICAL_POINT_SHIFT 16 | ||
| 395 | # define RADEON_GRPH2_CRITICAL_CNTL (1<<28) | ||
| 396 | # define RADEON_GRPH2_BUFFER_SIZE (1<<29) | ||
| 397 | # define RADEON_GRPH2_CRITICAL_AT_SOF (1<<30) | ||
| 398 | # define RADEON_GRPH2_STOP_CNTL (1<<31) | ||
| 399 | #define RADEON_CRTC_CRNT_FRAME 0x0214 | ||
| 400 | #define RADEON_CRTC_EXT_CNTL 0x0054 | ||
| 401 | # define RADEON_CRTC_VGA_XOVERSCAN (1 << 0) | ||
| 402 | # define RADEON_VGA_ATI_LINEAR (1 << 3) | ||
| 403 | # define RADEON_XCRT_CNT_EN (1 << 6) | ||
| 404 | # define RADEON_CRTC_HSYNC_DIS (1 << 8) | ||
| 405 | # define RADEON_CRTC_VSYNC_DIS (1 << 9) | ||
| 406 | # define RADEON_CRTC_DISPLAY_DIS (1 << 10) | ||
| 407 | # define RADEON_CRTC_SYNC_TRISTAT (1 << 11) | ||
| 408 | # define RADEON_CRTC_CRT_ON (1 << 15) | ||
| 409 | #define RADEON_CRTC_EXT_CNTL_DPMS_BYTE 0x0055 | ||
| 410 | # define RADEON_CRTC_HSYNC_DIS_BYTE (1 << 0) | ||
| 411 | # define RADEON_CRTC_VSYNC_DIS_BYTE (1 << 1) | ||
| 412 | # define RADEON_CRTC_DISPLAY_DIS_BYTE (1 << 2) | ||
| 413 | #define RADEON_CRTC_GEN_CNTL 0x0050 | ||
| 414 | # define RADEON_CRTC_DBL_SCAN_EN (1 << 0) | ||
| 415 | # define RADEON_CRTC_INTERLACE_EN (1 << 1) | ||
| 416 | # define RADEON_CRTC_CSYNC_EN (1 << 4) | ||
| 417 | # define RADEON_CRTC_ICON_EN (1 << 15) | ||
| 418 | # define RADEON_CRTC_CUR_EN (1 << 16) | ||
| 419 | # define RADEON_CRTC_CUR_MODE_MASK (7 << 20) | ||
| 420 | # define RADEON_CRTC_CUR_MODE_SHIFT 20 | ||
| 421 | # define RADEON_CRTC_CUR_MODE_MONO 0 | ||
| 422 | # define RADEON_CRTC_CUR_MODE_24BPP 2 | ||
| 423 | # define RADEON_CRTC_EXT_DISP_EN (1 << 24) | ||
| 424 | # define RADEON_CRTC_EN (1 << 25) | ||
| 425 | # define RADEON_CRTC_DISP_REQ_EN_B (1 << 26) | ||
| 426 | #define RADEON_CRTC2_GEN_CNTL 0x03f8 | ||
| 427 | # define RADEON_CRTC2_DBL_SCAN_EN (1 << 0) | ||
| 428 | # define RADEON_CRTC2_INTERLACE_EN (1 << 1) | ||
| 429 | # define RADEON_CRTC2_SYNC_TRISTAT (1 << 4) | ||
| 430 | # define RADEON_CRTC2_HSYNC_TRISTAT (1 << 5) | ||
| 431 | # define RADEON_CRTC2_VSYNC_TRISTAT (1 << 6) | ||
| 432 | # define RADEON_CRTC2_CRT2_ON (1 << 7) | ||
| 433 | # define RADEON_CRTC2_PIX_WIDTH_SHIFT 8 | ||
| 434 | # define RADEON_CRTC2_PIX_WIDTH_MASK (0xf << 8) | ||
| 435 | # define RADEON_CRTC2_ICON_EN (1 << 15) | ||
| 436 | # define RADEON_CRTC2_CUR_EN (1 << 16) | ||
| 437 | # define RADEON_CRTC2_CUR_MODE_MASK (7 << 20) | ||
| 438 | # define RADEON_CRTC2_DISP_DIS (1 << 23) | ||
| 439 | # define RADEON_CRTC2_EN (1 << 25) | ||
| 440 | # define RADEON_CRTC2_DISP_REQ_EN_B (1 << 26) | ||
| 441 | # define RADEON_CRTC2_CSYNC_EN (1 << 27) | ||
| 442 | # define RADEON_CRTC2_HSYNC_DIS (1 << 28) | ||
| 443 | # define RADEON_CRTC2_VSYNC_DIS (1 << 29) | ||
| 444 | #define RADEON_CRTC_MORE_CNTL 0x27c | ||
| 445 | # define RADEON_CRTC_AUTO_HORZ_CENTER_EN (1<<2) | ||
| 446 | # define RADEON_CRTC_AUTO_VERT_CENTER_EN (1<<3) | ||
| 447 | # define RADEON_CRTC_H_CUTOFF_ACTIVE_EN (1<<4) | ||
| 448 | # define RADEON_CRTC_V_CUTOFF_ACTIVE_EN (1<<5) | ||
| 449 | #define RADEON_CRTC_GUI_TRIG_VLINE 0x0218 | ||
| 450 | #define RADEON_CRTC_H_SYNC_STRT_WID 0x0204 | ||
| 451 | # define RADEON_CRTC_H_SYNC_STRT_PIX (0x07 << 0) | ||
| 452 | # define RADEON_CRTC_H_SYNC_STRT_CHAR (0x3ff << 3) | ||
| 453 | # define RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT 3 | ||
| 454 | # define RADEON_CRTC_H_SYNC_WID (0x3f << 16) | ||
| 455 | # define RADEON_CRTC_H_SYNC_WID_SHIFT 16 | ||
| 456 | # define RADEON_CRTC_H_SYNC_POL (1 << 23) | ||
| 457 | #define RADEON_CRTC2_H_SYNC_STRT_WID 0x0304 | ||
| 458 | # define RADEON_CRTC2_H_SYNC_STRT_PIX (0x07 << 0) | ||
| 459 | # define RADEON_CRTC2_H_SYNC_STRT_CHAR (0x3ff << 3) | ||
| 460 | # define RADEON_CRTC2_H_SYNC_STRT_CHAR_SHIFT 3 | ||
| 461 | # define RADEON_CRTC2_H_SYNC_WID (0x3f << 16) | ||
| 462 | # define RADEON_CRTC2_H_SYNC_WID_SHIFT 16 | ||
| 463 | # define RADEON_CRTC2_H_SYNC_POL (1 << 23) | ||
| 464 | #define RADEON_CRTC_H_TOTAL_DISP 0x0200 | ||
| 465 | # define RADEON_CRTC_H_TOTAL (0x03ff << 0) | ||
| 466 | # define RADEON_CRTC_H_TOTAL_SHIFT 0 | ||
| 467 | # define RADEON_CRTC_H_DISP (0x01ff << 16) | ||
| 468 | # define RADEON_CRTC_H_DISP_SHIFT 16 | ||
| 469 | #define RADEON_CRTC2_H_TOTAL_DISP 0x0300 | ||
| 470 | # define RADEON_CRTC2_H_TOTAL (0x03ff << 0) | ||
| 471 | # define RADEON_CRTC2_H_TOTAL_SHIFT 0 | ||
| 472 | # define RADEON_CRTC2_H_DISP (0x01ff << 16) | ||
| 473 | # define RADEON_CRTC2_H_DISP_SHIFT 16 | ||
| 474 | |||
| 475 | #define RADEON_CRTC_OFFSET_RIGHT 0x0220 | ||
| 476 | #define RADEON_CRTC_OFFSET 0x0224 | ||
| 477 | # define RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET (1<<30) | ||
| 478 | # define RADEON_CRTC_OFFSET__OFFSET_LOCK (1<<31) | ||
| 479 | |||
| 480 | #define RADEON_CRTC2_OFFSET 0x0324 | ||
| 481 | # define RADEON_CRTC2_OFFSET__GUI_TRIG_OFFSET (1<<30) | ||
| 482 | # define RADEON_CRTC2_OFFSET__OFFSET_LOCK (1<<31) | ||
| 483 | #define RADEON_CRTC_OFFSET_CNTL 0x0228 | ||
| 484 | # define RADEON_CRTC_TILE_LINE_SHIFT 0 | ||
| 485 | # define RADEON_CRTC_TILE_LINE_RIGHT_SHIFT 4 | ||
| 486 | # define R300_CRTC_X_Y_MODE_EN_RIGHT (1 << 6) | ||
| 487 | # define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_MASK (3 << 7) | ||
| 488 | # define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_AUTO (0 << 7) | ||
| 489 | # define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_SINGLE (1 << 7) | ||
| 490 | # define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_DOUBLE (2 << 7) | ||
| 491 | # define R300_CRTC_MICRO_TILE_BUFFER_RIGHT_DIS (3 << 7) | ||
| 492 | # define R300_CRTC_X_Y_MODE_EN (1 << 9) | ||
| 493 | # define R300_CRTC_MICRO_TILE_BUFFER_MASK (3 << 10) | ||
| 494 | # define R300_CRTC_MICRO_TILE_BUFFER_AUTO (0 << 10) | ||
| 495 | # define R300_CRTC_MICRO_TILE_BUFFER_SINGLE (1 << 10) | ||
| 496 | # define R300_CRTC_MICRO_TILE_BUFFER_DOUBLE (2 << 10) | ||
| 497 | # define R300_CRTC_MICRO_TILE_BUFFER_DIS (3 << 10) | ||
| 498 | # define R300_CRTC_MICRO_TILE_EN_RIGHT (1 << 12) | ||
| 499 | # define R300_CRTC_MICRO_TILE_EN (1 << 13) | ||
| 500 | # define R300_CRTC_MACRO_TILE_EN_RIGHT (1 << 14) | ||
| 501 | # define R300_CRTC_MACRO_TILE_EN (1 << 15) | ||
| 502 | # define RADEON_CRTC_TILE_EN_RIGHT (1 << 14) | ||
| 503 | # define RADEON_CRTC_TILE_EN (1 << 15) | ||
| 504 | # define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) | ||
| 505 | # define RADEON_CRTC_STEREO_OFFSET_EN (1 << 17) | ||
| 506 | |||
| 507 | #define R300_CRTC_TILE_X0_Y0 0x0350 | ||
| 508 | #define R300_CRTC2_TILE_X0_Y0 0x0358 | ||
| 509 | |||
| 510 | #define RADEON_CRTC2_OFFSET_CNTL 0x0328 | ||
| 511 | # define RADEON_CRTC2_OFFSET_FLIP_CNTL (1 << 16) | ||
| 512 | # define RADEON_CRTC2_TILE_EN (1 << 15) | ||
| 513 | #define RADEON_CRTC_PITCH 0x022c | ||
| 514 | # define RADEON_CRTC_PITCH__SHIFT 0 | ||
| 515 | # define RADEON_CRTC_PITCH__RIGHT_SHIFT 16 | ||
| 516 | |||
| 517 | #define RADEON_CRTC2_PITCH 0x032c | ||
| 518 | #define RADEON_CRTC_STATUS 0x005c | ||
| 519 | # define RADEON_CRTC_VBLANK_SAVE (1 << 1) | ||
| 520 | # define RADEON_CRTC_VBLANK_SAVE_CLEAR (1 << 1) | ||
| 521 | #define RADEON_CRTC2_STATUS 0x03fc | ||
| 522 | # define RADEON_CRTC2_VBLANK_SAVE (1 << 1) | ||
| 523 | # define RADEON_CRTC2_VBLANK_SAVE_CLEAR (1 << 1) | ||
| 524 | #define RADEON_CRTC_V_SYNC_STRT_WID 0x020c | ||
| 525 | # define RADEON_CRTC_V_SYNC_STRT (0x7ff << 0) | ||
| 526 | # define RADEON_CRTC_V_SYNC_STRT_SHIFT 0 | ||
| 527 | # define RADEON_CRTC_V_SYNC_WID (0x1f << 16) | ||
| 528 | # define RADEON_CRTC_V_SYNC_WID_SHIFT 16 | ||
| 529 | # define RADEON_CRTC_V_SYNC_POL (1 << 23) | ||
| 530 | #define RADEON_CRTC2_V_SYNC_STRT_WID 0x030c | ||
| 531 | # define RADEON_CRTC2_V_SYNC_STRT (0x7ff << 0) | ||
| 532 | # define RADEON_CRTC2_V_SYNC_STRT_SHIFT 0 | ||
| 533 | # define RADEON_CRTC2_V_SYNC_WID (0x1f << 16) | ||
| 534 | # define RADEON_CRTC2_V_SYNC_WID_SHIFT 16 | ||
| 535 | # define RADEON_CRTC2_V_SYNC_POL (1 << 23) | ||
| 536 | #define RADEON_CRTC_V_TOTAL_DISP 0x0208 | ||
| 537 | # define RADEON_CRTC_V_TOTAL (0x07ff << 0) | ||
| 538 | # define RADEON_CRTC_V_TOTAL_SHIFT 0 | ||
| 539 | # define RADEON_CRTC_V_DISP (0x07ff << 16) | ||
| 540 | # define RADEON_CRTC_V_DISP_SHIFT 16 | ||
| 541 | #define RADEON_CRTC2_V_TOTAL_DISP 0x0308 | ||
| 542 | # define RADEON_CRTC2_V_TOTAL (0x07ff << 0) | ||
| 543 | # define RADEON_CRTC2_V_TOTAL_SHIFT 0 | ||
| 544 | # define RADEON_CRTC2_V_DISP (0x07ff << 16) | ||
| 545 | # define RADEON_CRTC2_V_DISP_SHIFT 16 | ||
| 546 | #define RADEON_CRTC_VLINE_CRNT_VLINE 0x0210 | ||
| 547 | # define RADEON_CRTC_CRNT_VLINE_MASK (0x7ff << 16) | ||
| 548 | #define RADEON_CRTC2_CRNT_FRAME 0x0314 | ||
| 549 | #define RADEON_CRTC2_GUI_TRIG_VLINE 0x0318 | ||
| 550 | #define RADEON_CRTC2_STATUS 0x03fc | ||
| 551 | #define RADEON_CRTC2_VLINE_CRNT_VLINE 0x0310 | ||
| 552 | #define RADEON_CRTC8_DATA 0x03d5 /* VGA, 0x3b5 */ | ||
| 553 | #define RADEON_CRTC8_IDX 0x03d4 /* VGA, 0x3b4 */ | ||
| 554 | #define RADEON_CUR_CLR0 0x026c | ||
| 555 | #define RADEON_CUR_CLR1 0x0270 | ||
| 556 | #define RADEON_CUR_HORZ_VERT_OFF 0x0268 | ||
| 557 | #define RADEON_CUR_HORZ_VERT_POSN 0x0264 | ||
| 558 | #define RADEON_CUR_OFFSET 0x0260 | ||
| 559 | # define RADEON_CUR_LOCK (1 << 31) | ||
| 560 | #define RADEON_CUR2_CLR0 0x036c | ||
| 561 | #define RADEON_CUR2_CLR1 0x0370 | ||
| 562 | #define RADEON_CUR2_HORZ_VERT_OFF 0x0368 | ||
| 563 | #define RADEON_CUR2_HORZ_VERT_POSN 0x0364 | ||
| 564 | #define RADEON_CUR2_OFFSET 0x0360 | ||
| 565 | # define RADEON_CUR2_LOCK (1 << 31) | ||
| 566 | |||
| 567 | #define RADEON_DAC_CNTL 0x0058 | ||
| 568 | # define RADEON_DAC_RANGE_CNTL (3 << 0) | ||
| 569 | # define RADEON_DAC_RANGE_CNTL_PS2 (2 << 0) | ||
| 570 | # define RADEON_DAC_RANGE_CNTL_MASK 0x03 | ||
| 571 | # define RADEON_DAC_BLANKING (1 << 2) | ||
| 572 | # define RADEON_DAC_CMP_EN (1 << 3) | ||
| 573 | # define RADEON_DAC_CMP_OUTPUT (1 << 7) | ||
| 574 | # define RADEON_DAC_8BIT_EN (1 << 8) | ||
| 575 | # define RADEON_DAC_TVO_EN (1 << 10) | ||
| 576 | # define RADEON_DAC_VGA_ADR_EN (1 << 13) | ||
| 577 | # define RADEON_DAC_PDWN (1 << 15) | ||
| 578 | # define RADEON_DAC_MASK_ALL (0xff << 24) | ||
| 579 | #define RADEON_DAC_CNTL2 0x007c | ||
| 580 | # define RADEON_DAC2_TV_CLK_SEL (0 << 1) | ||
| 581 | # define RADEON_DAC2_DAC_CLK_SEL (1 << 0) | ||
| 582 | # define RADEON_DAC2_DAC2_CLK_SEL (1 << 1) | ||
| 583 | # define RADEON_DAC2_PALETTE_ACC_CTL (1 << 5) | ||
| 584 | # define RADEON_DAC2_CMP_EN (1 << 7) | ||
| 585 | # define RADEON_DAC2_CMP_OUT_R (1 << 8) | ||
| 586 | # define RADEON_DAC2_CMP_OUT_G (1 << 9) | ||
| 587 | # define RADEON_DAC2_CMP_OUT_B (1 << 10) | ||
| 588 | # define RADEON_DAC2_CMP_OUTPUT (1 << 11) | ||
| 589 | #define RADEON_DAC_EXT_CNTL 0x0280 | ||
| 590 | # define RADEON_DAC2_FORCE_BLANK_OFF_EN (1 << 0) | ||
| 591 | # define RADEON_DAC2_FORCE_DATA_EN (1 << 1) | ||
| 592 | # define RADEON_DAC_FORCE_BLANK_OFF_EN (1 << 4) | ||
| 593 | # define RADEON_DAC_FORCE_DATA_EN (1 << 5) | ||
| 594 | # define RADEON_DAC_FORCE_DATA_SEL_MASK (3 << 6) | ||
| 595 | # define RADEON_DAC_FORCE_DATA_SEL_R (0 << 6) | ||
| 596 | # define RADEON_DAC_FORCE_DATA_SEL_G (1 << 6) | ||
| 597 | # define RADEON_DAC_FORCE_DATA_SEL_B (2 << 6) | ||
| 598 | # define RADEON_DAC_FORCE_DATA_SEL_RGB (3 << 6) | ||
| 599 | # define RADEON_DAC_FORCE_DATA_MASK 0x0003ff00 | ||
| 600 | # define RADEON_DAC_FORCE_DATA_SHIFT 8 | ||
| 601 | #define RADEON_DAC_MACRO_CNTL 0x0d04 | ||
| 602 | # define RADEON_DAC_PDWN_R (1 << 16) | ||
| 603 | # define RADEON_DAC_PDWN_G (1 << 17) | ||
| 604 | # define RADEON_DAC_PDWN_B (1 << 18) | ||
| 605 | #define RADEON_DISP_PWR_MAN 0x0d08 | ||
| 606 | # define RADEON_DISP_PWR_MAN_D3_CRTC_EN (1 << 0) | ||
| 607 | # define RADEON_DISP_PWR_MAN_D3_CRTC2_EN (1 << 4) | ||
| 608 | # define RADEON_DISP_PWR_MAN_DPMS_ON (0 << 8) | ||
| 609 | # define RADEON_DISP_PWR_MAN_DPMS_STANDBY (1 << 8) | ||
| 610 | # define RADEON_DISP_PWR_MAN_DPMS_SUSPEND (2 << 8) | ||
| 611 | # define RADEON_DISP_PWR_MAN_DPMS_OFF (3 << 8) | ||
| 612 | # define RADEON_DISP_D3_RST (1 << 16) | ||
| 613 | # define RADEON_DISP_D3_REG_RST (1 << 17) | ||
| 614 | # define RADEON_DISP_D3_GRPH_RST (1 << 18) | ||
| 615 | # define RADEON_DISP_D3_SUBPIC_RST (1 << 19) | ||
| 616 | # define RADEON_DISP_D3_OV0_RST (1 << 20) | ||
| 617 | # define RADEON_DISP_D1D2_GRPH_RST (1 << 21) | ||
| 618 | # define RADEON_DISP_D1D2_SUBPIC_RST (1 << 22) | ||
| 619 | # define RADEON_DISP_D1D2_OV0_RST (1 << 23) | ||
| 620 | # define RADEON_DIG_TMDS_ENABLE_RST (1 << 24) | ||
| 621 | # define RADEON_TV_ENABLE_RST (1 << 25) | ||
| 622 | # define RADEON_AUTO_PWRUP_EN (1 << 26) | ||
| 623 | #define RADEON_TV_DAC_CNTL 0x088c | ||
| 624 | # define RADEON_TV_DAC_NBLANK (1 << 0) | ||
| 625 | # define RADEON_TV_DAC_NHOLD (1 << 1) | ||
| 626 | # define RADEON_TV_DAC_PEDESTAL (1 << 2) | ||
| 627 | # define RADEON_TV_MONITOR_DETECT_EN (1 << 4) | ||
| 628 | # define RADEON_TV_DAC_CMPOUT (1 << 5) | ||
| 629 | # define RADEON_TV_DAC_STD_MASK (3 << 8) | ||
| 630 | # define RADEON_TV_DAC_STD_PAL (0 << 8) | ||
| 631 | # define RADEON_TV_DAC_STD_NTSC (1 << 8) | ||
| 632 | # define RADEON_TV_DAC_STD_PS2 (2 << 8) | ||
| 633 | # define RADEON_TV_DAC_STD_RS343 (3 << 8) | ||
| 634 | # define RADEON_TV_DAC_BGSLEEP (1 << 6) | ||
| 635 | # define RADEON_TV_DAC_BGADJ_MASK (0xf << 16) | ||
| 636 | # define RADEON_TV_DAC_BGADJ_SHIFT 16 | ||
| 637 | # define RADEON_TV_DAC_DACADJ_MASK (0xf << 20) | ||
| 638 | # define RADEON_TV_DAC_DACADJ_SHIFT 20 | ||
| 639 | # define RADEON_TV_DAC_RDACPD (1 << 24) | ||
| 640 | # define RADEON_TV_DAC_GDACPD (1 << 25) | ||
| 641 | # define RADEON_TV_DAC_BDACPD (1 << 26) | ||
| 642 | # define RADEON_TV_DAC_RDACDET (1 << 29) | ||
| 643 | # define RADEON_TV_DAC_GDACDET (1 << 30) | ||
| 644 | # define RADEON_TV_DAC_BDACDET (1 << 31) | ||
| 645 | # define R420_TV_DAC_DACADJ_MASK (0x1f << 20) | ||
| 646 | # define R420_TV_DAC_RDACPD (1 << 25) | ||
| 647 | # define R420_TV_DAC_GDACPD (1 << 26) | ||
| 648 | # define R420_TV_DAC_BDACPD (1 << 27) | ||
| 649 | # define R420_TV_DAC_TVENABLE (1 << 28) | ||
| 650 | #define RADEON_DISP_HW_DEBUG 0x0d14 | ||
| 651 | # define RADEON_CRT2_DISP1_SEL (1 << 5) | ||
| 652 | #define RADEON_DISP_OUTPUT_CNTL 0x0d64 | ||
| 653 | # define RADEON_DISP_DAC_SOURCE_MASK 0x03 | ||
| 654 | # define RADEON_DISP_DAC2_SOURCE_MASK 0x0c | ||
| 655 | # define RADEON_DISP_DAC_SOURCE_CRTC2 0x01 | ||
| 656 | # define RADEON_DISP_DAC_SOURCE_RMX 0x02 | ||
| 657 | # define RADEON_DISP_DAC_SOURCE_LTU 0x03 | ||
| 658 | # define RADEON_DISP_DAC2_SOURCE_CRTC2 0x04 | ||
| 659 | # define RADEON_DISP_TVDAC_SOURCE_MASK (0x03 << 2) | ||
| 660 | # define RADEON_DISP_TVDAC_SOURCE_CRTC 0x0 | ||
| 661 | # define RADEON_DISP_TVDAC_SOURCE_CRTC2 (0x01 << 2) | ||
| 662 | # define RADEON_DISP_TVDAC_SOURCE_RMX (0x02 << 2) | ||
| 663 | # define RADEON_DISP_TVDAC_SOURCE_LTU (0x03 << 2) | ||
| 664 | # define RADEON_DISP_TRANS_MATRIX_MASK (0x03 << 4) | ||
| 665 | # define RADEON_DISP_TRANS_MATRIX_ALPHA_MSB (0x00 << 4) | ||
| 666 | # define RADEON_DISP_TRANS_MATRIX_GRAPHICS (0x01 << 4) | ||
| 667 | # define RADEON_DISP_TRANS_MATRIX_VIDEO (0x02 << 4) | ||
| 668 | # define RADEON_DISP_TV_SOURCE_CRTC (1 << 16) /* crtc1 or crtc2 */ | ||
| 669 | # define RADEON_DISP_TV_SOURCE_LTU (0 << 16) /* linear transform unit */ | ||
| 670 | #define RADEON_DISP_TV_OUT_CNTL 0x0d6c | ||
| 671 | # define RADEON_DISP_TV_PATH_SRC_CRTC2 (1 << 16) | ||
| 672 | # define RADEON_DISP_TV_PATH_SRC_CRTC1 (0 << 16) | ||
| 673 | #define RADEON_DAC_CRC_SIG 0x02cc | ||
| 674 | #define RADEON_DAC_DATA 0x03c9 /* VGA */ | ||
| 675 | #define RADEON_DAC_MASK 0x03c6 /* VGA */ | ||
| 676 | #define RADEON_DAC_R_INDEX 0x03c7 /* VGA */ | ||
| 677 | #define RADEON_DAC_W_INDEX 0x03c8 /* VGA */ | ||
| 678 | #define RADEON_DDA_CONFIG 0x02e0 | ||
| 679 | #define RADEON_DDA_ON_OFF 0x02e4 | ||
| 680 | #define RADEON_DEFAULT_OFFSET 0x16e0 | ||
| 681 | #define RADEON_DEFAULT_PITCH 0x16e4 | ||
| 682 | #define RADEON_DEFAULT_SC_BOTTOM_RIGHT 0x16e8 | ||
| 683 | # define RADEON_DEFAULT_SC_RIGHT_MAX (0x1fff << 0) | ||
| 684 | # define RADEON_DEFAULT_SC_BOTTOM_MAX (0x1fff << 16) | ||
| 685 | #define RADEON_DESTINATION_3D_CLR_CMP_VAL 0x1820 | ||
| 686 | #define RADEON_DESTINATION_3D_CLR_CMP_MSK 0x1824 | ||
| 687 | #define RADEON_DEVICE_ID 0x0f02 /* PCI */ | ||
| 688 | #define RADEON_DISP_MISC_CNTL 0x0d00 | ||
| 689 | # define RADEON_SOFT_RESET_GRPH_PP (1 << 0) | ||
| 690 | #define RADEON_DISP_MERGE_CNTL 0x0d60 | ||
| 691 | # define RADEON_DISP_ALPHA_MODE_MASK 0x03 | ||
| 692 | # define RADEON_DISP_ALPHA_MODE_KEY 0 | ||
| 693 | # define RADEON_DISP_ALPHA_MODE_PER_PIXEL 1 | ||
| 694 | # define RADEON_DISP_ALPHA_MODE_GLOBAL 2 | ||
| 695 | # define RADEON_DISP_RGB_OFFSET_EN (1 << 8) | ||
| 696 | # define RADEON_DISP_GRPH_ALPHA_MASK (0xff << 16) | ||
| 697 | # define RADEON_DISP_OV0_ALPHA_MASK (0xff << 24) | ||
| 698 | # define RADEON_DISP_LIN_TRANS_BYPASS (0x01 << 9) | ||
| 699 | #define RADEON_DISP2_MERGE_CNTL 0x0d68 | ||
| 700 | # define RADEON_DISP2_RGB_OFFSET_EN (1 << 8) | ||
| 701 | #define RADEON_DISP_LIN_TRANS_GRPH_A 0x0d80 | ||
| 702 | #define RADEON_DISP_LIN_TRANS_GRPH_B 0x0d84 | ||
| 703 | #define RADEON_DISP_LIN_TRANS_GRPH_C 0x0d88 | ||
| 704 | #define RADEON_DISP_LIN_TRANS_GRPH_D 0x0d8c | ||
| 705 | #define RADEON_DISP_LIN_TRANS_GRPH_E 0x0d90 | ||
| 706 | #define RADEON_DISP_LIN_TRANS_GRPH_F 0x0d98 | ||
| 707 | #define RADEON_DP_BRUSH_BKGD_CLR 0x1478 | ||
| 708 | #define RADEON_DP_BRUSH_FRGD_CLR 0x147c | ||
| 709 | #define RADEON_DP_CNTL 0x16c0 | ||
| 710 | # define RADEON_DST_X_LEFT_TO_RIGHT (1 << 0) | ||
| 711 | # define RADEON_DST_Y_TOP_TO_BOTTOM (1 << 1) | ||
| 712 | # define RADEON_DP_DST_TILE_LINEAR (0 << 3) | ||
| 713 | # define RADEON_DP_DST_TILE_MACRO (1 << 3) | ||
| 714 | # define RADEON_DP_DST_TILE_MICRO (2 << 3) | ||
| 715 | # define RADEON_DP_DST_TILE_BOTH (3 << 3) | ||
| 716 | #define RADEON_DP_CNTL_XDIR_YDIR_YMAJOR 0x16d0 | ||
| 717 | # define RADEON_DST_Y_MAJOR (1 << 2) | ||
| 718 | # define RADEON_DST_Y_DIR_TOP_TO_BOTTOM (1 << 15) | ||
| 719 | # define RADEON_DST_X_DIR_LEFT_TO_RIGHT (1 << 31) | ||
| 720 | #define RADEON_DP_DATATYPE 0x16c4 | ||
| 721 | # define RADEON_HOST_BIG_ENDIAN_EN (1 << 29) | ||
| 722 | #define RADEON_DP_GUI_MASTER_CNTL 0x146c | ||
| 723 | # define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) | ||
| 724 | # define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) | ||
| 725 | # define RADEON_GMC_SRC_CLIPPING (1 << 2) | ||
| 726 | # define RADEON_GMC_DST_CLIPPING (1 << 3) | ||
| 727 | # define RADEON_GMC_BRUSH_DATATYPE_MASK (0x0f << 4) | ||
| 728 | # define RADEON_GMC_BRUSH_8X8_MONO_FG_BG (0 << 4) | ||
| 729 | # define RADEON_GMC_BRUSH_8X8_MONO_FG_LA (1 << 4) | ||
| 730 | # define RADEON_GMC_BRUSH_1X8_MONO_FG_BG (4 << 4) | ||
| 731 | # define RADEON_GMC_BRUSH_1X8_MONO_FG_LA (5 << 4) | ||
| 732 | # define RADEON_GMC_BRUSH_32x1_MONO_FG_BG (6 << 4) | ||
| 733 | # define RADEON_GMC_BRUSH_32x1_MONO_FG_LA (7 << 4) | ||
| 734 | # define RADEON_GMC_BRUSH_32x32_MONO_FG_BG (8 << 4) | ||
| 735 | # define RADEON_GMC_BRUSH_32x32_MONO_FG_LA (9 << 4) | ||
| 736 | # define RADEON_GMC_BRUSH_8x8_COLOR (10 << 4) | ||
| 737 | # define RADEON_GMC_BRUSH_1X8_COLOR (12 << 4) | ||
| 738 | # define RADEON_GMC_BRUSH_SOLID_COLOR (13 << 4) | ||
| 739 | # define RADEON_GMC_BRUSH_NONE (15 << 4) | ||
| 740 | # define RADEON_GMC_DST_8BPP_CI (2 << 8) | ||
| 741 | # define RADEON_GMC_DST_15BPP (3 << 8) | ||
| 742 | # define RADEON_GMC_DST_16BPP (4 << 8) | ||
| 743 | # define RADEON_GMC_DST_24BPP (5 << 8) | ||
| 744 | # define RADEON_GMC_DST_32BPP (6 << 8) | ||
| 745 | # define RADEON_GMC_DST_8BPP_RGB (7 << 8) | ||
| 746 | # define RADEON_GMC_DST_Y8 (8 << 8) | ||
| 747 | # define RADEON_GMC_DST_RGB8 (9 << 8) | ||
| 748 | # define RADEON_GMC_DST_VYUY (11 << 8) | ||
| 749 | # define RADEON_GMC_DST_YVYU (12 << 8) | ||
| 750 | # define RADEON_GMC_DST_AYUV444 (14 << 8) | ||
| 751 | # define RADEON_GMC_DST_ARGB4444 (15 << 8) | ||
| 752 | # define RADEON_GMC_DST_DATATYPE_MASK (0x0f << 8) | ||
| 753 | # define RADEON_GMC_DST_DATATYPE_SHIFT 8 | ||
| 754 | # define RADEON_GMC_SRC_DATATYPE_MASK (3 << 12) | ||
| 755 | # define RADEON_GMC_SRC_DATATYPE_MONO_FG_BG (0 << 12) | ||
| 756 | # define RADEON_GMC_SRC_DATATYPE_MONO_FG_LA (1 << 12) | ||
| 757 | # define RADEON_GMC_SRC_DATATYPE_COLOR (3 << 12) | ||
| 758 | # define RADEON_GMC_BYTE_PIX_ORDER (1 << 14) | ||
| 759 | # define RADEON_GMC_BYTE_MSB_TO_LSB (0 << 14) | ||
| 760 | # define RADEON_GMC_BYTE_LSB_TO_MSB (1 << 14) | ||
| 761 | # define RADEON_GMC_CONVERSION_TEMP (1 << 15) | ||
| 762 | # define RADEON_GMC_CONVERSION_TEMP_6500 (0 << 15) | ||
| 763 | # define RADEON_GMC_CONVERSION_TEMP_9300 (1 << 15) | ||
| 764 | # define RADEON_GMC_ROP3_MASK (0xff << 16) | ||
| 765 | # define RADEON_DP_SRC_SOURCE_MASK (7 << 24) | ||
| 766 | # define RADEON_DP_SRC_SOURCE_MEMORY (2 << 24) | ||
| 767 | # define RADEON_DP_SRC_SOURCE_HOST_DATA (3 << 24) | ||
| 768 | # define RADEON_GMC_3D_FCN_EN (1 << 27) | ||
| 769 | # define RADEON_GMC_CLR_CMP_CNTL_DIS (1 << 28) | ||
| 770 | # define RADEON_GMC_AUX_CLIP_DIS (1 << 29) | ||
| 771 | # define RADEON_GMC_WR_MSK_DIS (1 << 30) | ||
| 772 | # define RADEON_GMC_LD_BRUSH_Y_X (1 << 31) | ||
| 773 | # define RADEON_ROP3_ZERO 0x00000000 | ||
| 774 | # define RADEON_ROP3_DSa 0x00880000 | ||
| 775 | # define RADEON_ROP3_SDna 0x00440000 | ||
| 776 | # define RADEON_ROP3_S 0x00cc0000 | ||
| 777 | # define RADEON_ROP3_DSna 0x00220000 | ||
| 778 | # define RADEON_ROP3_D 0x00aa0000 | ||
| 779 | # define RADEON_ROP3_DSx 0x00660000 | ||
| 780 | # define RADEON_ROP3_DSo 0x00ee0000 | ||
| 781 | # define RADEON_ROP3_DSon 0x00110000 | ||
| 782 | # define RADEON_ROP3_DSxn 0x00990000 | ||
| 783 | # define RADEON_ROP3_Dn 0x00550000 | ||
| 784 | # define RADEON_ROP3_SDno 0x00dd0000 | ||
| 785 | # define RADEON_ROP3_Sn 0x00330000 | ||
| 786 | # define RADEON_ROP3_DSno 0x00bb0000 | ||
| 787 | # define RADEON_ROP3_DSan 0x00770000 | ||
| 788 | # define RADEON_ROP3_ONE 0x00ff0000 | ||
| 789 | # define RADEON_ROP3_DPa 0x00a00000 | ||
| 790 | # define RADEON_ROP3_PDna 0x00500000 | ||
| 791 | # define RADEON_ROP3_P 0x00f00000 | ||
| 792 | # define RADEON_ROP3_DPna 0x000a0000 | ||
| 793 | # define RADEON_ROP3_D 0x00aa0000 | ||
| 794 | # define RADEON_ROP3_DPx 0x005a0000 | ||
| 795 | # define RADEON_ROP3_DPo 0x00fa0000 | ||
| 796 | # define RADEON_ROP3_DPon 0x00050000 | ||
| 797 | # define RADEON_ROP3_PDxn 0x00a50000 | ||
| 798 | # define RADEON_ROP3_PDno 0x00f50000 | ||
| 799 | # define RADEON_ROP3_Pn 0x000f0000 | ||
| 800 | # define RADEON_ROP3_DPno 0x00af0000 | ||
| 801 | # define RADEON_ROP3_DPan 0x005f0000 | ||
| 802 | #define RADEON_DP_GUI_MASTER_CNTL_C 0x1c84 | ||
| 803 | #define RADEON_DP_MIX 0x16c8 | ||
| 804 | #define RADEON_DP_SRC_BKGD_CLR 0x15dc | ||
| 805 | #define RADEON_DP_SRC_FRGD_CLR 0x15d8 | ||
| 806 | #define RADEON_DP_WRITE_MASK 0x16cc | ||
| 807 | #define RADEON_DST_BRES_DEC 0x1630 | ||
| 808 | #define RADEON_DST_BRES_ERR 0x1628 | ||
| 809 | #define RADEON_DST_BRES_INC 0x162c | ||
| 810 | #define RADEON_DST_BRES_LNTH 0x1634 | ||
| 811 | #define RADEON_DST_BRES_LNTH_SUB 0x1638 | ||
| 812 | #define RADEON_DST_HEIGHT 0x1410 | ||
| 813 | #define RADEON_DST_HEIGHT_WIDTH 0x143c | ||
| 814 | #define RADEON_DST_HEIGHT_WIDTH_8 0x158c | ||
| 815 | #define RADEON_DST_HEIGHT_WIDTH_BW 0x15b4 | ||
| 816 | #define RADEON_DST_HEIGHT_Y 0x15a0 | ||
| 817 | #define RADEON_DST_LINE_START 0x1600 | ||
| 818 | #define RADEON_DST_LINE_END 0x1604 | ||
| 819 | #define RADEON_DST_LINE_PATCOUNT 0x1608 | ||
| 820 | # define RADEON_BRES_CNTL_SHIFT 8 | ||
| 821 | #define RADEON_DST_OFFSET 0x1404 | ||
| 822 | #define RADEON_DST_PITCH 0x1408 | ||
| 823 | #define RADEON_DST_PITCH_OFFSET 0x142c | ||
| 824 | #define RADEON_DST_PITCH_OFFSET_C 0x1c80 | ||
| 825 | # define RADEON_PITCH_SHIFT 21 | ||
| 826 | # define RADEON_DST_TILE_LINEAR (0 << 30) | ||
| 827 | # define RADEON_DST_TILE_MACRO (1 << 30) | ||
| 828 | # define RADEON_DST_TILE_MICRO (2 << 30) | ||
| 829 | # define RADEON_DST_TILE_BOTH (3 << 30) | ||
| 830 | #define RADEON_DST_WIDTH 0x140c | ||
| 831 | #define RADEON_DST_WIDTH_HEIGHT 0x1598 | ||
| 832 | #define RADEON_DST_WIDTH_X 0x1588 | ||
| 833 | #define RADEON_DST_WIDTH_X_INCY 0x159c | ||
| 834 | #define RADEON_DST_X 0x141c | ||
| 835 | #define RADEON_DST_X_SUB 0x15a4 | ||
| 836 | #define RADEON_DST_X_Y 0x1594 | ||
| 837 | #define RADEON_DST_Y 0x1420 | ||
| 838 | #define RADEON_DST_Y_SUB 0x15a8 | ||
| 839 | #define RADEON_DST_Y_X 0x1438 | ||
| 840 | |||
| 841 | #define RADEON_FCP_CNTL 0x0910 | ||
| 842 | # define RADEON_FCP0_SRC_PCICLK 0 | ||
| 843 | # define RADEON_FCP0_SRC_PCLK 1 | ||
| 844 | # define RADEON_FCP0_SRC_PCLKb 2 | ||
| 845 | # define RADEON_FCP0_SRC_HREF 3 | ||
| 846 | # define RADEON_FCP0_SRC_GND 4 | ||
| 847 | # define RADEON_FCP0_SRC_HREFb 5 | ||
| 848 | #define RADEON_FLUSH_1 0x1704 | ||
| 849 | #define RADEON_FLUSH_2 0x1708 | ||
| 850 | #define RADEON_FLUSH_3 0x170c | ||
| 851 | #define RADEON_FLUSH_4 0x1710 | ||
| 852 | #define RADEON_FLUSH_5 0x1714 | ||
| 853 | #define RADEON_FLUSH_6 0x1718 | ||
| 854 | #define RADEON_FLUSH_7 0x171c | ||
| 855 | #define RADEON_FOG_3D_TABLE_START 0x1810 | ||
| 856 | #define RADEON_FOG_3D_TABLE_END 0x1814 | ||
| 857 | #define RADEON_FOG_3D_TABLE_DENSITY 0x181c | ||
| 858 | #define RADEON_FOG_TABLE_INDEX 0x1a14 | ||
| 859 | #define RADEON_FOG_TABLE_DATA 0x1a18 | ||
| 860 | #define RADEON_FP_CRTC_H_TOTAL_DISP 0x0250 | ||
| 861 | #define RADEON_FP_CRTC_V_TOTAL_DISP 0x0254 | ||
| 862 | # define RADEON_FP_CRTC_H_TOTAL_MASK 0x000003ff | ||
| 863 | # define RADEON_FP_CRTC_H_DISP_MASK 0x01ff0000 | ||
| 864 | # define RADEON_FP_CRTC_V_TOTAL_MASK 0x00000fff | ||
| 865 | # define RADEON_FP_CRTC_V_DISP_MASK 0x0fff0000 | ||
| 866 | # define RADEON_FP_H_SYNC_STRT_CHAR_MASK 0x00001ff8 | ||
| 867 | # define RADEON_FP_H_SYNC_WID_MASK 0x003f0000 | ||
| 868 | # define RADEON_FP_V_SYNC_STRT_MASK 0x00000fff | ||
| 869 | # define RADEON_FP_V_SYNC_WID_MASK 0x001f0000 | ||
| 870 | # define RADEON_FP_CRTC_H_TOTAL_SHIFT 0x00000000 | ||
| 871 | # define RADEON_FP_CRTC_H_DISP_SHIFT 0x00000010 | ||
| 872 | # define RADEON_FP_CRTC_V_TOTAL_SHIFT 0x00000000 | ||
| 873 | # define RADEON_FP_CRTC_V_DISP_SHIFT 0x00000010 | ||
| 874 | # define RADEON_FP_H_SYNC_STRT_CHAR_SHIFT 0x00000003 | ||
| 875 | # define RADEON_FP_H_SYNC_WID_SHIFT 0x00000010 | ||
| 876 | # define RADEON_FP_V_SYNC_STRT_SHIFT 0x00000000 | ||
| 877 | # define RADEON_FP_V_SYNC_WID_SHIFT 0x00000010 | ||
| 878 | #define RADEON_FP_GEN_CNTL 0x0284 | ||
| 879 | # define RADEON_FP_FPON (1 << 0) | ||
| 880 | # define RADEON_FP_BLANK_EN (1 << 1) | ||
| 881 | # define RADEON_FP_TMDS_EN (1 << 2) | ||
| 882 | # define RADEON_FP_PANEL_FORMAT (1 << 3) | ||
| 883 | # define RADEON_FP_EN_TMDS (1 << 7) | ||
| 884 | # define RADEON_FP_DETECT_SENSE (1 << 8) | ||
| 885 | # define R200_FP_SOURCE_SEL_MASK (3 << 10) | ||
| 886 | # define R200_FP_SOURCE_SEL_CRTC1 (0 << 10) | ||
| 887 | # define R200_FP_SOURCE_SEL_CRTC2 (1 << 10) | ||
| 888 | # define R200_FP_SOURCE_SEL_RMX (2 << 10) | ||
| 889 | # define R200_FP_SOURCE_SEL_TRANS (3 << 10) | ||
| 890 | # define RADEON_FP_SEL_CRTC1 (0 << 13) | ||
| 891 | # define RADEON_FP_SEL_CRTC2 (1 << 13) | ||
| 892 | # define RADEON_FP_CRTC_DONT_SHADOW_HPAR (1 << 15) | ||
| 893 | # define RADEON_FP_CRTC_DONT_SHADOW_VPAR (1 << 16) | ||
| 894 | # define RADEON_FP_CRTC_DONT_SHADOW_HEND (1 << 17) | ||
| 895 | # define RADEON_FP_CRTC_USE_SHADOW_VEND (1 << 18) | ||
| 896 | # define RADEON_FP_RMX_HVSYNC_CONTROL_EN (1 << 20) | ||
| 897 | # define RADEON_FP_DFP_SYNC_SEL (1 << 21) | ||
| 898 | # define RADEON_FP_CRTC_LOCK_8DOT (1 << 22) | ||
| 899 | # define RADEON_FP_CRT_SYNC_SEL (1 << 23) | ||
| 900 | # define RADEON_FP_USE_SHADOW_EN (1 << 24) | ||
| 901 | # define RADEON_FP_CRT_SYNC_ALT (1 << 26) | ||
| 902 | #define RADEON_FP2_GEN_CNTL 0x0288 | ||
| 903 | # define RADEON_FP2_BLANK_EN (1 << 1) | ||
| 904 | # define RADEON_FP2_ON (1 << 2) | ||
| 905 | # define RADEON_FP2_PANEL_FORMAT (1 << 3) | ||
| 906 | # define RADEON_FP2_DETECT_SENSE (1 << 8) | ||
| 907 | # define R200_FP2_SOURCE_SEL_MASK (3 << 10) | ||
| 908 | # define R200_FP2_SOURCE_SEL_CRTC1 (0 << 10) | ||
| 909 | # define R200_FP2_SOURCE_SEL_CRTC2 (1 << 10) | ||
| 910 | # define R200_FP2_SOURCE_SEL_RMX (2 << 10) | ||
| 911 | # define R200_FP2_SOURCE_SEL_TRANS_UNIT (3 << 10) | ||
| 912 | # define RADEON_FP2_SRC_SEL_MASK (3 << 13) | ||
| 913 | # define RADEON_FP2_SRC_SEL_CRTC2 (1 << 13) | ||
| 914 | # define RADEON_FP2_FP_POL (1 << 16) | ||
| 915 | # define RADEON_FP2_LP_POL (1 << 17) | ||
| 916 | # define RADEON_FP2_SCK_POL (1 << 18) | ||
| 917 | # define RADEON_FP2_LCD_CNTL_MASK (7 << 19) | ||
| 918 | # define RADEON_FP2_PAD_FLOP_EN (1 << 22) | ||
| 919 | # define RADEON_FP2_CRC_EN (1 << 23) | ||
| 920 | # define RADEON_FP2_CRC_READ_EN (1 << 24) | ||
| 921 | # define RADEON_FP2_DVO_EN (1 << 25) | ||
| 922 | # define RADEON_FP2_DVO_RATE_SEL_SDR (1 << 26) | ||
| 923 | # define R200_FP2_DVO_RATE_SEL_SDR (1 << 27) | ||
| 924 | # define R300_FP2_DVO_CLOCK_MODE_SINGLE (1 << 28) | ||
| 925 | # define R300_FP2_DVO_DUAL_CHANNEL_EN (1 << 29) | ||
| 926 | #define RADEON_FP_H_SYNC_STRT_WID 0x02c4 | ||
| 927 | #define RADEON_FP_H2_SYNC_STRT_WID 0x03c4 | ||
| 928 | #define RADEON_FP_HORZ_STRETCH 0x028c | ||
| 929 | #define RADEON_FP_HORZ2_STRETCH 0x038c | ||
| 930 | # define RADEON_HORZ_STRETCH_RATIO_MASK 0xffff | ||
| 931 | # define RADEON_HORZ_STRETCH_RATIO_MAX 4096 | ||
| 932 | # define RADEON_HORZ_PANEL_SIZE (0x1ff << 16) | ||
| 933 | # define RADEON_HORZ_PANEL_SHIFT 16 | ||
| 934 | # define RADEON_HORZ_STRETCH_PIXREP (0 << 25) | ||
| 935 | # define RADEON_HORZ_STRETCH_BLEND (1 << 26) | ||
| 936 | # define RADEON_HORZ_STRETCH_ENABLE (1 << 25) | ||
| 937 | # define RADEON_HORZ_AUTO_RATIO (1 << 27) | ||
| 938 | # define RADEON_HORZ_FP_LOOP_STRETCH (0x7 << 28) | ||
| 939 | # define RADEON_HORZ_AUTO_RATIO_INC (1 << 31) | ||
| 940 | #define RADEON_FP_HORZ_VERT_ACTIVE 0x0278 | ||
| 941 | #define RADEON_FP_V_SYNC_STRT_WID 0x02c8 | ||
| 942 | #define RADEON_FP_VERT_STRETCH 0x0290 | ||
| 943 | #define RADEON_FP_V2_SYNC_STRT_WID 0x03c8 | ||
| 944 | #define RADEON_FP_VERT2_STRETCH 0x0390 | ||
| 945 | # define RADEON_VERT_PANEL_SIZE (0xfff << 12) | ||
| 946 | # define RADEON_VERT_PANEL_SHIFT 12 | ||
| 947 | # define RADEON_VERT_STRETCH_RATIO_MASK 0xfff | ||
| 948 | # define RADEON_VERT_STRETCH_RATIO_SHIFT 0 | ||
| 949 | # define RADEON_VERT_STRETCH_RATIO_MAX 4096 | ||
| 950 | # define RADEON_VERT_STRETCH_ENABLE (1 << 25) | ||
| 951 | # define RADEON_VERT_STRETCH_LINEREP (0 << 26) | ||
| 952 | # define RADEON_VERT_STRETCH_BLEND (1 << 26) | ||
| 953 | # define RADEON_VERT_AUTO_RATIO_EN (1 << 27) | ||
| 954 | # define RADEON_VERT_AUTO_RATIO_INC (1 << 31) | ||
| 955 | # define RADEON_VERT_STRETCH_RESERVED 0x71000000 | ||
| 956 | #define RS400_FP_2ND_GEN_CNTL 0x0384 | ||
| 957 | # define RS400_FP_2ND_ON (1 << 0) | ||
| 958 | # define RS400_FP_2ND_BLANK_EN (1 << 1) | ||
| 959 | # define RS400_TMDS_2ND_EN (1 << 2) | ||
| 960 | # define RS400_PANEL_FORMAT_2ND (1 << 3) | ||
| 961 | # define RS400_FP_2ND_EN_TMDS (1 << 7) | ||
| 962 | # define RS400_FP_2ND_DETECT_SENSE (1 << 8) | ||
| 963 | # define RS400_FP_2ND_SOURCE_SEL_MASK (3 << 10) | ||
| 964 | # define RS400_FP_2ND_SOURCE_SEL_CRTC1 (0 << 10) | ||
| 965 | # define RS400_FP_2ND_SOURCE_SEL_CRTC2 (1 << 10) | ||
| 966 | # define RS400_FP_2ND_SOURCE_SEL_RMX (2 << 10) | ||
| 967 | # define RS400_FP_2ND_DETECT_EN (1 << 12) | ||
| 968 | # define RS400_HPD_2ND_SEL (1 << 13) | ||
| 969 | #define RS400_FP2_2_GEN_CNTL 0x0388 | ||
| 970 | # define RS400_FP2_2_BLANK_EN (1 << 1) | ||
| 971 | # define RS400_FP2_2_ON (1 << 2) | ||
| 972 | # define RS400_FP2_2_PANEL_FORMAT (1 << 3) | ||
| 973 | # define RS400_FP2_2_DETECT_SENSE (1 << 8) | ||
| 974 | # define RS400_FP2_2_SOURCE_SEL_MASK (3 << 10) | ||
| 975 | # define RS400_FP2_2_SOURCE_SEL_CRTC1 (0 << 10) | ||
| 976 | # define RS400_FP2_2_SOURCE_SEL_CRTC2 (1 << 10) | ||
| 977 | # define RS400_FP2_2_SOURCE_SEL_RMX (2 << 10) | ||
| 978 | # define RS400_FP2_2_DVO2_EN (1 << 25) | ||
| 979 | #define RS400_TMDS2_CNTL 0x0394 | ||
| 980 | #define RS400_TMDS2_TRANSMITTER_CNTL 0x03a4 | ||
| 981 | # define RS400_TMDS2_PLLEN (1 << 0) | ||
| 982 | # define RS400_TMDS2_PLLRST (1 << 1) | ||
| 983 | |||
| 984 | #define RADEON_GEN_INT_CNTL 0x0040 | ||
| 985 | # define RADEON_SW_INT_ENABLE (1 << 25) | ||
| 986 | #define RADEON_GEN_INT_STATUS 0x0044 | ||
| 987 | # define RADEON_VSYNC_INT_AK (1 << 2) | ||
| 988 | # define RADEON_VSYNC_INT (1 << 2) | ||
| 989 | # define RADEON_VSYNC2_INT_AK (1 << 6) | ||
| 990 | # define RADEON_VSYNC2_INT (1 << 6) | ||
| 991 | # define RADEON_SW_INT_FIRE (1 << 26) | ||
| 992 | # define RADEON_SW_INT_TEST (1 << 25) | ||
| 993 | # define RADEON_SW_INT_TEST_ACK (1 << 25) | ||
| 994 | #define RADEON_GENENB 0x03c3 /* VGA */ | ||
| 995 | #define RADEON_GENFC_RD 0x03ca /* VGA */ | ||
| 996 | #define RADEON_GENFC_WT 0x03da /* VGA, 0x03ba */ | ||
| 997 | #define RADEON_GENMO_RD 0x03cc /* VGA */ | ||
| 998 | #define RADEON_GENMO_WT 0x03c2 /* VGA */ | ||
| 999 | #define RADEON_GENS0 0x03c2 /* VGA */ | ||
| 1000 | #define RADEON_GENS1 0x03da /* VGA, 0x03ba */ | ||
| 1001 | #define RADEON_GPIO_MONID 0x0068 /* DDC interface via I2C */ /* DDC3 */ | ||
| 1002 | #define RADEON_GPIO_MONIDB 0x006c | ||
| 1003 | #define RADEON_GPIO_CRT2_DDC 0x006c | ||
| 1004 | #define RADEON_GPIO_DVI_DDC 0x0064 /* DDC2 */ | ||
| 1005 | #define RADEON_GPIO_VGA_DDC 0x0060 /* DDC1 */ | ||
| 1006 | # define RADEON_GPIO_A_0 (1 << 0) | ||
| 1007 | # define RADEON_GPIO_A_1 (1 << 1) | ||
| 1008 | # define RADEON_GPIO_Y_0 (1 << 8) | ||
| 1009 | # define RADEON_GPIO_Y_1 (1 << 9) | ||
| 1010 | # define RADEON_GPIO_Y_SHIFT_0 8 | ||
| 1011 | # define RADEON_GPIO_Y_SHIFT_1 9 | ||
| 1012 | # define RADEON_GPIO_EN_0 (1 << 16) | ||
| 1013 | # define RADEON_GPIO_EN_1 (1 << 17) | ||
| 1014 | # define RADEON_GPIO_MASK_0 (1 << 24) /*??*/ | ||
| 1015 | # define RADEON_GPIO_MASK_1 (1 << 25) /*??*/ | ||
| 1016 | #define RADEON_GRPH8_DATA 0x03cf /* VGA */ | ||
| 1017 | #define RADEON_GRPH8_IDX 0x03ce /* VGA */ | ||
| 1018 | #define RADEON_GUI_SCRATCH_REG0 0x15e0 | ||
| 1019 | #define RADEON_GUI_SCRATCH_REG1 0x15e4 | ||
| 1020 | #define RADEON_GUI_SCRATCH_REG2 0x15e8 | ||
| 1021 | #define RADEON_GUI_SCRATCH_REG3 0x15ec | ||
| 1022 | #define RADEON_GUI_SCRATCH_REG4 0x15f0 | ||
| 1023 | #define RADEON_GUI_SCRATCH_REG5 0x15f4 | ||
| 1024 | |||
| 1025 | #define RADEON_HEADER 0x0f0e /* PCI */ | ||
| 1026 | #define RADEON_HOST_DATA0 0x17c0 | ||
| 1027 | #define RADEON_HOST_DATA1 0x17c4 | ||
| 1028 | #define RADEON_HOST_DATA2 0x17c8 | ||
| 1029 | #define RADEON_HOST_DATA3 0x17cc | ||
| 1030 | #define RADEON_HOST_DATA4 0x17d0 | ||
| 1031 | #define RADEON_HOST_DATA5 0x17d4 | ||
| 1032 | #define RADEON_HOST_DATA6 0x17d8 | ||
| 1033 | #define RADEON_HOST_DATA7 0x17dc | ||
| 1034 | #define RADEON_HOST_DATA_LAST 0x17e0 | ||
| 1035 | #define RADEON_HOST_PATH_CNTL 0x0130 | ||
| 1036 | # define RADEON_HP_LIN_RD_CACHE_DIS (1 << 24) | ||
| 1037 | # define RADEON_HDP_READ_BUFFER_INVALIDATE (1 << 27) | ||
| 1038 | # define RADEON_HDP_SOFT_RESET (1 << 26) | ||
| 1039 | # define RADEON_HDP_APER_CNTL (1 << 23) | ||
| 1040 | #define RADEON_HTOTAL_CNTL 0x0009 /* PLL */ | ||
| 1041 | # define RADEON_HTOT_CNTL_VGA_EN (1 << 28) | ||
| 1042 | #define RADEON_HTOTAL2_CNTL 0x002e /* PLL */ | ||
| 1043 | |||
| 1044 | /* Multimedia I2C bus */ | ||
| 1045 | #define RADEON_I2C_CNTL_0 0x0090 | ||
| 1046 | #define RADEON_I2C_DONE (1<<0) | ||
| 1047 | #define RADEON_I2C_NACK (1<<1) | ||
| 1048 | #define RADEON_I2C_HALT (1<<2) | ||
| 1049 | #define RADEON_I2C_SOFT_RST (1<<5) | ||
| 1050 | #define RADEON_I2C_DRIVE_EN (1<<6) | ||
| 1051 | #define RADEON_I2C_DRIVE_SEL (1<<7) | ||
| 1052 | #define RADEON_I2C_START (1<<8) | ||
| 1053 | #define RADEON_I2C_STOP (1<<9) | ||
| 1054 | #define RADEON_I2C_RECEIVE (1<<10) | ||
| 1055 | #define RADEON_I2C_ABORT (1<<11) | ||
| 1056 | #define RADEON_I2C_GO (1<<12) | ||
| 1057 | #define RADEON_I2C_CNTL_1 0x0094 | ||
| 1058 | #define RADEON_I2C_SEL (1<<16) | ||
| 1059 | #define RADEON_I2C_EN (1<<17) | ||
| 1060 | #define RADEON_I2C_DATA 0x0098 | ||
| 1061 | |||
| 1062 | #define RADEON_DVI_I2C_CNTL_0 0x02e0 | ||
| 1063 | # define R200_DVI_I2C_PIN_SEL(x) ((x) << 3) | ||
| 1064 | # define R200_SEL_DDC1 0 /* 0x60 - VGA_DDC */ | ||
| 1065 | # define R200_SEL_DDC2 1 /* 0x64 - DVI_DDC */ | ||
| 1066 | # define R200_SEL_DDC3 2 /* 0x68 - MONID_DDC */ | ||
| 1067 | #define RADEON_DVI_I2C_CNTL_1 0x02e4 /* ? */ | ||
| 1068 | #define RADEON_DVI_I2C_DATA 0x02e8 | ||
| 1069 | |||
| 1070 | #define RADEON_INTERRUPT_LINE 0x0f3c /* PCI */ | ||
| 1071 | #define RADEON_INTERRUPT_PIN 0x0f3d /* PCI */ | ||
| 1072 | #define RADEON_IO_BASE 0x0f14 /* PCI */ | ||
| 1073 | |||
| 1074 | #define RADEON_LATENCY 0x0f0d /* PCI */ | ||
| 1075 | #define RADEON_LEAD_BRES_DEC 0x1608 | ||
| 1076 | #define RADEON_LEAD_BRES_LNTH 0x161c | ||
| 1077 | #define RADEON_LEAD_BRES_LNTH_SUB 0x1624 | ||
| 1078 | #define RADEON_LVDS_GEN_CNTL 0x02d0 | ||
| 1079 | # define RADEON_LVDS_ON (1 << 0) | ||
| 1080 | # define RADEON_LVDS_DISPLAY_DIS (1 << 1) | ||
| 1081 | # define RADEON_LVDS_PANEL_TYPE (1 << 2) | ||
| 1082 | # define RADEON_LVDS_PANEL_FORMAT (1 << 3) | ||
| 1083 | # define RADEON_LVDS_NO_FM (0 << 4) | ||
| 1084 | # define RADEON_LVDS_2_GREY (1 << 4) | ||
| 1085 | # define RADEON_LVDS_4_GREY (2 << 4) | ||
| 1086 | # define RADEON_LVDS_RST_FM (1 << 6) | ||
| 1087 | # define RADEON_LVDS_EN (1 << 7) | ||
| 1088 | # define RADEON_LVDS_BL_MOD_LEVEL_SHIFT 8 | ||
| 1089 | # define RADEON_LVDS_BL_MOD_LEVEL_MASK (0xff << 8) | ||
| 1090 | # define RADEON_LVDS_BL_MOD_EN (1 << 16) | ||
| 1091 | # define RADEON_LVDS_BL_CLK_SEL (1 << 17) | ||
| 1092 | # define RADEON_LVDS_DIGON (1 << 18) | ||
| 1093 | # define RADEON_LVDS_BLON (1 << 19) | ||
| 1094 | # define RADEON_LVDS_FP_POL_LOW (1 << 20) | ||
| 1095 | # define RADEON_LVDS_LP_POL_LOW (1 << 21) | ||
| 1096 | # define RADEON_LVDS_DTM_POL_LOW (1 << 22) | ||
| 1097 | # define RADEON_LVDS_SEL_CRTC2 (1 << 23) | ||
| 1098 | # define RADEON_LVDS_FPDI_EN (1 << 27) | ||
| 1099 | # define RADEON_LVDS_HSYNC_DELAY_SHIFT 28 | ||
| 1100 | #define RADEON_LVDS_PLL_CNTL 0x02d4 | ||
| 1101 | # define RADEON_HSYNC_DELAY_SHIFT 28 | ||
| 1102 | # define RADEON_HSYNC_DELAY_MASK (0xf << 28) | ||
| 1103 | # define RADEON_LVDS_PLL_EN (1 << 16) | ||
| 1104 | # define RADEON_LVDS_PLL_RESET (1 << 17) | ||
| 1105 | # define R300_LVDS_SRC_SEL_MASK (3 << 18) | ||
| 1106 | # define R300_LVDS_SRC_SEL_CRTC1 (0 << 18) | ||
| 1107 | # define R300_LVDS_SRC_SEL_CRTC2 (1 << 18) | ||
| 1108 | # define R300_LVDS_SRC_SEL_RMX (2 << 18) | ||
| 1109 | #define RADEON_LVDS_SS_GEN_CNTL 0x02ec | ||
| 1110 | # define RADEON_LVDS_PWRSEQ_DELAY1_SHIFT 16 | ||
| 1111 | # define RADEON_LVDS_PWRSEQ_DELAY2_SHIFT 20 | ||
| 1112 | |||
| 1113 | #define RADEON_MAX_LATENCY 0x0f3f /* PCI */ | ||
| 1114 | #define RADEON_DISPLAY_BASE_ADDR 0x23c | ||
| 1115 | #define RADEON_DISPLAY2_BASE_ADDR 0x33c | ||
| 1116 | #define RADEON_OV0_BASE_ADDR 0x43c | ||
| 1117 | #define RADEON_NB_TOM 0x15c | ||
| 1118 | #define R300_MC_INIT_MISC_LAT_TIMER 0x180 | ||
| 1119 | # define R300_MC_DISP0R_INIT_LAT_SHIFT 8 | ||
| 1120 | # define R300_MC_DISP0R_INIT_LAT_MASK 0xf | ||
| 1121 | # define R300_MC_DISP1R_INIT_LAT_SHIFT 12 | ||
| 1122 | # define R300_MC_DISP1R_INIT_LAT_MASK 0xf | ||
| 1123 | #define RADEON_MCLK_CNTL 0x0012 /* PLL */ | ||
| 1124 | # define RADEON_MCLKA_SRC_SEL_MASK 0x7 | ||
| 1125 | # define RADEON_FORCEON_MCLKA (1 << 16) | ||
| 1126 | # define RADEON_FORCEON_MCLKB (1 << 17) | ||
| 1127 | # define RADEON_FORCEON_YCLKA (1 << 18) | ||
| 1128 | # define RADEON_FORCEON_YCLKB (1 << 19) | ||
| 1129 | # define RADEON_FORCEON_MC (1 << 20) | ||
| 1130 | # define RADEON_FORCEON_AIC (1 << 21) | ||
| 1131 | # define R300_DISABLE_MC_MCLKA (1 << 21) | ||
| 1132 | # define R300_DISABLE_MC_MCLKB (1 << 21) | ||
| 1133 | #define RADEON_MCLK_MISC 0x001f /* PLL */ | ||
| 1134 | # define RADEON_MC_MCLK_MAX_DYN_STOP_LAT (1 << 12) | ||
| 1135 | # define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1 << 13) | ||
| 1136 | # define RADEON_MC_MCLK_DYN_ENABLE (1 << 14) | ||
| 1137 | # define RADEON_IO_MCLK_DYN_ENABLE (1 << 15) | ||
| 1138 | #define RADEON_LCD_GPIO_MASK 0x01a0 | ||
| 1139 | #define RADEON_GPIOPAD_EN 0x01a0 | ||
| 1140 | #define RADEON_LCD_GPIO_Y_REG 0x01a4 | ||
| 1141 | #define RADEON_MDGPIO_A_REG 0x01ac | ||
| 1142 | #define RADEON_MDGPIO_EN_REG 0x01b0 | ||
| 1143 | #define RADEON_MDGPIO_MASK 0x0198 | ||
| 1144 | #define RADEON_GPIOPAD_MASK 0x0198 | ||
| 1145 | #define RADEON_GPIOPAD_A 0x019c | ||
| 1146 | #define RADEON_MDGPIO_Y_REG 0x01b4 | ||
| 1147 | #define RADEON_MEM_ADDR_CONFIG 0x0148 | ||
| 1148 | #define RADEON_MEM_BASE 0x0f10 /* PCI */ | ||
| 1149 | #define RADEON_MEM_CNTL 0x0140 | ||
| 1150 | # define RADEON_MEM_NUM_CHANNELS_MASK 0x01 | ||
| 1151 | # define RADEON_MEM_USE_B_CH_ONLY (1 << 1) | ||
| 1152 | # define RV100_HALF_MODE (1 << 3) | ||
| 1153 | # define R300_MEM_NUM_CHANNELS_MASK 0x03 | ||
| 1154 | # define R300_MEM_USE_CD_CH_ONLY (1 << 2) | ||
| 1155 | #define RADEON_MEM_TIMING_CNTL 0x0144 /* EXT_MEM_CNTL */ | ||
| 1156 | #define RADEON_MEM_INIT_LAT_TIMER 0x0154 | ||
| 1157 | #define RADEON_MEM_INTF_CNTL 0x014c | ||
| 1158 | #define RADEON_MEM_SDRAM_MODE_REG 0x0158 | ||
| 1159 | # define RADEON_SDRAM_MODE_MASK 0xffff0000 | ||
| 1160 | # define RADEON_B3MEM_RESET_MASK 0x6fffffff | ||
| 1161 | # define RADEON_MEM_CFG_TYPE_DDR (1 << 30) | ||
| 1162 | #define RADEON_MEM_STR_CNTL 0x0150 | ||
| 1163 | # define RADEON_MEM_PWRUP_COMPL_A (1 << 0) | ||
| 1164 | # define RADEON_MEM_PWRUP_COMPL_B (1 << 1) | ||
| 1165 | # define R300_MEM_PWRUP_COMPL_C (1 << 2) | ||
| 1166 | # define R300_MEM_PWRUP_COMPL_D (1 << 3) | ||
| 1167 | # define RADEON_MEM_PWRUP_COMPLETE 0x03 | ||
| 1168 | # define R300_MEM_PWRUP_COMPLETE 0x0f | ||
| 1169 | #define RADEON_MC_STATUS 0x0150 | ||
| 1170 | # define RADEON_MC_IDLE (1 << 2) | ||
| 1171 | # define R300_MC_IDLE (1 << 4) | ||
| 1172 | #define RADEON_MEM_VGA_RP_SEL 0x003c | ||
| 1173 | #define RADEON_MEM_VGA_WP_SEL 0x0038 | ||
| 1174 | #define RADEON_MIN_GRANT 0x0f3e /* PCI */ | ||
| 1175 | #define RADEON_MM_DATA 0x0004 | ||
| 1176 | #define RADEON_MM_INDEX 0x0000 | ||
| 1177 | # define RADEON_MM_APER (1 << 31) | ||
| 1178 | #define RADEON_MPLL_CNTL 0x000e /* PLL */ | ||
| 1179 | #define RADEON_MPP_TB_CONFIG 0x01c0 /* ? */ | ||
| 1180 | #define RADEON_MPP_GP_CONFIG 0x01c8 /* ? */ | ||
| 1181 | #define RADEON_SEPROM_CNTL1 0x01c0 | ||
| 1182 | # define RADEON_SCK_PRESCALE_SHIFT 24 | ||
| 1183 | # define RADEON_SCK_PRESCALE_MASK (0xff << 24) | ||
| 1184 | #define R300_MC_IND_INDEX 0x01f8 | ||
| 1185 | # define R300_MC_IND_ADDR_MASK 0x3f | ||
| 1186 | # define R300_MC_IND_WR_EN (1 << 8) | ||
| 1187 | #define R300_MC_IND_DATA 0x01fc | ||
| 1188 | #define R300_MC_READ_CNTL_AB 0x017c | ||
| 1189 | # define R300_MEM_RBS_POSITION_A_MASK 0x03 | ||
| 1190 | #define R300_MC_READ_CNTL_CD_mcind 0x24 | ||
| 1191 | # define R300_MEM_RBS_POSITION_C_MASK 0x03 | ||
| 1192 | |||
| 1193 | #define RADEON_N_VIF_COUNT 0x0248 | ||
| 1194 | |||
| 1195 | #define RADEON_OV0_AUTO_FLIP_CNTL 0x0470 | ||
| 1196 | # define RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_NUM 0x00000007 | ||
| 1197 | # define RADEON_OV0_AUTO_FLIP_CNTL_SOFT_REPEAT_FIELD 0x00000008 | ||
| 1198 | # define RADEON_OV0_AUTO_FLIP_CNTL_SOFT_BUF_ODD 0x00000010 | ||
| 1199 | # define RADEON_OV0_AUTO_FLIP_CNTL_IGNORE_REPEAT_FIELD 0x00000020 | ||
| 1200 | # define RADEON_OV0_AUTO_FLIP_CNTL_SOFT_EOF_TOGGLE 0x00000040 | ||
| 1201 | # define RADEON_OV0_AUTO_FLIP_CNTL_VID_PORT_SELECT 0x00000300 | ||
| 1202 | # define RADEON_OV0_AUTO_FLIP_CNTL_P1_FIRST_LINE_EVEN 0x00010000 | ||
| 1203 | # define RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_EVEN_DOWN 0x00040000 | ||
| 1204 | # define RADEON_OV0_AUTO_FLIP_CNTL_SHIFT_ODD_DOWN 0x00080000 | ||
| 1205 | # define RADEON_OV0_AUTO_FLIP_CNTL_FIELD_POL_SOURCE 0x00800000 | ||
| 1206 | |||
| 1207 | #define RADEON_OV0_COLOUR_CNTL 0x04E0 | ||
| 1208 | #define RADEON_OV0_DEINTERLACE_PATTERN 0x0474 | ||
| 1209 | #define RADEON_OV0_EXCLUSIVE_HORZ 0x0408 | ||
| 1210 | # define RADEON_EXCL_HORZ_START_MASK 0x000000ff | ||
| 1211 | # define RADEON_EXCL_HORZ_END_MASK 0x0000ff00 | ||
| 1212 | # define RADEON_EXCL_HORZ_BACK_PORCH_MASK 0x00ff0000 | ||
| 1213 | # define RADEON_EXCL_HORZ_EXCLUSIVE_EN 0x80000000 | ||
| 1214 | #define RADEON_OV0_EXCLUSIVE_VERT 0x040C | ||
| 1215 | # define RADEON_EXCL_VERT_START_MASK 0x000003ff | ||
| 1216 | # define RADEON_EXCL_VERT_END_MASK 0x03ff0000 | ||
| 1217 | #define RADEON_OV0_FILTER_CNTL 0x04A0 | ||
| 1218 | # define RADEON_FILTER_PROGRAMMABLE_COEF 0x0 | ||
| 1219 | # define RADEON_FILTER_HC_COEF_HORZ_Y 0x1 | ||
| 1220 | # define RADEON_FILTER_HC_COEF_HORZ_UV 0x2 | ||
| 1221 | # define RADEON_FILTER_HC_COEF_VERT_Y 0x4 | ||
| 1222 | # define RADEON_FILTER_HC_COEF_VERT_UV 0x8 | ||
| 1223 | # define RADEON_FILTER_HARDCODED_COEF 0xf | ||
| 1224 | # define RADEON_FILTER_COEF_MASK 0xf | ||
| 1225 | |||
| 1226 | #define RADEON_OV0_FOUR_TAP_COEF_0 0x04B0 | ||
| 1227 | #define RADEON_OV0_FOUR_TAP_COEF_1 0x04B4 | ||
| 1228 | #define RADEON_OV0_FOUR_TAP_COEF_2 0x04B8 | ||
| 1229 | #define RADEON_OV0_FOUR_TAP_COEF_3 0x04BC | ||
| 1230 | #define RADEON_OV0_FOUR_TAP_COEF_4 0x04C0 | ||
| 1231 | #define RADEON_OV0_FLAG_CNTL 0x04DC | ||
| 1232 | #define RADEON_OV0_GAMMA_000_00F 0x0d40 | ||
| 1233 | #define RADEON_OV0_GAMMA_010_01F 0x0d44 | ||
| 1234 | #define RADEON_OV0_GAMMA_020_03F 0x0d48 | ||
| 1235 | #define RADEON_OV0_GAMMA_040_07F 0x0d4c | ||
| 1236 | #define RADEON_OV0_GAMMA_080_0BF 0x0e00 | ||
| 1237 | #define RADEON_OV0_GAMMA_0C0_0FF 0x0e04 | ||
| 1238 | #define RADEON_OV0_GAMMA_100_13F 0x0e08 | ||
| 1239 | #define RADEON_OV0_GAMMA_140_17F 0x0e0c | ||
| 1240 | #define RADEON_OV0_GAMMA_180_1BF 0x0e10 | ||
| 1241 | #define RADEON_OV0_GAMMA_1C0_1FF 0x0e14 | ||
| 1242 | #define RADEON_OV0_GAMMA_200_23F 0x0e18 | ||
| 1243 | #define RADEON_OV0_GAMMA_240_27F 0x0e1c | ||
| 1244 | #define RADEON_OV0_GAMMA_280_2BF 0x0e20 | ||
| 1245 | #define RADEON_OV0_GAMMA_2C0_2FF 0x0e24 | ||
| 1246 | #define RADEON_OV0_GAMMA_300_33F 0x0e28 | ||
| 1247 | #define RADEON_OV0_GAMMA_340_37F 0x0e2c | ||
| 1248 | #define RADEON_OV0_GAMMA_380_3BF 0x0d50 | ||
| 1249 | #define RADEON_OV0_GAMMA_3C0_3FF 0x0d54 | ||
| 1250 | #define RADEON_OV0_GRAPHICS_KEY_CLR_LOW 0x04EC | ||
| 1251 | #define RADEON_OV0_GRAPHICS_KEY_CLR_HIGH 0x04F0 | ||
| 1252 | #define RADEON_OV0_H_INC 0x0480 | ||
| 1253 | #define RADEON_OV0_KEY_CNTL 0x04F4 | ||
| 1254 | # define RADEON_VIDEO_KEY_FN_MASK 0x00000003L | ||
| 1255 | # define RADEON_VIDEO_KEY_FN_FALSE 0x00000000L | ||
| 1256 | # define RADEON_VIDEO_KEY_FN_TRUE 0x00000001L | ||
| 1257 | # define RADEON_VIDEO_KEY_FN_EQ 0x00000002L | ||
| 1258 | # define RADEON_VIDEO_KEY_FN_NE 0x00000003L | ||
| 1259 | # define RADEON_GRAPHIC_KEY_FN_MASK 0x00000030L | ||
| 1260 | # define RADEON_GRAPHIC_KEY_FN_FALSE 0x00000000L | ||
| 1261 | # define RADEON_GRAPHIC_KEY_FN_TRUE 0x00000010L | ||
| 1262 | # define RADEON_GRAPHIC_KEY_FN_EQ 0x00000020L | ||
| 1263 | # define RADEON_GRAPHIC_KEY_FN_NE 0x00000030L | ||
| 1264 | # define RADEON_CMP_MIX_MASK 0x00000100L | ||
| 1265 | # define RADEON_CMP_MIX_OR 0x00000000L | ||
| 1266 | # define RADEON_CMP_MIX_AND 0x00000100L | ||
| 1267 | #define RADEON_OV0_LIN_TRANS_A 0x0d20 | ||
| 1268 | #define RADEON_OV0_LIN_TRANS_B 0x0d24 | ||
| 1269 | #define RADEON_OV0_LIN_TRANS_C 0x0d28 | ||
| 1270 | #define RADEON_OV0_LIN_TRANS_D 0x0d2c | ||
| 1271 | #define RADEON_OV0_LIN_TRANS_E 0x0d30 | ||
| 1272 | #define RADEON_OV0_LIN_TRANS_F 0x0d34 | ||
| 1273 | #define RADEON_OV0_P1_BLANK_LINES_AT_TOP 0x0430 | ||
| 1274 | # define RADEON_P1_BLNK_LN_AT_TOP_M1_MASK 0x00000fffL | ||
| 1275 | # define RADEON_P1_ACTIVE_LINES_M1 0x0fff0000L | ||
| 1276 | #define RADEON_OV0_P1_H_ACCUM_INIT 0x0488 | ||
| 1277 | #define RADEON_OV0_P1_V_ACCUM_INIT 0x0428 | ||
| 1278 | # define RADEON_OV0_P1_MAX_LN_IN_PER_LN_OUT 0x00000003L | ||
| 1279 | # define RADEON_OV0_P1_V_ACCUM_INIT_MASK 0x01ff8000L | ||
| 1280 | #define RADEON_OV0_P1_X_START_END 0x0494 | ||
| 1281 | #define RADEON_OV0_P2_X_START_END 0x0498 | ||
| 1282 | #define RADEON_OV0_P23_BLANK_LINES_AT_TOP 0x0434 | ||
| 1283 | # define RADEON_P23_BLNK_LN_AT_TOP_M1_MASK 0x000007ffL | ||
| 1284 | # define RADEON_P23_ACTIVE_LINES_M1 0x07ff0000L | ||
| 1285 | #define RADEON_OV0_P23_H_ACCUM_INIT 0x048C | ||
| 1286 | #define RADEON_OV0_P23_V_ACCUM_INIT 0x042C | ||
| 1287 | #define RADEON_OV0_P3_X_START_END 0x049C | ||
| 1288 | #define RADEON_OV0_REG_LOAD_CNTL 0x0410 | ||
| 1289 | # define RADEON_REG_LD_CTL_LOCK 0x00000001L | ||
| 1290 | # define RADEON_REG_LD_CTL_VBLANK_DURING_LOCK 0x00000002L | ||
| 1291 | # define RADEON_REG_LD_CTL_STALL_GUI_UNTIL_FLIP 0x00000004L | ||
| 1292 | # define RADEON_REG_LD_CTL_LOCK_READBACK 0x00000008L | ||
| 1293 | # define RADEON_REG_LD_CTL_FLIP_READBACK 0x00000010L | ||
| 1294 | #define RADEON_OV0_SCALE_CNTL 0x0420 | ||
| 1295 | # define RADEON_SCALER_HORZ_PICK_NEAREST 0x00000004L | ||
| 1296 | # define RADEON_SCALER_VERT_PICK_NEAREST 0x00000008L | ||
| 1297 | # define RADEON_SCALER_SIGNED_UV 0x00000010L | ||
| 1298 | # define RADEON_SCALER_GAMMA_SEL_MASK 0x00000060L | ||
| 1299 | # define RADEON_SCALER_GAMMA_SEL_BRIGHT 0x00000000L | ||
| 1300 | # define RADEON_SCALER_GAMMA_SEL_G22 0x00000020L | ||
| 1301 | # define RADEON_SCALER_GAMMA_SEL_G18 0x00000040L | ||
| 1302 | # define RADEON_SCALER_GAMMA_SEL_G14 0x00000060L | ||
| 1303 | # define RADEON_SCALER_COMCORE_SHIFT_UP_ONE 0x00000080L | ||
| 1304 | # define RADEON_SCALER_SURFAC_FORMAT 0x00000f00L | ||
| 1305 | # define RADEON_SCALER_SOURCE_15BPP 0x00000300L | ||
| 1306 | # define RADEON_SCALER_SOURCE_16BPP 0x00000400L | ||
| 1307 | # define RADEON_SCALER_SOURCE_32BPP 0x00000600L | ||
| 1308 | # define RADEON_SCALER_SOURCE_YUV9 0x00000900L | ||
| 1309 | # define RADEON_SCALER_SOURCE_YUV12 0x00000A00L | ||
| 1310 | # define RADEON_SCALER_SOURCE_VYUY422 0x00000B00L | ||
| 1311 | # define RADEON_SCALER_SOURCE_YVYU422 0x00000C00L | ||
| 1312 | # define RADEON_SCALER_ADAPTIVE_DEINT 0x00001000L | ||
| 1313 | # define RADEON_SCALER_TEMPORAL_DEINT 0x00002000L | ||
| 1314 | # define RADEON_SCALER_CRTC_SEL 0x00004000L | ||
| 1315 | # define RADEON_SCALER_SMART_SWITCH 0x00008000L | ||
| 1316 | # define RADEON_SCALER_BURST_PER_PLANE 0x007F0000L | ||
| 1317 | # define RADEON_SCALER_DOUBLE_BUFFER 0x01000000L | ||
| 1318 | # define RADEON_SCALER_DIS_LIMIT 0x08000000L | ||
| 1319 | # define RADEON_SCALER_LIN_TRANS_BYPASS 0x10000000L | ||
| 1320 | # define RADEON_SCALER_INT_EMU 0x20000000L | ||
| 1321 | # define RADEON_SCALER_ENABLE 0x40000000L | ||
| 1322 | # define RADEON_SCALER_SOFT_RESET 0x80000000L | ||
| 1323 | #define RADEON_OV0_STEP_BY 0x0484 | ||
| 1324 | #define RADEON_OV0_TEST 0x04F8 | ||
| 1325 | #define RADEON_OV0_V_INC 0x0424 | ||
| 1326 | #define RADEON_OV0_VID_BUF_PITCH0_VALUE 0x0460 | ||
| 1327 | #define RADEON_OV0_VID_BUF_PITCH1_VALUE 0x0464 | ||
| 1328 | #define RADEON_OV0_VID_BUF0_BASE_ADRS 0x0440 | ||
| 1329 | # define RADEON_VIF_BUF0_PITCH_SEL 0x00000001L | ||
| 1330 | # define RADEON_VIF_BUF0_TILE_ADRS 0x00000002L | ||
| 1331 | # define RADEON_VIF_BUF0_BASE_ADRS_MASK 0x03fffff0L | ||
| 1332 | # define RADEON_VIF_BUF0_1ST_LINE_LSBS_MASK 0x48000000L | ||
| 1333 | #define RADEON_OV0_VID_BUF1_BASE_ADRS 0x0444 | ||
| 1334 | # define RADEON_VIF_BUF1_PITCH_SEL 0x00000001L | ||
| 1335 | # define RADEON_VIF_BUF1_TILE_ADRS 0x00000002L | ||
| 1336 | # define RADEON_VIF_BUF1_BASE_ADRS_MASK 0x03fffff0L | ||
| 1337 | # define RADEON_VIF_BUF1_1ST_LINE_LSBS_MASK 0x48000000L | ||
| 1338 | #define RADEON_OV0_VID_BUF2_BASE_ADRS 0x0448 | ||
| 1339 | # define RADEON_VIF_BUF2_PITCH_SEL 0x00000001L | ||
| 1340 | # define RADEON_VIF_BUF2_TILE_ADRS 0x00000002L | ||
| 1341 | # define RADEON_VIF_BUF2_BASE_ADRS_MASK 0x03fffff0L | ||
| 1342 | # define RADEON_VIF_BUF2_1ST_LINE_LSBS_MASK 0x48000000L | ||
| 1343 | #define RADEON_OV0_VID_BUF3_BASE_ADRS 0x044C | ||
| 1344 | #define RADEON_OV0_VID_BUF4_BASE_ADRS 0x0450 | ||
| 1345 | #define RADEON_OV0_VID_BUF5_BASE_ADRS 0x0454 | ||
| 1346 | #define RADEON_OV0_VIDEO_KEY_CLR_HIGH 0x04E8 | ||
| 1347 | #define RADEON_OV0_VIDEO_KEY_CLR_LOW 0x04E4 | ||
| 1348 | #define RADEON_OV0_Y_X_START 0x0400 | ||
| 1349 | #define RADEON_OV0_Y_X_END 0x0404 | ||
| 1350 | #define RADEON_OV1_Y_X_START 0x0600 | ||
| 1351 | #define RADEON_OV1_Y_X_END 0x0604 | ||
| 1352 | #define RADEON_OVR_CLR 0x0230 | ||
| 1353 | #define RADEON_OVR_WID_LEFT_RIGHT 0x0234 | ||
| 1354 | #define RADEON_OVR_WID_TOP_BOTTOM 0x0238 | ||
| 1355 | |||
| 1356 | /* first capture unit */ | ||
| 1357 | |||
| 1358 | #define RADEON_CAP0_BUF0_OFFSET 0x0920 | ||
| 1359 | #define RADEON_CAP0_BUF1_OFFSET 0x0924 | ||
| 1360 | #define RADEON_CAP0_BUF0_EVEN_OFFSET 0x0928 | ||
| 1361 | #define RADEON_CAP0_BUF1_EVEN_OFFSET 0x092C | ||
| 1362 | |||
| 1363 | #define RADEON_CAP0_BUF_PITCH 0x0930 | ||
| 1364 | #define RADEON_CAP0_V_WINDOW 0x0934 | ||
| 1365 | #define RADEON_CAP0_H_WINDOW 0x0938 | ||
| 1366 | #define RADEON_CAP0_VBI0_OFFSET 0x093C | ||
| 1367 | #define RADEON_CAP0_VBI1_OFFSET 0x0940 | ||
| 1368 | #define RADEON_CAP0_VBI_V_WINDOW 0x0944 | ||
| 1369 | #define RADEON_CAP0_VBI_H_WINDOW 0x0948 | ||
| 1370 | #define RADEON_CAP0_PORT_MODE_CNTL 0x094C | ||
| 1371 | #define RADEON_CAP0_TRIG_CNTL 0x0950 | ||
| 1372 | #define RADEON_CAP0_DEBUG 0x0954 | ||
| 1373 | #define RADEON_CAP0_CONFIG 0x0958 | ||
| 1374 | # define RADEON_CAP0_CONFIG_CONTINUOS 0x00000001 | ||
| 1375 | # define RADEON_CAP0_CONFIG_START_FIELD_EVEN 0x00000002 | ||
| 1376 | # define RADEON_CAP0_CONFIG_START_BUF_GET 0x00000004 | ||
| 1377 | # define RADEON_CAP0_CONFIG_START_BUF_SET 0x00000008 | ||
| 1378 | # define RADEON_CAP0_CONFIG_BUF_TYPE_ALT 0x00000010 | ||
| 1379 | # define RADEON_CAP0_CONFIG_BUF_TYPE_FRAME 0x00000020 | ||
| 1380 | # define RADEON_CAP0_CONFIG_ONESHOT_MODE_FRAME 0x00000040 | ||
| 1381 | # define RADEON_CAP0_CONFIG_BUF_MODE_DOUBLE 0x00000080 | ||
| 1382 | # define RADEON_CAP0_CONFIG_BUF_MODE_TRIPLE 0x00000100 | ||
| 1383 | # define RADEON_CAP0_CONFIG_MIRROR_EN 0x00000200 | ||
| 1384 | # define RADEON_CAP0_CONFIG_ONESHOT_MIRROR_EN 0x00000400 | ||
| 1385 | # define RADEON_CAP0_CONFIG_VIDEO_SIGNED_UV 0x00000800 | ||
| 1386 | # define RADEON_CAP0_CONFIG_ANC_DECODE_EN 0x00001000 | ||
| 1387 | # define RADEON_CAP0_CONFIG_VBI_EN 0x00002000 | ||
| 1388 | # define RADEON_CAP0_CONFIG_SOFT_PULL_DOWN_EN 0x00004000 | ||
| 1389 | # define RADEON_CAP0_CONFIG_VIP_EXTEND_FLAG_EN 0x00008000 | ||
| 1390 | # define RADEON_CAP0_CONFIG_FAKE_FIELD_EN 0x00010000 | ||
| 1391 | # define RADEON_CAP0_CONFIG_ODD_ONE_MORE_LINE 0x00020000 | ||
| 1392 | # define RADEON_CAP0_CONFIG_EVEN_ONE_MORE_LINE 0x00040000 | ||
| 1393 | # define RADEON_CAP0_CONFIG_HORZ_DIVIDE_2 0x00080000 | ||
| 1394 | # define RADEON_CAP0_CONFIG_HORZ_DIVIDE_4 0x00100000 | ||
| 1395 | # define RADEON_CAP0_CONFIG_VERT_DIVIDE_2 0x00200000 | ||
| 1396 | # define RADEON_CAP0_CONFIG_VERT_DIVIDE_4 0x00400000 | ||
| 1397 | # define RADEON_CAP0_CONFIG_FORMAT_BROOKTREE 0x00000000 | ||
| 1398 | # define RADEON_CAP0_CONFIG_FORMAT_CCIR656 0x00800000 | ||
| 1399 | # define RADEON_CAP0_CONFIG_FORMAT_ZV 0x01000000 | ||
| 1400 | # define RADEON_CAP0_CONFIG_FORMAT_VIP 0x01800000 | ||
| 1401 | # define RADEON_CAP0_CONFIG_FORMAT_TRANSPORT 0x02000000 | ||
| 1402 | # define RADEON_CAP0_CONFIG_HORZ_DECIMATOR 0x04000000 | ||
| 1403 | # define RADEON_CAP0_CONFIG_VIDEO_IN_YVYU422 0x00000000 | ||
| 1404 | # define RADEON_CAP0_CONFIG_VIDEO_IN_VYUY422 0x20000000 | ||
| 1405 | # define RADEON_CAP0_CONFIG_VBI_DIVIDE_2 0x40000000 | ||
| 1406 | # define RADEON_CAP0_CONFIG_VBI_DIVIDE_4 0x80000000 | ||
| 1407 | #define RADEON_CAP0_ANC_ODD_OFFSET 0x095C | ||
| 1408 | #define RADEON_CAP0_ANC_EVEN_OFFSET 0x0960 | ||
| 1409 | #define RADEON_CAP0_ANC_H_WINDOW 0x0964 | ||
| 1410 | #define RADEON_CAP0_VIDEO_SYNC_TEST 0x0968 | ||
| 1411 | #define RADEON_CAP0_ONESHOT_BUF_OFFSET 0x096C | ||
| 1412 | #define RADEON_CAP0_BUF_STATUS 0x0970 | ||
| 1413 | /* #define RADEON_CAP0_DWNSC_XRATIO 0x0978 */ | ||
| 1414 | /* #define RADEON_CAP0_XSHARPNESS 0x097C */ | ||
| 1415 | #define RADEON_CAP0_VBI2_OFFSET 0x0980 | ||
| 1416 | #define RADEON_CAP0_VBI3_OFFSET 0x0984 | ||
| 1417 | #define RADEON_CAP0_ANC2_OFFSET 0x0988 | ||
| 1418 | #define RADEON_CAP0_ANC3_OFFSET 0x098C | ||
| 1419 | #define RADEON_VID_BUFFER_CONTROL 0x0900 | ||
| 1420 | |||
| 1421 | /* second capture unit */ | ||
| 1422 | |||
| 1423 | #define RADEON_CAP1_BUF0_OFFSET 0x0990 | ||
| 1424 | #define RADEON_CAP1_BUF1_OFFSET 0x0994 | ||
| 1425 | #define RADEON_CAP1_BUF0_EVEN_OFFSET 0x0998 | ||
| 1426 | #define RADEON_CAP1_BUF1_EVEN_OFFSET 0x099C | ||
| 1427 | |||
| 1428 | #define RADEON_CAP1_BUF_PITCH 0x09A0 | ||
| 1429 | #define RADEON_CAP1_V_WINDOW 0x09A4 | ||
| 1430 | #define RADEON_CAP1_H_WINDOW 0x09A8 | ||
| 1431 | #define RADEON_CAP1_VBI_ODD_OFFSET 0x09AC | ||
| 1432 | #define RADEON_CAP1_VBI_EVEN_OFFSET 0x09B0 | ||
| 1433 | #define RADEON_CAP1_VBI_V_WINDOW 0x09B4 | ||
| 1434 | #define RADEON_CAP1_VBI_H_WINDOW 0x09B8 | ||
| 1435 | #define RADEON_CAP1_PORT_MODE_CNTL 0x09BC | ||
| 1436 | #define RADEON_CAP1_TRIG_CNTL 0x09C0 | ||
| 1437 | #define RADEON_CAP1_DEBUG 0x09C4 | ||
| 1438 | #define RADEON_CAP1_CONFIG 0x09C8 | ||
| 1439 | #define RADEON_CAP1_ANC_ODD_OFFSET 0x09CC | ||
| 1440 | #define RADEON_CAP1_ANC_EVEN_OFFSET 0x09D0 | ||
| 1441 | #define RADEON_CAP1_ANC_H_WINDOW 0x09D4 | ||
| 1442 | #define RADEON_CAP1_VIDEO_SYNC_TEST 0x09D8 | ||
| 1443 | #define RADEON_CAP1_ONESHOT_BUF_OFFSET 0x09DC | ||
| 1444 | #define RADEON_CAP1_BUF_STATUS 0x09E0 | ||
| 1445 | #define RADEON_CAP1_DWNSC_XRATIO 0x09E8 | ||
| 1446 | #define RADEON_CAP1_XSHARPNESS 0x09EC | ||
| 1447 | |||
| 1448 | /* misc multimedia registers */ | ||
| 1449 | |||
| 1450 | #define RADEON_IDCT_RUNS 0x1F80 | ||
| 1451 | #define RADEON_IDCT_LEVELS 0x1F84 | ||
| 1452 | #define RADEON_IDCT_CONTROL 0x1FBC | ||
| 1453 | #define RADEON_IDCT_AUTH_CONTROL 0x1F88 | ||
| 1454 | #define RADEON_IDCT_AUTH 0x1F8C | ||
| 1455 | |||
| 1456 | #define RADEON_P2PLL_CNTL 0x002a /* P2PLL */ | ||
| 1457 | # define RADEON_P2PLL_RESET (1 << 0) | ||
| 1458 | # define RADEON_P2PLL_SLEEP (1 << 1) | ||
| 1459 | # define RADEON_P2PLL_PVG_MASK (7 << 11) | ||
| 1460 | # define RADEON_P2PLL_PVG_SHIFT 11 | ||
| 1461 | # define RADEON_P2PLL_ATOMIC_UPDATE_EN (1 << 16) | ||
| 1462 | # define RADEON_P2PLL_VGA_ATOMIC_UPDATE_EN (1 << 17) | ||
| 1463 | # define RADEON_P2PLL_ATOMIC_UPDATE_VSYNC (1 << 18) | ||
| 1464 | #define RADEON_P2PLL_DIV_0 0x002c | ||
| 1465 | # define RADEON_P2PLL_FB0_DIV_MASK 0x07ff | ||
| 1466 | # define RADEON_P2PLL_POST0_DIV_MASK 0x00070000 | ||
| 1467 | #define RADEON_P2PLL_REF_DIV 0x002B /* PLL */ | ||
| 1468 | # define RADEON_P2PLL_REF_DIV_MASK 0x03ff | ||
| 1469 | # define RADEON_P2PLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */ | ||
| 1470 | # define RADEON_P2PLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */ | ||
| 1471 | # define R300_PPLL_REF_DIV_ACC_MASK (0x3ff << 18) | ||
| 1472 | # define R300_PPLL_REF_DIV_ACC_SHIFT 18 | ||
| 1473 | #define RADEON_PALETTE_DATA 0x00b4 | ||
| 1474 | #define RADEON_PALETTE_30_DATA 0x00b8 | ||
| 1475 | #define RADEON_PALETTE_INDEX 0x00b0 | ||
| 1476 | #define RADEON_PCI_GART_PAGE 0x017c | ||
| 1477 | #define RADEON_PIXCLKS_CNTL 0x002d | ||
| 1478 | # define RADEON_PIX2CLK_SRC_SEL_MASK 0x03 | ||
| 1479 | # define RADEON_PIX2CLK_SRC_SEL_CPUCLK 0x00 | ||
| 1480 | # define RADEON_PIX2CLK_SRC_SEL_PSCANCLK 0x01 | ||
| 1481 | # define RADEON_PIX2CLK_SRC_SEL_BYTECLK 0x02 | ||
| 1482 | # define RADEON_PIX2CLK_SRC_SEL_P2PLLCLK 0x03 | ||
| 1483 | # define RADEON_PIX2CLK_ALWAYS_ONb (1<<6) | ||
| 1484 | # define RADEON_PIX2CLK_DAC_ALWAYS_ONb (1<<7) | ||
| 1485 | # define RADEON_PIXCLK_TV_SRC_SEL (1 << 8) | ||
| 1486 | # define RADEON_DISP_TVOUT_PIXCLK_TV_ALWAYS_ONb (1 << 9) | ||
| 1487 | # define R300_DVOCLK_ALWAYS_ONb (1 << 10) | ||
| 1488 | # define RADEON_PIXCLK_BLEND_ALWAYS_ONb (1 << 11) | ||
| 1489 | # define RADEON_PIXCLK_GV_ALWAYS_ONb (1 << 12) | ||
| 1490 | # define RADEON_PIXCLK_DIG_TMDS_ALWAYS_ONb (1 << 13) | ||
| 1491 | # define R300_PIXCLK_DVO_ALWAYS_ONb (1 << 13) | ||
| 1492 | # define RADEON_PIXCLK_LVDS_ALWAYS_ONb (1 << 14) | ||
| 1493 | # define RADEON_PIXCLK_TMDS_ALWAYS_ONb (1 << 15) | ||
| 1494 | # define R300_PIXCLK_TRANS_ALWAYS_ONb (1 << 16) | ||
| 1495 | # define R300_PIXCLK_TVO_ALWAYS_ONb (1 << 17) | ||
| 1496 | # define R300_P2G2CLK_ALWAYS_ONb (1 << 18) | ||
| 1497 | # define R300_P2G2CLK_DAC_ALWAYS_ONb (1 << 19) | ||
| 1498 | # define R300_DISP_DAC_PIXCLK_DAC2_BLANK_OFF (1 << 23) | ||
| 1499 | #define RADEON_PLANE_3D_MASK_C 0x1d44 | ||
| 1500 | #define RADEON_PLL_TEST_CNTL 0x0013 /* PLL */ | ||
| 1501 | # define RADEON_PLL_MASK_READ_B (1 << 9) | ||
| 1502 | #define RADEON_PMI_CAP_ID 0x0f5c /* PCI */ | ||
| 1503 | #define RADEON_PMI_DATA 0x0f63 /* PCI */ | ||
| 1504 | #define RADEON_PMI_NXT_CAP_PTR 0x0f5d /* PCI */ | ||
| 1505 | #define RADEON_PMI_PMC_REG 0x0f5e /* PCI */ | ||
| 1506 | #define RADEON_PMI_PMCSR_REG 0x0f60 /* PCI */ | ||
| 1507 | #define RADEON_PMI_REGISTER 0x0f5c /* PCI */ | ||
| 1508 | #define RADEON_PPLL_CNTL 0x0002 /* PLL */ | ||
| 1509 | # define RADEON_PPLL_RESET (1 << 0) | ||
| 1510 | # define RADEON_PPLL_SLEEP (1 << 1) | ||
| 1511 | # define RADEON_PPLL_PVG_MASK (7 << 11) | ||
| 1512 | # define RADEON_PPLL_PVG_SHIFT 11 | ||
| 1513 | # define RADEON_PPLL_ATOMIC_UPDATE_EN (1 << 16) | ||
| 1514 | # define RADEON_PPLL_VGA_ATOMIC_UPDATE_EN (1 << 17) | ||
| 1515 | # define RADEON_PPLL_ATOMIC_UPDATE_VSYNC (1 << 18) | ||
| 1516 | #define RADEON_PPLL_DIV_0 0x0004 /* PLL */ | ||
| 1517 | #define RADEON_PPLL_DIV_1 0x0005 /* PLL */ | ||
| 1518 | #define RADEON_PPLL_DIV_2 0x0006 /* PLL */ | ||
| 1519 | #define RADEON_PPLL_DIV_3 0x0007 /* PLL */ | ||
| 1520 | # define RADEON_PPLL_FB3_DIV_MASK 0x07ff | ||
| 1521 | # define RADEON_PPLL_POST3_DIV_MASK 0x00070000 | ||
| 1522 | #define RADEON_PPLL_REF_DIV 0x0003 /* PLL */ | ||
| 1523 | # define RADEON_PPLL_REF_DIV_MASK 0x03ff | ||
| 1524 | # define RADEON_PPLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */ | ||
| 1525 | # define RADEON_PPLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */ | ||
| 1526 | #define RADEON_PWR_MNGMT_CNTL_STATUS 0x0f60 /* PCI */ | ||
| 1527 | |||
| 1528 | #define RADEON_RBBM_GUICNTL 0x172c | ||
| 1529 | # define RADEON_HOST_DATA_SWAP_NONE (0 << 0) | ||
| 1530 | # define RADEON_HOST_DATA_SWAP_16BIT (1 << 0) | ||
| 1531 | # define RADEON_HOST_DATA_SWAP_32BIT (2 << 0) | ||
| 1532 | # define RADEON_HOST_DATA_SWAP_HDW (3 << 0) | ||
| 1533 | #define RADEON_RBBM_SOFT_RESET 0x00f0 | ||
| 1534 | # define RADEON_SOFT_RESET_CP (1 << 0) | ||
| 1535 | # define RADEON_SOFT_RESET_HI (1 << 1) | ||
| 1536 | # define RADEON_SOFT_RESET_SE (1 << 2) | ||
| 1537 | # define RADEON_SOFT_RESET_RE (1 << 3) | ||
| 1538 | # define RADEON_SOFT_RESET_PP (1 << 4) | ||
| 1539 | # define RADEON_SOFT_RESET_E2 (1 << 5) | ||
| 1540 | # define RADEON_SOFT_RESET_RB (1 << 6) | ||
| 1541 | # define RADEON_SOFT_RESET_HDP (1 << 7) | ||
| 1542 | #define RADEON_RBBM_STATUS 0x0e40 | ||
| 1543 | # define RADEON_RBBM_FIFOCNT_MASK 0x007f | ||
| 1544 | # define RADEON_RBBM_ACTIVE (1 << 31) | ||
| 1545 | #define RADEON_RB2D_DSTCACHE_CTLSTAT 0x342c | ||
| 1546 | # define RADEON_RB2D_DC_FLUSH (3 << 0) | ||
| 1547 | # define RADEON_RB2D_DC_FREE (3 << 2) | ||
| 1548 | # define RADEON_RB2D_DC_FLUSH_ALL 0xf | ||
| 1549 | # define RADEON_RB2D_DC_BUSY (1 << 31) | ||
| 1550 | #define RADEON_RB2D_DSTCACHE_MODE 0x3428 | ||
| 1551 | #define RADEON_DSTCACHE_CTLSTAT 0x1714 | ||
| 1552 | |||
| 1553 | #define RADEON_RB3D_ZCACHE_MODE 0x3250 | ||
| 1554 | #define RADEON_RB3D_ZCACHE_CTLSTAT 0x3254 | ||
| 1555 | # define RADEON_RB3D_ZC_FLUSH_ALL 0x5 | ||
| 1556 | #define RADEON_RB3D_DSTCACHE_MODE 0x3258 | ||
| 1557 | # define RADEON_RB3D_DC_CACHE_ENABLE (0) | ||
| 1558 | # define RADEON_RB3D_DC_2D_CACHE_DISABLE (1) | ||
| 1559 | # define RADEON_RB3D_DC_3D_CACHE_DISABLE (2) | ||
| 1560 | # define RADEON_RB3D_DC_CACHE_DISABLE (3) | ||
| 1561 | # define RADEON_RB3D_DC_2D_CACHE_LINESIZE_128 (1 << 2) | ||
| 1562 | # define RADEON_RB3D_DC_3D_CACHE_LINESIZE_128 (2 << 2) | ||
| 1563 | # define RADEON_RB3D_DC_2D_CACHE_AUTOFLUSH (1 << 8) | ||
| 1564 | # define RADEON_RB3D_DC_3D_CACHE_AUTOFLUSH (2 << 8) | ||
| 1565 | # define R200_RB3D_DC_2D_CACHE_AUTOFREE (1 << 10) | ||
| 1566 | # define R200_RB3D_DC_3D_CACHE_AUTOFREE (2 << 10) | ||
| 1567 | # define RADEON_RB3D_DC_FORCE_RMW (1 << 16) | ||
| 1568 | # define RADEON_RB3D_DC_DISABLE_RI_FILL (1 << 24) | ||
| 1569 | # define RADEON_RB3D_DC_DISABLE_RI_READ (1 << 25) | ||
| 1570 | |||
| 1571 | #define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325C | ||
| 1572 | # define RADEON_RB3D_DC_FLUSH (3 << 0) | ||
| 1573 | # define RADEON_RB3D_DC_FREE (3 << 2) | ||
| 1574 | # define RADEON_RB3D_DC_FLUSH_ALL 0xf | ||
| 1575 | # define RADEON_RB3D_DC_BUSY (1 << 31) | ||
| 1576 | |||
| 1577 | #define RADEON_REG_BASE 0x0f18 /* PCI */ | ||
| 1578 | #define RADEON_REGPROG_INF 0x0f09 /* PCI */ | ||
| 1579 | #define RADEON_REVISION_ID 0x0f08 /* PCI */ | ||
| 1580 | |||
| 1581 | #define RADEON_SC_BOTTOM 0x164c | ||
| 1582 | #define RADEON_SC_BOTTOM_RIGHT 0x16f0 | ||
| 1583 | #define RADEON_SC_BOTTOM_RIGHT_C 0x1c8c | ||
| 1584 | #define RADEON_SC_LEFT 0x1640 | ||
| 1585 | #define RADEON_SC_RIGHT 0x1644 | ||
| 1586 | #define RADEON_SC_TOP 0x1648 | ||
| 1587 | #define RADEON_SC_TOP_LEFT 0x16ec | ||
| 1588 | #define RADEON_SC_TOP_LEFT_C 0x1c88 | ||
| 1589 | # define RADEON_SC_SIGN_MASK_LO 0x8000 | ||
| 1590 | # define RADEON_SC_SIGN_MASK_HI 0x80000000 | ||
| 1591 | #define RADEON_M_SPLL_REF_FB_DIV 0x000a /* PLL */ | ||
| 1592 | # define RADEON_M_SPLL_REF_DIV_SHIFT 0 | ||
| 1593 | # define RADEON_M_SPLL_REF_DIV_MASK 0xff | ||
| 1594 | # define RADEON_MPLL_FB_DIV_SHIFT 8 | ||
| 1595 | # define RADEON_MPLL_FB_DIV_MASK 0xff | ||
| 1596 | # define RADEON_SPLL_FB_DIV_SHIFT 16 | ||
| 1597 | # define RADEON_SPLL_FB_DIV_MASK 0xff | ||
| 1598 | #define RADEON_SPLL_CNTL 0x000c /* PLL */ | ||
| 1599 | # define RADEON_SPLL_SLEEP (1 << 0) | ||
| 1600 | # define RADEON_SPLL_RESET (1 << 1) | ||
| 1601 | # define RADEON_SPLL_PCP_MASK 0x7 | ||
| 1602 | # define RADEON_SPLL_PCP_SHIFT 8 | ||
| 1603 | # define RADEON_SPLL_PVG_MASK 0x7 | ||
| 1604 | # define RADEON_SPLL_PVG_SHIFT 11 | ||
| 1605 | # define RADEON_SPLL_PDC_MASK 0x3 | ||
| 1606 | # define RADEON_SPLL_PDC_SHIFT 14 | ||
| 1607 | #define RADEON_SCLK_CNTL 0x000d /* PLL */ | ||
| 1608 | # define RADEON_SCLK_SRC_SEL_MASK 0x0007 | ||
| 1609 | # define RADEON_DYN_STOP_LAT_MASK 0x00007ff8 | ||
| 1610 | # define RADEON_CP_MAX_DYN_STOP_LAT 0x0008 | ||
| 1611 | # define RADEON_SCLK_FORCEON_MASK 0xffff8000 | ||
| 1612 | # define RADEON_SCLK_FORCE_DISP2 (1<<15) | ||
| 1613 | # define RADEON_SCLK_FORCE_CP (1<<16) | ||
| 1614 | # define RADEON_SCLK_FORCE_HDP (1<<17) | ||
| 1615 | # define RADEON_SCLK_FORCE_DISP1 (1<<18) | ||
| 1616 | # define RADEON_SCLK_FORCE_TOP (1<<19) | ||
| 1617 | # define RADEON_SCLK_FORCE_E2 (1<<20) | ||
| 1618 | # define RADEON_SCLK_FORCE_SE (1<<21) | ||
| 1619 | # define RADEON_SCLK_FORCE_IDCT (1<<22) | ||
| 1620 | # define RADEON_SCLK_FORCE_VIP (1<<23) | ||
| 1621 | # define RADEON_SCLK_FORCE_RE (1<<24) | ||
| 1622 | # define RADEON_SCLK_FORCE_PB (1<<25) | ||
| 1623 | # define RADEON_SCLK_FORCE_TAM (1<<26) | ||
| 1624 | # define RADEON_SCLK_FORCE_TDM (1<<27) | ||
| 1625 | # define RADEON_SCLK_FORCE_RB (1<<28) | ||
| 1626 | # define RADEON_SCLK_FORCE_TV_SCLK (1<<29) | ||
| 1627 | # define RADEON_SCLK_FORCE_SUBPIC (1<<30) | ||
| 1628 | # define RADEON_SCLK_FORCE_OV0 (1<<31) | ||
| 1629 | # define R300_SCLK_FORCE_VAP (1<<21) | ||
| 1630 | # define R300_SCLK_FORCE_SR (1<<25) | ||
| 1631 | # define R300_SCLK_FORCE_PX (1<<26) | ||
| 1632 | # define R300_SCLK_FORCE_TX (1<<27) | ||
| 1633 | # define R300_SCLK_FORCE_US (1<<28) | ||
| 1634 | # define R300_SCLK_FORCE_SU (1<<30) | ||
| 1635 | #define R300_SCLK_CNTL2 0x1e /* PLL */ | ||
| 1636 | # define R300_SCLK_TCL_MAX_DYN_STOP_LAT (1<<10) | ||
| 1637 | # define R300_SCLK_GA_MAX_DYN_STOP_LAT (1<<11) | ||
| 1638 | # define R300_SCLK_CBA_MAX_DYN_STOP_LAT (1<<12) | ||
| 1639 | # define R300_SCLK_FORCE_TCL (1<<13) | ||
| 1640 | # define R300_SCLK_FORCE_CBA (1<<14) | ||
| 1641 | # define R300_SCLK_FORCE_GA (1<<15) | ||
| 1642 | #define RADEON_SCLK_MORE_CNTL 0x0035 /* PLL */ | ||
| 1643 | # define RADEON_SCLK_MORE_MAX_DYN_STOP_LAT 0x0007 | ||
| 1644 | # define RADEON_SCLK_MORE_FORCEON 0x0700 | ||
| 1645 | #define RADEON_SDRAM_MODE_REG 0x0158 | ||
| 1646 | #define RADEON_SEQ8_DATA 0x03c5 /* VGA */ | ||
| 1647 | #define RADEON_SEQ8_IDX 0x03c4 /* VGA */ | ||
| 1648 | #define RADEON_SNAPSHOT_F_COUNT 0x0244 | ||
| 1649 | #define RADEON_SNAPSHOT_VH_COUNTS 0x0240 | ||
| 1650 | #define RADEON_SNAPSHOT_VIF_COUNT 0x024c | ||
| 1651 | #define RADEON_SRC_OFFSET 0x15ac | ||
| 1652 | #define RADEON_SRC_PITCH 0x15b0 | ||
| 1653 | #define RADEON_SRC_PITCH_OFFSET 0x1428 | ||
| 1654 | #define RADEON_SRC_SC_BOTTOM 0x165c | ||
| 1655 | #define RADEON_SRC_SC_BOTTOM_RIGHT 0x16f4 | ||
| 1656 | #define RADEON_SRC_SC_RIGHT 0x1654 | ||
| 1657 | #define RADEON_SRC_X 0x1414 | ||
| 1658 | #define RADEON_SRC_X_Y 0x1590 | ||
| 1659 | #define RADEON_SRC_Y 0x1418 | ||
| 1660 | #define RADEON_SRC_Y_X 0x1434 | ||
| 1661 | #define RADEON_STATUS 0x0f06 /* PCI */ | ||
| 1662 | #define RADEON_SUBPIC_CNTL 0x0540 /* ? */ | ||
| 1663 | #define RADEON_SUB_CLASS 0x0f0a /* PCI */ | ||
| 1664 | #define RADEON_SURFACE_CNTL 0x0b00 | ||
| 1665 | # define RADEON_SURF_TRANSLATION_DIS (1 << 8) | ||
| 1666 | # define RADEON_NONSURF_AP0_SWP_16BPP (1 << 20) | ||
| 1667 | # define RADEON_NONSURF_AP0_SWP_32BPP (1 << 21) | ||
| 1668 | # define RADEON_NONSURF_AP1_SWP_16BPP (1 << 22) | ||
| 1669 | # define RADEON_NONSURF_AP1_SWP_32BPP (1 << 23) | ||
| 1670 | #define RADEON_SURFACE0_INFO 0x0b0c | ||
| 1671 | # define RADEON_SURF_TILE_COLOR_MACRO (0 << 16) | ||
| 1672 | # define RADEON_SURF_TILE_COLOR_BOTH (1 << 16) | ||
| 1673 | # define RADEON_SURF_TILE_DEPTH_32BPP (2 << 16) | ||
| 1674 | # define RADEON_SURF_TILE_DEPTH_16BPP (3 << 16) | ||
| 1675 | # define R200_SURF_TILE_NONE (0 << 16) | ||
| 1676 | # define R200_SURF_TILE_COLOR_MACRO (1 << 16) | ||
| 1677 | # define R200_SURF_TILE_COLOR_MICRO (2 << 16) | ||
| 1678 | # define R200_SURF_TILE_COLOR_BOTH (3 << 16) | ||
| 1679 | # define R200_SURF_TILE_DEPTH_32BPP (4 << 16) | ||
| 1680 | # define R200_SURF_TILE_DEPTH_16BPP (5 << 16) | ||
| 1681 | # define R300_SURF_TILE_NONE (0 << 16) | ||
| 1682 | # define R300_SURF_TILE_COLOR_MACRO (1 << 16) | ||
| 1683 | # define R300_SURF_TILE_DEPTH_32BPP (2 << 16) | ||
| 1684 | # define RADEON_SURF_AP0_SWP_16BPP (1 << 20) | ||
| 1685 | # define RADEON_SURF_AP0_SWP_32BPP (1 << 21) | ||
| 1686 | # define RADEON_SURF_AP1_SWP_16BPP (1 << 22) | ||
| 1687 | # define RADEON_SURF_AP1_SWP_32BPP (1 << 23) | ||
| 1688 | #define RADEON_SURFACE0_LOWER_BOUND 0x0b04 | ||
| 1689 | #define RADEON_SURFACE0_UPPER_BOUND 0x0b08 | ||
| 1690 | #define RADEON_SURFACE1_INFO 0x0b1c | ||
| 1691 | #define RADEON_SURFACE1_LOWER_BOUND 0x0b14 | ||
| 1692 | #define RADEON_SURFACE1_UPPER_BOUND 0x0b18 | ||
| 1693 | #define RADEON_SURFACE2_INFO 0x0b2c | ||
| 1694 | #define RADEON_SURFACE2_LOWER_BOUND 0x0b24 | ||
| 1695 | #define RADEON_SURFACE2_UPPER_BOUND 0x0b28 | ||
| 1696 | #define RADEON_SURFACE3_INFO 0x0b3c | ||
| 1697 | #define RADEON_SURFACE3_LOWER_BOUND 0x0b34 | ||
| 1698 | #define RADEON_SURFACE3_UPPER_BOUND 0x0b38 | ||
| 1699 | #define RADEON_SURFACE4_INFO 0x0b4c | ||
| 1700 | #define RADEON_SURFACE4_LOWER_BOUND 0x0b44 | ||
| 1701 | #define RADEON_SURFACE4_UPPER_BOUND 0x0b48 | ||
| 1702 | #define RADEON_SURFACE5_INFO 0x0b5c | ||
| 1703 | #define RADEON_SURFACE5_LOWER_BOUND 0x0b54 | ||
| 1704 | #define RADEON_SURFACE5_UPPER_BOUND 0x0b58 | ||
| 1705 | #define RADEON_SURFACE6_INFO 0x0b6c | ||
| 1706 | #define RADEON_SURFACE6_LOWER_BOUND 0x0b64 | ||
| 1707 | #define RADEON_SURFACE6_UPPER_BOUND 0x0b68 | ||
| 1708 | #define RADEON_SURFACE7_INFO 0x0b7c | ||
| 1709 | #define RADEON_SURFACE7_LOWER_BOUND 0x0b74 | ||
| 1710 | #define RADEON_SURFACE7_UPPER_BOUND 0x0b78 | ||
| 1711 | #define RADEON_SW_SEMAPHORE 0x013c | ||
| 1712 | |||
| 1713 | #define RADEON_TEST_DEBUG_CNTL 0x0120 | ||
| 1714 | #define RADEON_TEST_DEBUG_CNTL__TEST_DEBUG_OUT_EN 0x00000001 | ||
| 1715 | |||
| 1716 | #define RADEON_TEST_DEBUG_MUX 0x0124 | ||
| 1717 | #define RADEON_TEST_DEBUG_OUT 0x012c | ||
| 1718 | #define RADEON_TMDS_PLL_CNTL 0x02a8 | ||
| 1719 | #define RADEON_TMDS_TRANSMITTER_CNTL 0x02a4 | ||
| 1720 | # define RADEON_TMDS_TRANSMITTER_PLLEN 1 | ||
| 1721 | # define RADEON_TMDS_TRANSMITTER_PLLRST 2 | ||
| 1722 | #define RADEON_TRAIL_BRES_DEC 0x1614 | ||
| 1723 | #define RADEON_TRAIL_BRES_ERR 0x160c | ||
| 1724 | #define RADEON_TRAIL_BRES_INC 0x1610 | ||
| 1725 | #define RADEON_TRAIL_X 0x1618 | ||
| 1726 | #define RADEON_TRAIL_X_SUB 0x1620 | ||
| 1727 | |||
| 1728 | #define RADEON_VCLK_ECP_CNTL 0x0008 /* PLL */ | ||
| 1729 | # define RADEON_VCLK_SRC_SEL_MASK 0x03 | ||
| 1730 | # define RADEON_VCLK_SRC_SEL_CPUCLK 0x00 | ||
| 1731 | # define RADEON_VCLK_SRC_SEL_PSCANCLK 0x01 | ||
| 1732 | # define RADEON_VCLK_SRC_SEL_BYTECLK 0x02 | ||
| 1733 | # define RADEON_VCLK_SRC_SEL_PPLLCLK 0x03 | ||
| 1734 | # define RADEON_PIXCLK_ALWAYS_ONb (1<<6) | ||
| 1735 | # define RADEON_PIXCLK_DAC_ALWAYS_ONb (1<<7) | ||
| 1736 | # define R300_DISP_DAC_PIXCLK_DAC_BLANK_OFF (1<<23) | ||
| 1737 | |||
| 1738 | #define RADEON_VENDOR_ID 0x0f00 /* PCI */ | ||
| 1739 | #define RADEON_VGA_DDA_CONFIG 0x02e8 | ||
| 1740 | #define RADEON_VGA_DDA_ON_OFF 0x02ec | ||
| 1741 | #define RADEON_VID_BUFFER_CONTROL 0x0900 | ||
| 1742 | #define RADEON_VIDEOMUX_CNTL 0x0190 | ||
| 1743 | |||
| 1744 | /* VIP bus */ | ||
| 1745 | #define RADEON_VIPH_CH0_DATA 0x0c00 | ||
| 1746 | #define RADEON_VIPH_CH1_DATA 0x0c04 | ||
| 1747 | #define RADEON_VIPH_CH2_DATA 0x0c08 | ||
| 1748 | #define RADEON_VIPH_CH3_DATA 0x0c0c | ||
| 1749 | #define RADEON_VIPH_CH0_ADDR 0x0c10 | ||
| 1750 | #define RADEON_VIPH_CH1_ADDR 0x0c14 | ||
| 1751 | #define RADEON_VIPH_CH2_ADDR 0x0c18 | ||
| 1752 | #define RADEON_VIPH_CH3_ADDR 0x0c1c | ||
| 1753 | #define RADEON_VIPH_CH0_SBCNT 0x0c20 | ||
| 1754 | #define RADEON_VIPH_CH1_SBCNT 0x0c24 | ||
| 1755 | #define RADEON_VIPH_CH2_SBCNT 0x0c28 | ||
| 1756 | #define RADEON_VIPH_CH3_SBCNT 0x0c2c | ||
| 1757 | #define RADEON_VIPH_CH0_ABCNT 0x0c30 | ||
| 1758 | #define RADEON_VIPH_CH1_ABCNT 0x0c34 | ||
| 1759 | #define RADEON_VIPH_CH2_ABCNT 0x0c38 | ||
| 1760 | #define RADEON_VIPH_CH3_ABCNT 0x0c3c | ||
| 1761 | #define RADEON_VIPH_CONTROL 0x0c40 | ||
| 1762 | # define RADEON_VIP_BUSY 0 | ||
| 1763 | # define RADEON_VIP_IDLE 1 | ||
| 1764 | # define RADEON_VIP_RESET 2 | ||
| 1765 | # define RADEON_VIPH_EN (1 << 21) | ||
| 1766 | #define RADEON_VIPH_DV_LAT 0x0c44 | ||
| 1767 | #define RADEON_VIPH_BM_CHUNK 0x0c48 | ||
| 1768 | #define RADEON_VIPH_DV_INT 0x0c4c | ||
| 1769 | #define RADEON_VIPH_TIMEOUT_STAT 0x0c50 | ||
| 1770 | #define RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_STAT 0x00000010 | ||
| 1771 | #define RADEON_VIPH_TIMEOUT_STAT__VIPH_REG_AK 0x00000010 | ||
| 1772 | #define RADEON_VIPH_TIMEOUT_STAT__VIPH_REGR_DIS 0x01000000 | ||
| 1773 | |||
| 1774 | #define RADEON_VIPH_REG_DATA 0x0084 | ||
| 1775 | #define RADEON_VIPH_REG_ADDR 0x0080 | ||
| 1776 | |||
| 1777 | |||
| 1778 | #define RADEON_WAIT_UNTIL 0x1720 | ||
| 1779 | # define RADEON_WAIT_CRTC_PFLIP (1 << 0) | ||
| 1780 | # define RADEON_WAIT_RE_CRTC_VLINE (1 << 1) | ||
| 1781 | # define RADEON_WAIT_FE_CRTC_VLINE (1 << 2) | ||
| 1782 | # define RADEON_WAIT_CRTC_VLINE (1 << 3) | ||
| 1783 | # define RADEON_WAIT_DMA_VID_IDLE (1 << 8) | ||
| 1784 | # define RADEON_WAIT_DMA_GUI_IDLE (1 << 9) | ||
| 1785 | # define RADEON_WAIT_CMDFIFO (1 << 10) /* wait for CMDFIFO_ENTRIES */ | ||
| 1786 | # define RADEON_WAIT_OV0_FLIP (1 << 11) | ||
| 1787 | # define RADEON_WAIT_AGP_FLUSH (1 << 13) | ||
| 1788 | # define RADEON_WAIT_2D_IDLE (1 << 14) | ||
| 1789 | # define RADEON_WAIT_3D_IDLE (1 << 15) | ||
| 1790 | # define RADEON_WAIT_2D_IDLECLEAN (1 << 16) | ||
| 1791 | # define RADEON_WAIT_3D_IDLECLEAN (1 << 17) | ||
| 1792 | # define RADEON_WAIT_HOST_IDLECLEAN (1 << 18) | ||
| 1793 | # define RADEON_CMDFIFO_ENTRIES_SHIFT 10 | ||
| 1794 | # define RADEON_CMDFIFO_ENTRIES_MASK 0x7f | ||
| 1795 | # define RADEON_WAIT_VAP_IDLE (1 << 28) | ||
| 1796 | # define RADEON_WAIT_BOTH_CRTC_PFLIP (1 << 30) | ||
| 1797 | # define RADEON_ENG_DISPLAY_SELECT_CRTC0 (0 << 31) | ||
| 1798 | # define RADEON_ENG_DISPLAY_SELECT_CRTC1 (1 << 31) | ||
| 1799 | |||
| 1800 | #define RADEON_X_MPLL_REF_FB_DIV 0x000a /* PLL */ | ||
| 1801 | #define RADEON_XCLK_CNTL 0x000d /* PLL */ | ||
| 1802 | #define RADEON_XDLL_CNTL 0x000c /* PLL */ | ||
| 1803 | #define RADEON_XPLL_CNTL 0x000b /* PLL */ | ||
| 1804 | |||
| 1805 | |||
| 1806 | |||
| 1807 | /* Registers for 3D/TCL */ | ||
| 1808 | #define RADEON_PP_BORDER_COLOR_0 0x1d40 | ||
| 1809 | #define RADEON_PP_BORDER_COLOR_1 0x1d44 | ||
| 1810 | #define RADEON_PP_BORDER_COLOR_2 0x1d48 | ||
| 1811 | #define RADEON_PP_CNTL 0x1c38 | ||
| 1812 | # define RADEON_STIPPLE_ENABLE (1 << 0) | ||
| 1813 | # define RADEON_SCISSOR_ENABLE (1 << 1) | ||
| 1814 | # define RADEON_PATTERN_ENABLE (1 << 2) | ||
| 1815 | # define RADEON_SHADOW_ENABLE (1 << 3) | ||
| 1816 | # define RADEON_TEX_ENABLE_MASK (0xf << 4) | ||
| 1817 | # define RADEON_TEX_0_ENABLE (1 << 4) | ||
| 1818 | # define RADEON_TEX_1_ENABLE (1 << 5) | ||
| 1819 | # define RADEON_TEX_2_ENABLE (1 << 6) | ||
| 1820 | # define RADEON_TEX_3_ENABLE (1 << 7) | ||
| 1821 | # define RADEON_TEX_BLEND_ENABLE_MASK (0xf << 12) | ||
| 1822 | # define RADEON_TEX_BLEND_0_ENABLE (1 << 12) | ||
| 1823 | # define RADEON_TEX_BLEND_1_ENABLE (1 << 13) | ||
| 1824 | # define RADEON_TEX_BLEND_2_ENABLE (1 << 14) | ||
| 1825 | # define RADEON_TEX_BLEND_3_ENABLE (1 << 15) | ||
| 1826 | # define RADEON_PLANAR_YUV_ENABLE (1 << 20) | ||
| 1827 | # define RADEON_SPECULAR_ENABLE (1 << 21) | ||
| 1828 | # define RADEON_FOG_ENABLE (1 << 22) | ||
| 1829 | # define RADEON_ALPHA_TEST_ENABLE (1 << 23) | ||
| 1830 | # define RADEON_ANTI_ALIAS_NONE (0 << 24) | ||
| 1831 | # define RADEON_ANTI_ALIAS_LINE (1 << 24) | ||
| 1832 | # define RADEON_ANTI_ALIAS_POLY (2 << 24) | ||
| 1833 | # define RADEON_ANTI_ALIAS_LINE_POLY (3 << 24) | ||
| 1834 | # define RADEON_BUMP_MAP_ENABLE (1 << 26) | ||
| 1835 | # define RADEON_BUMPED_MAP_T0 (0 << 27) | ||
| 1836 | # define RADEON_BUMPED_MAP_T1 (1 << 27) | ||
| 1837 | # define RADEON_BUMPED_MAP_T2 (2 << 27) | ||
| 1838 | # define RADEON_TEX_3D_ENABLE_0 (1 << 29) | ||
| 1839 | # define RADEON_TEX_3D_ENABLE_1 (1 << 30) | ||
| 1840 | # define RADEON_MC_ENABLE (1 << 31) | ||
| 1841 | #define RADEON_PP_FOG_COLOR 0x1c18 | ||
| 1842 | # define RADEON_FOG_COLOR_MASK 0x00ffffff | ||
| 1843 | # define RADEON_FOG_VERTEX (0 << 24) | ||
| 1844 | # define RADEON_FOG_TABLE (1 << 24) | ||
| 1845 | # define RADEON_FOG_USE_DEPTH (0 << 25) | ||
| 1846 | # define RADEON_FOG_USE_DIFFUSE_ALPHA (2 << 25) | ||
| 1847 | # define RADEON_FOG_USE_SPEC_ALPHA (3 << 25) | ||
| 1848 | #define RADEON_PP_LUM_MATRIX 0x1d00 | ||
| 1849 | #define RADEON_PP_MISC 0x1c14 | ||
| 1850 | # define RADEON_REF_ALPHA_MASK 0x000000ff | ||
| 1851 | # define RADEON_ALPHA_TEST_FAIL (0 << 8) | ||
| 1852 | # define RADEON_ALPHA_TEST_LESS (1 << 8) | ||
| 1853 | # define RADEON_ALPHA_TEST_LEQUAL (2 << 8) | ||
| 1854 | # define RADEON_ALPHA_TEST_EQUAL (3 << 8) | ||
| 1855 | # define RADEON_ALPHA_TEST_GEQUAL (4 << 8) | ||
| 1856 | # define RADEON_ALPHA_TEST_GREATER (5 << 8) | ||
| 1857 | # define RADEON_ALPHA_TEST_NEQUAL (6 << 8) | ||
| 1858 | # define RADEON_ALPHA_TEST_PASS (7 << 8) | ||
| 1859 | # define RADEON_ALPHA_TEST_OP_MASK (7 << 8) | ||
| 1860 | # define RADEON_CHROMA_FUNC_FAIL (0 << 16) | ||
| 1861 | # define RADEON_CHROMA_FUNC_PASS (1 << 16) | ||
| 1862 | # define RADEON_CHROMA_FUNC_NEQUAL (2 << 16) | ||
| 1863 | # define RADEON_CHROMA_FUNC_EQUAL (3 << 16) | ||
| 1864 | # define RADEON_CHROMA_KEY_NEAREST (0 << 18) | ||
| 1865 | # define RADEON_CHROMA_KEY_ZERO (1 << 18) | ||
| 1866 | # define RADEON_SHADOW_ID_AUTO_INC (1 << 20) | ||
| 1867 | # define RADEON_SHADOW_FUNC_EQUAL (0 << 21) | ||
| 1868 | # define RADEON_SHADOW_FUNC_NEQUAL (1 << 21) | ||
| 1869 | # define RADEON_SHADOW_PASS_1 (0 << 22) | ||
| 1870 | # define RADEON_SHADOW_PASS_2 (1 << 22) | ||
| 1871 | # define RADEON_RIGHT_HAND_CUBE_D3D (0 << 24) | ||
| 1872 | # define RADEON_RIGHT_HAND_CUBE_OGL (1 << 24) | ||
| 1873 | #define RADEON_PP_ROT_MATRIX_0 0x1d58 | ||
| 1874 | #define RADEON_PP_ROT_MATRIX_1 0x1d5c | ||
| 1875 | #define RADEON_PP_TXFILTER_0 0x1c54 | ||
| 1876 | #define RADEON_PP_TXFILTER_1 0x1c6c | ||
| 1877 | #define RADEON_PP_TXFILTER_2 0x1c84 | ||
| 1878 | # define RADEON_MAG_FILTER_NEAREST (0 << 0) | ||
| 1879 | # define RADEON_MAG_FILTER_LINEAR (1 << 0) | ||
| 1880 | # define RADEON_MAG_FILTER_MASK (1 << 0) | ||
| 1881 | # define RADEON_MIN_FILTER_NEAREST (0 << 1) | ||
| 1882 | # define RADEON_MIN_FILTER_LINEAR (1 << 1) | ||
| 1883 | # define RADEON_MIN_FILTER_NEAREST_MIP_NEAREST (2 << 1) | ||
| 1884 | # define RADEON_MIN_FILTER_NEAREST_MIP_LINEAR (3 << 1) | ||
| 1885 | # define RADEON_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 1) | ||
| 1886 | # define RADEON_MIN_FILTER_LINEAR_MIP_LINEAR (7 << 1) | ||
| 1887 | # define RADEON_MIN_FILTER_ANISO_NEAREST (8 << 1) | ||
| 1888 | # define RADEON_MIN_FILTER_ANISO_LINEAR (9 << 1) | ||
| 1889 | # define RADEON_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (10 << 1) | ||
| 1890 | # define RADEON_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (11 << 1) | ||
| 1891 | # define RADEON_MIN_FILTER_MASK (15 << 1) | ||
| 1892 | # define RADEON_MAX_ANISO_1_TO_1 (0 << 5) | ||
| 1893 | # define RADEON_MAX_ANISO_2_TO_1 (1 << 5) | ||
| 1894 | # define RADEON_MAX_ANISO_4_TO_1 (2 << 5) | ||
| 1895 | # define RADEON_MAX_ANISO_8_TO_1 (3 << 5) | ||
| 1896 | # define RADEON_MAX_ANISO_16_TO_1 (4 << 5) | ||
| 1897 | # define RADEON_MAX_ANISO_MASK (7 << 5) | ||
| 1898 | # define RADEON_LOD_BIAS_MASK (0xff << 8) | ||
| 1899 | # define RADEON_LOD_BIAS_SHIFT 8 | ||
| 1900 | # define RADEON_MAX_MIP_LEVEL_MASK (0x0f << 16) | ||
| 1901 | # define RADEON_MAX_MIP_LEVEL_SHIFT 16 | ||
| 1902 | # define RADEON_YUV_TO_RGB (1 << 20) | ||
| 1903 | # define RADEON_YUV_TEMPERATURE_COOL (0 << 21) | ||
| 1904 | # define RADEON_YUV_TEMPERATURE_HOT (1 << 21) | ||
| 1905 | # define RADEON_YUV_TEMPERATURE_MASK (1 << 21) | ||
| 1906 | # define RADEON_WRAPEN_S (1 << 22) | ||
| 1907 | # define RADEON_CLAMP_S_WRAP (0 << 23) | ||
| 1908 | # define RADEON_CLAMP_S_MIRROR (1 << 23) | ||
| 1909 | # define RADEON_CLAMP_S_CLAMP_LAST (2 << 23) | ||
| 1910 | # define RADEON_CLAMP_S_MIRROR_CLAMP_LAST (3 << 23) | ||
| 1911 | # define RADEON_CLAMP_S_CLAMP_BORDER (4 << 23) | ||
| 1912 | # define RADEON_CLAMP_S_MIRROR_CLAMP_BORDER (5 << 23) | ||
| 1913 | # define RADEON_CLAMP_S_CLAMP_GL (6 << 23) | ||
| 1914 | # define RADEON_CLAMP_S_MIRROR_CLAMP_GL (7 << 23) | ||
| 1915 | # define RADEON_CLAMP_S_MASK (7 << 23) | ||
| 1916 | # define RADEON_WRAPEN_T (1 << 26) | ||
| 1917 | # define RADEON_CLAMP_T_WRAP (0 << 27) | ||
| 1918 | # define RADEON_CLAMP_T_MIRROR (1 << 27) | ||
| 1919 | # define RADEON_CLAMP_T_CLAMP_LAST (2 << 27) | ||
| 1920 | # define RADEON_CLAMP_T_MIRROR_CLAMP_LAST (3 << 27) | ||
| 1921 | # define RADEON_CLAMP_T_CLAMP_BORDER (4 << 27) | ||
| 1922 | # define RADEON_CLAMP_T_MIRROR_CLAMP_BORDER (5 << 27) | ||
| 1923 | # define RADEON_CLAMP_T_CLAMP_GL (6 << 27) | ||
| 1924 | # define RADEON_CLAMP_T_MIRROR_CLAMP_GL (7 << 27) | ||
| 1925 | # define RADEON_CLAMP_T_MASK (7 << 27) | ||
| 1926 | # define RADEON_BORDER_MODE_OGL (0 << 31) | ||
| 1927 | # define RADEON_BORDER_MODE_D3D (1 << 31) | ||
| 1928 | #define RADEON_PP_TXFORMAT_0 0x1c58 | ||
| 1929 | #define RADEON_PP_TXFORMAT_1 0x1c70 | ||
| 1930 | #define RADEON_PP_TXFORMAT_2 0x1c88 | ||
| 1931 | # define RADEON_TXFORMAT_I8 (0 << 0) | ||
| 1932 | # define RADEON_TXFORMAT_AI88 (1 << 0) | ||
| 1933 | # define RADEON_TXFORMAT_RGB332 (2 << 0) | ||
| 1934 | # define RADEON_TXFORMAT_ARGB1555 (3 << 0) | ||
| 1935 | # define RADEON_TXFORMAT_RGB565 (4 << 0) | ||
| 1936 | # define RADEON_TXFORMAT_ARGB4444 (5 << 0) | ||
| 1937 | # define RADEON_TXFORMAT_ARGB8888 (6 << 0) | ||
| 1938 | # define RADEON_TXFORMAT_RGBA8888 (7 << 0) | ||
| 1939 | # define RADEON_TXFORMAT_Y8 (8 << 0) | ||
| 1940 | # define RADEON_TXFORMAT_VYUY422 (10 << 0) | ||
| 1941 | # define RADEON_TXFORMAT_YVYU422 (11 << 0) | ||
| 1942 | # define RADEON_TXFORMAT_DXT1 (12 << 0) | ||
| 1943 | # define RADEON_TXFORMAT_DXT23 (14 << 0) | ||
| 1944 | # define RADEON_TXFORMAT_DXT45 (15 << 0) | ||
| 1945 | # define RADEON_TXFORMAT_FORMAT_MASK (31 << 0) | ||
| 1946 | # define RADEON_TXFORMAT_FORMAT_SHIFT 0 | ||
| 1947 | # define RADEON_TXFORMAT_APPLE_YUV_MODE (1 << 5) | ||
| 1948 | # define RADEON_TXFORMAT_ALPHA_IN_MAP (1 << 6) | ||
| 1949 | # define RADEON_TXFORMAT_NON_POWER2 (1 << 7) | ||
| 1950 | # define RADEON_TXFORMAT_WIDTH_MASK (15 << 8) | ||
| 1951 | # define RADEON_TXFORMAT_WIDTH_SHIFT 8 | ||
| 1952 | # define RADEON_TXFORMAT_HEIGHT_MASK (15 << 12) | ||
| 1953 | # define RADEON_TXFORMAT_HEIGHT_SHIFT 12 | ||
| 1954 | # define RADEON_TXFORMAT_F5_WIDTH_MASK (15 << 16) | ||
| 1955 | # define RADEON_TXFORMAT_F5_WIDTH_SHIFT 16 | ||
| 1956 | # define RADEON_TXFORMAT_F5_HEIGHT_MASK (15 << 20) | ||
| 1957 | # define RADEON_TXFORMAT_F5_HEIGHT_SHIFT 20 | ||
| 1958 | # define RADEON_TXFORMAT_ST_ROUTE_STQ0 (0 << 24) | ||
| 1959 | # define RADEON_TXFORMAT_ST_ROUTE_MASK (3 << 24) | ||
| 1960 | # define RADEON_TXFORMAT_ST_ROUTE_STQ1 (1 << 24) | ||
| 1961 | # define RADEON_TXFORMAT_ST_ROUTE_STQ2 (2 << 24) | ||
| 1962 | # define RADEON_TXFORMAT_ENDIAN_NO_SWAP (0 << 26) | ||
| 1963 | # define RADEON_TXFORMAT_ENDIAN_16BPP_SWAP (1 << 26) | ||
| 1964 | # define RADEON_TXFORMAT_ENDIAN_32BPP_SWAP (2 << 26) | ||
| 1965 | # define RADEON_TXFORMAT_ENDIAN_HALFDW_SWAP (3 << 26) | ||
| 1966 | # define RADEON_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28) | ||
| 1967 | # define RADEON_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29) | ||
| 1968 | # define RADEON_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30) | ||
| 1969 | # define RADEON_TXFORMAT_PERSPECTIVE_ENABLE (1 << 31) | ||
| 1970 | #define RADEON_PP_CUBIC_FACES_0 0x1d24 | ||
| 1971 | #define RADEON_PP_CUBIC_FACES_1 0x1d28 | ||
| 1972 | #define RADEON_PP_CUBIC_FACES_2 0x1d2c | ||
| 1973 | # define RADEON_FACE_WIDTH_1_SHIFT 0 | ||
| 1974 | # define RADEON_FACE_HEIGHT_1_SHIFT 4 | ||
| 1975 | # define RADEON_FACE_WIDTH_1_MASK (0xf << 0) | ||
| 1976 | # define RADEON_FACE_HEIGHT_1_MASK (0xf << 4) | ||
| 1977 | # define RADEON_FACE_WIDTH_2_SHIFT 8 | ||
| 1978 | # define RADEON_FACE_HEIGHT_2_SHIFT 12 | ||
| 1979 | # define RADEON_FACE_WIDTH_2_MASK (0xf << 8) | ||
| 1980 | # define RADEON_FACE_HEIGHT_2_MASK (0xf << 12) | ||
| 1981 | # define RADEON_FACE_WIDTH_3_SHIFT 16 | ||
| 1982 | # define RADEON_FACE_HEIGHT_3_SHIFT 20 | ||
| 1983 | # define RADEON_FACE_WIDTH_3_MASK (0xf << 16) | ||
| 1984 | # define RADEON_FACE_HEIGHT_3_MASK (0xf << 20) | ||
| 1985 | # define RADEON_FACE_WIDTH_4_SHIFT 24 | ||
| 1986 | # define RADEON_FACE_HEIGHT_4_SHIFT 28 | ||
| 1987 | # define RADEON_FACE_WIDTH_4_MASK (0xf << 24) | ||
| 1988 | # define RADEON_FACE_HEIGHT_4_MASK (0xf << 28) | ||
| 1989 | |||
| 1990 | #define RADEON_PP_TXOFFSET_0 0x1c5c | ||
| 1991 | #define RADEON_PP_TXOFFSET_1 0x1c74 | ||
| 1992 | #define RADEON_PP_TXOFFSET_2 0x1c8c | ||
| 1993 | # define RADEON_TXO_ENDIAN_NO_SWAP (0 << 0) | ||
| 1994 | # define RADEON_TXO_ENDIAN_BYTE_SWAP (1 << 0) | ||
| 1995 | # define RADEON_TXO_ENDIAN_WORD_SWAP (2 << 0) | ||
| 1996 | # define RADEON_TXO_ENDIAN_HALFDW_SWAP (3 << 0) | ||
| 1997 | # define RADEON_TXO_MACRO_LINEAR (0 << 2) | ||
| 1998 | # define RADEON_TXO_MACRO_TILE (1 << 2) | ||
| 1999 | # define RADEON_TXO_MICRO_LINEAR (0 << 3) | ||
| 2000 | # define RADEON_TXO_MICRO_TILE_X2 (1 << 3) | ||
| 2001 | # define RADEON_TXO_MICRO_TILE_OPT (2 << 3) | ||
| 2002 | # define RADEON_TXO_OFFSET_MASK 0xffffffe0 | ||
| 2003 | # define RADEON_TXO_OFFSET_SHIFT 5 | ||
| 2004 | |||
| 2005 | #define RADEON_PP_CUBIC_OFFSET_T0_0 0x1dd0 /* bits [31:5] */ | ||
| 2006 | #define RADEON_PP_CUBIC_OFFSET_T0_1 0x1dd4 | ||
| 2007 | #define RADEON_PP_CUBIC_OFFSET_T0_2 0x1dd8 | ||
| 2008 | #define RADEON_PP_CUBIC_OFFSET_T0_3 0x1ddc | ||
| 2009 | #define RADEON_PP_CUBIC_OFFSET_T0_4 0x1de0 | ||
| 2010 | #define RADEON_PP_CUBIC_OFFSET_T1_0 0x1e00 | ||
| 2011 | #define RADEON_PP_CUBIC_OFFSET_T1_1 0x1e04 | ||
| 2012 | #define RADEON_PP_CUBIC_OFFSET_T1_2 0x1e08 | ||
| 2013 | #define RADEON_PP_CUBIC_OFFSET_T1_3 0x1e0c | ||
| 2014 | #define RADEON_PP_CUBIC_OFFSET_T1_4 0x1e10 | ||
| 2015 | #define RADEON_PP_CUBIC_OFFSET_T2_0 0x1e14 | ||
| 2016 | #define RADEON_PP_CUBIC_OFFSET_T2_1 0x1e18 | ||
| 2017 | #define RADEON_PP_CUBIC_OFFSET_T2_2 0x1e1c | ||
| 2018 | #define RADEON_PP_CUBIC_OFFSET_T2_3 0x1e20 | ||
| 2019 | #define RADEON_PP_CUBIC_OFFSET_T2_4 0x1e24 | ||
| 2020 | |||
| 2021 | #define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */ | ||
| 2022 | #define RADEON_PP_TEX_SIZE_1 0x1d0c | ||
| 2023 | #define RADEON_PP_TEX_SIZE_2 0x1d14 | ||
| 2024 | # define RADEON_TEX_USIZE_MASK (0x7ff << 0) | ||
| 2025 | # define RADEON_TEX_USIZE_SHIFT 0 | ||
| 2026 | # define RADEON_TEX_VSIZE_MASK (0x7ff << 16) | ||
| 2027 | # define RADEON_TEX_VSIZE_SHIFT 16 | ||
| 2028 | # define RADEON_SIGNED_RGB_MASK (1 << 30) | ||
| 2029 | # define RADEON_SIGNED_RGB_SHIFT 30 | ||
| 2030 | # define RADEON_SIGNED_ALPHA_MASK (1 << 31) | ||
| 2031 | # define RADEON_SIGNED_ALPHA_SHIFT 31 | ||
| 2032 | #define RADEON_PP_TEX_PITCH_0 0x1d08 /* NPOT */ | ||
| 2033 | #define RADEON_PP_TEX_PITCH_1 0x1d10 /* NPOT */ | ||
| 2034 | #define RADEON_PP_TEX_PITCH_2 0x1d18 /* NPOT */ | ||
| 2035 | /* note: bits 13-5: 32 byte aligned stride of texture map */ | ||
| 2036 | |||
| 2037 | #define RADEON_PP_TXCBLEND_0 0x1c60 | ||
| 2038 | #define RADEON_PP_TXCBLEND_1 0x1c78 | ||
| 2039 | #define RADEON_PP_TXCBLEND_2 0x1c90 | ||
| 2040 | # define RADEON_COLOR_ARG_A_SHIFT 0 | ||
| 2041 | # define RADEON_COLOR_ARG_A_MASK (0x1f << 0) | ||
| 2042 | # define RADEON_COLOR_ARG_A_ZERO (0 << 0) | ||
| 2043 | # define RADEON_COLOR_ARG_A_CURRENT_COLOR (2 << 0) | ||
| 2044 | # define RADEON_COLOR_ARG_A_CURRENT_ALPHA (3 << 0) | ||
| 2045 | # define RADEON_COLOR_ARG_A_DIFFUSE_COLOR (4 << 0) | ||
| 2046 | # define RADEON_COLOR_ARG_A_DIFFUSE_ALPHA (5 << 0) | ||
| 2047 | # define RADEON_COLOR_ARG_A_SPECULAR_COLOR (6 << 0) | ||
| 2048 | # define RADEON_COLOR_ARG_A_SPECULAR_ALPHA (7 << 0) | ||
| 2049 | # define RADEON_COLOR_ARG_A_TFACTOR_COLOR (8 << 0) | ||
| 2050 | # define RADEON_COLOR_ARG_A_TFACTOR_ALPHA (9 << 0) | ||
| 2051 | # define RADEON_COLOR_ARG_A_T0_COLOR (10 << 0) | ||
| 2052 | # define RADEON_COLOR_ARG_A_T0_ALPHA (11 << 0) | ||
| 2053 | # define RADEON_COLOR_ARG_A_T1_COLOR (12 << 0) | ||
| 2054 | # define RADEON_COLOR_ARG_A_T1_ALPHA (13 << 0) | ||
| 2055 | # define RADEON_COLOR_ARG_A_T2_COLOR (14 << 0) | ||
| 2056 | # define RADEON_COLOR_ARG_A_T2_ALPHA (15 << 0) | ||
| 2057 | # define RADEON_COLOR_ARG_A_T3_COLOR (16 << 0) | ||
| 2058 | # define RADEON_COLOR_ARG_A_T3_ALPHA (17 << 0) | ||
| 2059 | # define RADEON_COLOR_ARG_B_SHIFT 5 | ||
| 2060 | # define RADEON_COLOR_ARG_B_MASK (0x1f << 5) | ||
| 2061 | # define RADEON_COLOR_ARG_B_ZERO (0 << 5) | ||
| 2062 | # define RADEON_COLOR_ARG_B_CURRENT_COLOR (2 << 5) | ||
| 2063 | # define RADEON_COLOR_ARG_B_CURRENT_ALPHA (3 << 5) | ||
| 2064 | # define RADEON_COLOR_ARG_B_DIFFUSE_COLOR (4 << 5) | ||
| 2065 | # define RADEON_COLOR_ARG_B_DIFFUSE_ALPHA (5 << 5) | ||
| 2066 | # define RADEON_COLOR_ARG_B_SPECULAR_COLOR (6 << 5) | ||
| 2067 | # define RADEON_COLOR_ARG_B_SPECULAR_ALPHA (7 << 5) | ||
| 2068 | # define RADEON_COLOR_ARG_B_TFACTOR_COLOR (8 << 5) | ||
| 2069 | # define RADEON_COLOR_ARG_B_TFACTOR_ALPHA (9 << 5) | ||
| 2070 | # define RADEON_COLOR_ARG_B_T0_COLOR (10 << 5) | ||
| 2071 | # define RADEON_COLOR_ARG_B_T0_ALPHA (11 << 5) | ||
| 2072 | # define RADEON_COLOR_ARG_B_T1_COLOR (12 << 5) | ||
| 2073 | # define RADEON_COLOR_ARG_B_T1_ALPHA (13 << 5) | ||
| 2074 | # define RADEON_COLOR_ARG_B_T2_COLOR (14 << 5) | ||
| 2075 | # define RADEON_COLOR_ARG_B_T2_ALPHA (15 << 5) | ||
| 2076 | # define RADEON_COLOR_ARG_B_T3_COLOR (16 << 5) | ||
| 2077 | # define RADEON_COLOR_ARG_B_T3_ALPHA (17 << 5) | ||
| 2078 | # define RADEON_COLOR_ARG_C_SHIFT 10 | ||
| 2079 | # define RADEON_COLOR_ARG_C_MASK (0x1f << 10) | ||
| 2080 | # define RADEON_COLOR_ARG_C_ZERO (0 << 10) | ||
| 2081 | # define RADEON_COLOR_ARG_C_CURRENT_COLOR (2 << 10) | ||
| 2082 | # define RADEON_COLOR_ARG_C_CURRENT_ALPHA (3 << 10) | ||
| 2083 | # define RADEON_COLOR_ARG_C_DIFFUSE_COLOR (4 << 10) | ||
| 2084 | # define RADEON_COLOR_ARG_C_DIFFUSE_ALPHA (5 << 10) | ||
| 2085 | # define RADEON_COLOR_ARG_C_SPECULAR_COLOR (6 << 10) | ||
| 2086 | # define RADEON_COLOR_ARG_C_SPECULAR_ALPHA (7 << 10) | ||
| 2087 | # define RADEON_COLOR_ARG_C_TFACTOR_COLOR (8 << 10) | ||
| 2088 | # define RADEON_COLOR_ARG_C_TFACTOR_ALPHA (9 << 10) | ||
| 2089 | # define RADEON_COLOR_ARG_C_T0_COLOR (10 << 10) | ||
| 2090 | # define RADEON_COLOR_ARG_C_T0_ALPHA (11 << 10) | ||
| 2091 | # define RADEON_COLOR_ARG_C_T1_COLOR (12 << 10) | ||
| 2092 | # define RADEON_COLOR_ARG_C_T1_ALPHA (13 << 10) | ||
| 2093 | # define RADEON_COLOR_ARG_C_T2_COLOR (14 << 10) | ||
| 2094 | # define RADEON_COLOR_ARG_C_T2_ALPHA (15 << 10) | ||
| 2095 | # define RADEON_COLOR_ARG_C_T3_COLOR (16 << 10) | ||
| 2096 | # define RADEON_COLOR_ARG_C_T3_ALPHA (17 << 10) | ||
| 2097 | # define RADEON_COMP_ARG_A (1 << 15) | ||
| 2098 | # define RADEON_COMP_ARG_A_SHIFT 15 | ||
| 2099 | # define RADEON_COMP_ARG_B (1 << 16) | ||
| 2100 | # define RADEON_COMP_ARG_B_SHIFT 16 | ||
| 2101 | # define RADEON_COMP_ARG_C (1 << 17) | ||
| 2102 | # define RADEON_COMP_ARG_C_SHIFT 17 | ||
| 2103 | # define RADEON_BLEND_CTL_MASK (7 << 18) | ||
| 2104 | # define RADEON_BLEND_CTL_ADD (0 << 18) | ||
| 2105 | # define RADEON_BLEND_CTL_SUBTRACT (1 << 18) | ||
| 2106 | # define RADEON_BLEND_CTL_ADDSIGNED (2 << 18) | ||
| 2107 | # define RADEON_BLEND_CTL_BLEND (3 << 18) | ||
| 2108 | # define RADEON_BLEND_CTL_DOT3 (4 << 18) | ||
| 2109 | # define RADEON_SCALE_SHIFT 21 | ||
| 2110 | # define RADEON_SCALE_MASK (3 << 21) | ||
| 2111 | # define RADEON_SCALE_1X (0 << 21) | ||
| 2112 | # define RADEON_SCALE_2X (1 << 21) | ||
| 2113 | # define RADEON_SCALE_4X (2 << 21) | ||
| 2114 | # define RADEON_CLAMP_TX (1 << 23) | ||
| 2115 | # define RADEON_T0_EQ_TCUR (1 << 24) | ||
| 2116 | # define RADEON_T1_EQ_TCUR (1 << 25) | ||
| 2117 | # define RADEON_T2_EQ_TCUR (1 << 26) | ||
| 2118 | # define RADEON_T3_EQ_TCUR (1 << 27) | ||
| 2119 | # define RADEON_COLOR_ARG_MASK 0x1f | ||
| 2120 | # define RADEON_COMP_ARG_SHIFT 15 | ||
| 2121 | #define RADEON_PP_TXABLEND_0 0x1c64 | ||
| 2122 | #define RADEON_PP_TXABLEND_1 0x1c7c | ||
| 2123 | #define RADEON_PP_TXABLEND_2 0x1c94 | ||
| 2124 | # define RADEON_ALPHA_ARG_A_SHIFT 0 | ||
| 2125 | # define RADEON_ALPHA_ARG_A_MASK (0xf << 0) | ||
| 2126 | # define RADEON_ALPHA_ARG_A_ZERO (0 << 0) | ||
| 2127 | # define RADEON_ALPHA_ARG_A_CURRENT_ALPHA (1 << 0) | ||
| 2128 | # define RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA (2 << 0) | ||
| 2129 | # define RADEON_ALPHA_ARG_A_SPECULAR_ALPHA (3 << 0) | ||
| 2130 | # define RADEON_ALPHA_ARG_A_TFACTOR_ALPHA (4 << 0) | ||
| 2131 | # define RADEON_ALPHA_ARG_A_T0_ALPHA (5 << 0) | ||
| 2132 | # define RADEON_ALPHA_ARG_A_T1_ALPHA (6 << 0) | ||
| 2133 | # define RADEON_ALPHA_ARG_A_T2_ALPHA (7 << 0) | ||
| 2134 | # define RADEON_ALPHA_ARG_A_T3_ALPHA (8 << 0) | ||
| 2135 | # define RADEON_ALPHA_ARG_B_SHIFT 4 | ||
| 2136 | # define RADEON_ALPHA_ARG_B_MASK (0xf << 4) | ||
| 2137 | # define RADEON_ALPHA_ARG_B_ZERO (0 << 4) | ||
| 2138 | # define RADEON_ALPHA_ARG_B_CURRENT_ALPHA (1 << 4) | ||
| 2139 | # define RADEON_ALPHA_ARG_B_DIFFUSE_ALPHA (2 << 4) | ||
| 2140 | # define RADEON_ALPHA_ARG_B_SPECULAR_ALPHA (3 << 4) | ||
| 2141 | # define RADEON_ALPHA_ARG_B_TFACTOR_ALPHA (4 << 4) | ||
| 2142 | # define RADEON_ALPHA_ARG_B_T0_ALPHA (5 << 4) | ||
| 2143 | # define RADEON_ALPHA_ARG_B_T1_ALPHA (6 << 4) | ||
| 2144 | # define RADEON_ALPHA_ARG_B_T2_ALPHA (7 << 4) | ||
| 2145 | # define RADEON_ALPHA_ARG_B_T3_ALPHA (8 << 4) | ||
| 2146 | # define RADEON_ALPHA_ARG_C_SHIFT 8 | ||
| 2147 | # define RADEON_ALPHA_ARG_C_MASK (0xf << 8) | ||
| 2148 | # define RADEON_ALPHA_ARG_C_ZERO (0 << 8) | ||
| 2149 | # define RADEON_ALPHA_ARG_C_CURRENT_ALPHA (1 << 8) | ||
| 2150 | # define RADEON_ALPHA_ARG_C_DIFFUSE_ALPHA (2 << 8) | ||
| 2151 | # define RADEON_ALPHA_ARG_C_SPECULAR_ALPHA (3 << 8) | ||
| 2152 | # define RADEON_ALPHA_ARG_C_TFACTOR_ALPHA (4 << 8) | ||
| 2153 | # define RADEON_ALPHA_ARG_C_T0_ALPHA (5 << 8) | ||
| 2154 | # define RADEON_ALPHA_ARG_C_T1_ALPHA (6 << 8) | ||
| 2155 | # define RADEON_ALPHA_ARG_C_T2_ALPHA (7 << 8) | ||
| 2156 | # define RADEON_ALPHA_ARG_C_T3_ALPHA (8 << 8) | ||
| 2157 | # define RADEON_DOT_ALPHA_DONT_REPLICATE (1 << 9) | ||
| 2158 | # define RADEON_ALPHA_ARG_MASK 0xf | ||
| 2159 | |||
| 2160 | #define RADEON_PP_TFACTOR_0 0x1c68 | ||
| 2161 | #define RADEON_PP_TFACTOR_1 0x1c80 | ||
| 2162 | #define RADEON_PP_TFACTOR_2 0x1c98 | ||
| 2163 | |||
| 2164 | #define RADEON_RB3D_BLENDCNTL 0x1c20 | ||
| 2165 | # define RADEON_COMB_FCN_MASK (3 << 12) | ||
| 2166 | # define RADEON_COMB_FCN_ADD_CLAMP (0 << 12) | ||
| 2167 | # define RADEON_COMB_FCN_ADD_NOCLAMP (1 << 12) | ||
| 2168 | # define RADEON_COMB_FCN_SUB_CLAMP (2 << 12) | ||
| 2169 | # define RADEON_COMB_FCN_SUB_NOCLAMP (3 << 12) | ||
| 2170 | # define RADEON_SRC_BLEND_GL_ZERO (32 << 16) | ||
| 2171 | # define RADEON_SRC_BLEND_GL_ONE (33 << 16) | ||
| 2172 | # define RADEON_SRC_BLEND_GL_SRC_COLOR (34 << 16) | ||
| 2173 | # define RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 16) | ||
| 2174 | # define RADEON_SRC_BLEND_GL_DST_COLOR (36 << 16) | ||
| 2175 | # define RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 16) | ||
| 2176 | # define RADEON_SRC_BLEND_GL_SRC_ALPHA (38 << 16) | ||
| 2177 | # define RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 16) | ||
| 2178 | # define RADEON_SRC_BLEND_GL_DST_ALPHA (40 << 16) | ||
| 2179 | # define RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 16) | ||
| 2180 | # define RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE (42 << 16) | ||
| 2181 | # define RADEON_SRC_BLEND_MASK (63 << 16) | ||
| 2182 | # define RADEON_DST_BLEND_GL_ZERO (32 << 24) | ||
| 2183 | # define RADEON_DST_BLEND_GL_ONE (33 << 24) | ||
| 2184 | # define RADEON_DST_BLEND_GL_SRC_COLOR (34 << 24) | ||
| 2185 | # define RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR (35 << 24) | ||
| 2186 | # define RADEON_DST_BLEND_GL_DST_COLOR (36 << 24) | ||
| 2187 | # define RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR (37 << 24) | ||
| 2188 | # define RADEON_DST_BLEND_GL_SRC_ALPHA (38 << 24) | ||
| 2189 | # define RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA (39 << 24) | ||
| 2190 | # define RADEON_DST_BLEND_GL_DST_ALPHA (40 << 24) | ||
| 2191 | # define RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA (41 << 24) | ||
| 2192 | # define RADEON_DST_BLEND_MASK (63 << 24) | ||
| 2193 | #define RADEON_RB3D_CNTL 0x1c3c | ||
| 2194 | # define RADEON_ALPHA_BLEND_ENABLE (1 << 0) | ||
| 2195 | # define RADEON_PLANE_MASK_ENABLE (1 << 1) | ||
| 2196 | # define RADEON_DITHER_ENABLE (1 << 2) | ||
| 2197 | # define RADEON_ROUND_ENABLE (1 << 3) | ||
| 2198 | # define RADEON_SCALE_DITHER_ENABLE (1 << 4) | ||
| 2199 | # define RADEON_DITHER_INIT (1 << 5) | ||
| 2200 | # define RADEON_ROP_ENABLE (1 << 6) | ||
| 2201 | # define RADEON_STENCIL_ENABLE (1 << 7) | ||
| 2202 | # define RADEON_Z_ENABLE (1 << 8) | ||
| 2203 | # define RADEON_DEPTH_XZ_OFFEST_ENABLE (1 << 9) | ||
| 2204 | # define RADEON_RB3D_COLOR_FORMAT_SHIFT 10 | ||
| 2205 | |||
| 2206 | # define RADEON_COLOR_FORMAT_ARGB1555 3 | ||
| 2207 | # define RADEON_COLOR_FORMAT_RGB565 4 | ||
| 2208 | # define RADEON_COLOR_FORMAT_ARGB8888 6 | ||
| 2209 | # define RADEON_COLOR_FORMAT_RGB332 7 | ||
| 2210 | # define RADEON_COLOR_FORMAT_Y8 8 | ||
| 2211 | # define RADEON_COLOR_FORMAT_RGB8 9 | ||
| 2212 | # define RADEON_COLOR_FORMAT_YUV422_VYUY 11 | ||
| 2213 | # define RADEON_COLOR_FORMAT_YUV422_YVYU 12 | ||
| 2214 | # define RADEON_COLOR_FORMAT_aYUV444 14 | ||
| 2215 | # define RADEON_COLOR_FORMAT_ARGB4444 15 | ||
| 2216 | |||
| 2217 | # define RADEON_CLRCMP_FLIP_ENABLE (1 << 14) | ||
| 2218 | #define RADEON_RB3D_COLOROFFSET 0x1c40 | ||
| 2219 | # define RADEON_COLOROFFSET_MASK 0xfffffff0 | ||
| 2220 | #define RADEON_RB3D_COLORPITCH 0x1c48 | ||
| 2221 | # define RADEON_COLORPITCH_MASK 0x000001ff8 | ||
| 2222 | # define RADEON_COLOR_TILE_ENABLE (1 << 16) | ||
| 2223 | # define RADEON_COLOR_MICROTILE_ENABLE (1 << 17) | ||
| 2224 | # define RADEON_COLOR_ENDIAN_NO_SWAP (0 << 18) | ||
| 2225 | # define RADEON_COLOR_ENDIAN_WORD_SWAP (1 << 18) | ||
| 2226 | # define RADEON_COLOR_ENDIAN_DWORD_SWAP (2 << 18) | ||
| 2227 | #define RADEON_RB3D_DEPTHOFFSET 0x1c24 | ||
| 2228 | #define RADEON_RB3D_DEPTHPITCH 0x1c28 | ||
| 2229 | # define RADEON_DEPTHPITCH_MASK 0x00001ff8 | ||
| 2230 | # define RADEON_DEPTH_ENDIAN_NO_SWAP (0 << 18) | ||
| 2231 | # define RADEON_DEPTH_ENDIAN_WORD_SWAP (1 << 18) | ||
| 2232 | # define RADEON_DEPTH_ENDIAN_DWORD_SWAP (2 << 18) | ||
| 2233 | #define RADEON_RB3D_PLANEMASK 0x1d84 | ||
| 2234 | #define RADEON_RB3D_ROPCNTL 0x1d80 | ||
| 2235 | # define RADEON_ROP_MASK (15 << 8) | ||
| 2236 | # define RADEON_ROP_CLEAR (0 << 8) | ||
| 2237 | # define RADEON_ROP_NOR (1 << 8) | ||
| 2238 | # define RADEON_ROP_AND_INVERTED (2 << 8) | ||
| 2239 | # define RADEON_ROP_COPY_INVERTED (3 << 8) | ||
| 2240 | # define RADEON_ROP_AND_REVERSE (4 << 8) | ||
| 2241 | # define RADEON_ROP_INVERT (5 << 8) | ||
| 2242 | # define RADEON_ROP_XOR (6 << 8) | ||
| 2243 | # define RADEON_ROP_NAND (7 << 8) | ||
| 2244 | # define RADEON_ROP_AND (8 << 8) | ||
| 2245 | # define RADEON_ROP_EQUIV (9 << 8) | ||
| 2246 | # define RADEON_ROP_NOOP (10 << 8) | ||
| 2247 | # define RADEON_ROP_OR_INVERTED (11 << 8) | ||
| 2248 | # define RADEON_ROP_COPY (12 << 8) | ||
| 2249 | # define RADEON_ROP_OR_REVERSE (13 << 8) | ||
| 2250 | # define RADEON_ROP_OR (14 << 8) | ||
| 2251 | # define RADEON_ROP_SET (15 << 8) | ||
| 2252 | #define RADEON_RB3D_STENCILREFMASK 0x1d7c | ||
| 2253 | # define RADEON_STENCIL_REF_SHIFT 0 | ||
| 2254 | # define RADEON_STENCIL_REF_MASK (0xff << 0) | ||
| 2255 | # define RADEON_STENCIL_MASK_SHIFT 16 | ||
| 2256 | # define RADEON_STENCIL_VALUE_MASK (0xff << 16) | ||
| 2257 | # define RADEON_STENCIL_WRITEMASK_SHIFT 24 | ||
| 2258 | # define RADEON_STENCIL_WRITE_MASK (0xff << 24) | ||
| 2259 | #define RADEON_RB3D_ZSTENCILCNTL 0x1c2c | ||
| 2260 | # define RADEON_DEPTH_FORMAT_MASK (0xf << 0) | ||
| 2261 | # define RADEON_DEPTH_FORMAT_16BIT_INT_Z (0 << 0) | ||
| 2262 | # define RADEON_DEPTH_FORMAT_24BIT_INT_Z (2 << 0) | ||
| 2263 | # define RADEON_DEPTH_FORMAT_24BIT_FLOAT_Z (3 << 0) | ||
| 2264 | # define RADEON_DEPTH_FORMAT_32BIT_INT_Z (4 << 0) | ||
| 2265 | # define RADEON_DEPTH_FORMAT_32BIT_FLOAT_Z (5 << 0) | ||
| 2266 | # define RADEON_DEPTH_FORMAT_16BIT_FLOAT_W (7 << 0) | ||
| 2267 | # define RADEON_DEPTH_FORMAT_24BIT_FLOAT_W (9 << 0) | ||
| 2268 | # define RADEON_DEPTH_FORMAT_32BIT_FLOAT_W (11 << 0) | ||
| 2269 | # define RADEON_Z_TEST_NEVER (0 << 4) | ||
| 2270 | # define RADEON_Z_TEST_LESS (1 << 4) | ||
| 2271 | # define RADEON_Z_TEST_LEQUAL (2 << 4) | ||
| 2272 | # define RADEON_Z_TEST_EQUAL (3 << 4) | ||
| 2273 | # define RADEON_Z_TEST_GEQUAL (4 << 4) | ||
| 2274 | # define RADEON_Z_TEST_GREATER (5 << 4) | ||
| 2275 | # define RADEON_Z_TEST_NEQUAL (6 << 4) | ||
| 2276 | # define RADEON_Z_TEST_ALWAYS (7 << 4) | ||
| 2277 | # define RADEON_Z_TEST_MASK (7 << 4) | ||
| 2278 | # define RADEON_STENCIL_TEST_NEVER (0 << 12) | ||
| 2279 | # define RADEON_STENCIL_TEST_LESS (1 << 12) | ||
| 2280 | # define RADEON_STENCIL_TEST_LEQUAL (2 << 12) | ||
| 2281 | # define RADEON_STENCIL_TEST_EQUAL (3 << 12) | ||
| 2282 | # define RADEON_STENCIL_TEST_GEQUAL (4 << 12) | ||
| 2283 | # define RADEON_STENCIL_TEST_GREATER (5 << 12) | ||
| 2284 | # define RADEON_STENCIL_TEST_NEQUAL (6 << 12) | ||
| 2285 | # define RADEON_STENCIL_TEST_ALWAYS (7 << 12) | ||
| 2286 | # define RADEON_STENCIL_TEST_MASK (0x7 << 12) | ||
| 2287 | # define RADEON_STENCIL_FAIL_KEEP (0 << 16) | ||
| 2288 | # define RADEON_STENCIL_FAIL_ZERO (1 << 16) | ||
| 2289 | # define RADEON_STENCIL_FAIL_REPLACE (2 << 16) | ||
| 2290 | # define RADEON_STENCIL_FAIL_INC (3 << 16) | ||
| 2291 | # define RADEON_STENCIL_FAIL_DEC (4 << 16) | ||
| 2292 | # define RADEON_STENCIL_FAIL_INVERT (5 << 16) | ||
| 2293 | # define RADEON_STENCIL_FAIL_MASK (0x7 << 16) | ||
| 2294 | # define RADEON_STENCIL_ZPASS_KEEP (0 << 20) | ||
| 2295 | # define RADEON_STENCIL_ZPASS_ZERO (1 << 20) | ||
| 2296 | # define RADEON_STENCIL_ZPASS_REPLACE (2 << 20) | ||
| 2297 | # define RADEON_STENCIL_ZPASS_INC (3 << 20) | ||
| 2298 | # define RADEON_STENCIL_ZPASS_DEC (4 << 20) | ||
| 2299 | # define RADEON_STENCIL_ZPASS_INVERT (5 << 20) | ||
| 2300 | # define RADEON_STENCIL_ZPASS_MASK (0x7 << 20) | ||
| 2301 | # define RADEON_STENCIL_ZFAIL_KEEP (0 << 24) | ||
| 2302 | # define RADEON_STENCIL_ZFAIL_ZERO (1 << 24) | ||
| 2303 | # define RADEON_STENCIL_ZFAIL_REPLACE (2 << 24) | ||
| 2304 | # define RADEON_STENCIL_ZFAIL_INC (3 << 24) | ||
| 2305 | # define RADEON_STENCIL_ZFAIL_DEC (4 << 24) | ||
| 2306 | # define RADEON_STENCIL_ZFAIL_INVERT (5 << 24) | ||
| 2307 | # define RADEON_STENCIL_ZFAIL_MASK (0x7 << 24) | ||
| 2308 | # define RADEON_Z_COMPRESSION_ENABLE (1 << 28) | ||
| 2309 | # define RADEON_FORCE_Z_DIRTY (1 << 29) | ||
| 2310 | # define RADEON_Z_WRITE_ENABLE (1 << 30) | ||
| 2311 | #define RADEON_RE_LINE_PATTERN 0x1cd0 | ||
| 2312 | # define RADEON_LINE_PATTERN_MASK 0x0000ffff | ||
| 2313 | # define RADEON_LINE_REPEAT_COUNT_SHIFT 16 | ||
| 2314 | # define RADEON_LINE_PATTERN_START_SHIFT 24 | ||
| 2315 | # define RADEON_LINE_PATTERN_LITTLE_BIT_ORDER (0 << 28) | ||
| 2316 | # define RADEON_LINE_PATTERN_BIG_BIT_ORDER (1 << 28) | ||
| 2317 | # define RADEON_LINE_PATTERN_AUTO_RESET (1 << 29) | ||
| 2318 | #define RADEON_RE_LINE_STATE 0x1cd4 | ||
| 2319 | # define RADEON_LINE_CURRENT_PTR_SHIFT 0 | ||
| 2320 | # define RADEON_LINE_CURRENT_COUNT_SHIFT 8 | ||
| 2321 | #define RADEON_RE_MISC 0x26c4 | ||
| 2322 | # define RADEON_STIPPLE_COORD_MASK 0x1f | ||
| 2323 | # define RADEON_STIPPLE_X_OFFSET_SHIFT 0 | ||
| 2324 | # define RADEON_STIPPLE_X_OFFSET_MASK (0x1f << 0) | ||
| 2325 | # define RADEON_STIPPLE_Y_OFFSET_SHIFT 8 | ||
| 2326 | # define RADEON_STIPPLE_Y_OFFSET_MASK (0x1f << 8) | ||
| 2327 | # define RADEON_STIPPLE_LITTLE_BIT_ORDER (0 << 16) | ||
| 2328 | # define RADEON_STIPPLE_BIG_BIT_ORDER (1 << 16) | ||
| 2329 | #define RADEON_RE_SOLID_COLOR 0x1c1c | ||
| 2330 | #define RADEON_RE_TOP_LEFT 0x26c0 | ||
| 2331 | # define RADEON_RE_LEFT_SHIFT 0 | ||
| 2332 | # define RADEON_RE_TOP_SHIFT 16 | ||
| 2333 | #define RADEON_RE_WIDTH_HEIGHT 0x1c44 | ||
| 2334 | # define RADEON_RE_WIDTH_SHIFT 0 | ||
| 2335 | # define RADEON_RE_HEIGHT_SHIFT 16 | ||
| 2336 | |||
| 2337 | #define RADEON_SE_CNTL 0x1c4c | ||
| 2338 | # define RADEON_FFACE_CULL_CW (0 << 0) | ||
| 2339 | # define RADEON_FFACE_CULL_CCW (1 << 0) | ||
| 2340 | # define RADEON_FFACE_CULL_DIR_MASK (1 << 0) | ||
| 2341 | # define RADEON_BFACE_CULL (0 << 1) | ||
| 2342 | # define RADEON_BFACE_SOLID (3 << 1) | ||
| 2343 | # define RADEON_FFACE_CULL (0 << 3) | ||
| 2344 | # define RADEON_FFACE_SOLID (3 << 3) | ||
| 2345 | # define RADEON_FFACE_CULL_MASK (3 << 3) | ||
| 2346 | # define RADEON_BADVTX_CULL_DISABLE (1 << 5) | ||
| 2347 | # define RADEON_FLAT_SHADE_VTX_0 (0 << 6) | ||
| 2348 | # define RADEON_FLAT_SHADE_VTX_1 (1 << 6) | ||
| 2349 | # define RADEON_FLAT_SHADE_VTX_2 (2 << 6) | ||
| 2350 | # define RADEON_FLAT_SHADE_VTX_LAST (3 << 6) | ||
| 2351 | # define RADEON_DIFFUSE_SHADE_SOLID (0 << 8) | ||
| 2352 | # define RADEON_DIFFUSE_SHADE_FLAT (1 << 8) | ||
| 2353 | # define RADEON_DIFFUSE_SHADE_GOURAUD (2 << 8) | ||
| 2354 | # define RADEON_DIFFUSE_SHADE_MASK (3 << 8) | ||
| 2355 | # define RADEON_ALPHA_SHADE_SOLID (0 << 10) | ||
| 2356 | # define RADEON_ALPHA_SHADE_FLAT (1 << 10) | ||
| 2357 | # define RADEON_ALPHA_SHADE_GOURAUD (2 << 10) | ||
| 2358 | # define RADEON_ALPHA_SHADE_MASK (3 << 10) | ||
| 2359 | # define RADEON_SPECULAR_SHADE_SOLID (0 << 12) | ||
| 2360 | # define RADEON_SPECULAR_SHADE_FLAT (1 << 12) | ||
| 2361 | # define RADEON_SPECULAR_SHADE_GOURAUD (2 << 12) | ||
| 2362 | # define RADEON_SPECULAR_SHADE_MASK (3 << 12) | ||
| 2363 | # define RADEON_FOG_SHADE_SOLID (0 << 14) | ||
| 2364 | # define RADEON_FOG_SHADE_FLAT (1 << 14) | ||
| 2365 | # define RADEON_FOG_SHADE_GOURAUD (2 << 14) | ||
| 2366 | # define RADEON_FOG_SHADE_MASK (3 << 14) | ||
| 2367 | # define RADEON_ZBIAS_ENABLE_POINT (1 << 16) | ||
| 2368 | # define RADEON_ZBIAS_ENABLE_LINE (1 << 17) | ||
| 2369 | # define RADEON_ZBIAS_ENABLE_TRI (1 << 18) | ||
| 2370 | # define RADEON_WIDELINE_ENABLE (1 << 20) | ||
| 2371 | # define RADEON_VPORT_XY_XFORM_ENABLE (1 << 24) | ||
| 2372 | # define RADEON_VPORT_Z_XFORM_ENABLE (1 << 25) | ||
| 2373 | # define RADEON_VTX_PIX_CENTER_D3D (0 << 27) | ||
| 2374 | # define RADEON_VTX_PIX_CENTER_OGL (1 << 27) | ||
| 2375 | # define RADEON_ROUND_MODE_TRUNC (0 << 28) | ||
| 2376 | # define RADEON_ROUND_MODE_ROUND (1 << 28) | ||
| 2377 | # define RADEON_ROUND_MODE_ROUND_EVEN (2 << 28) | ||
| 2378 | # define RADEON_ROUND_MODE_ROUND_ODD (3 << 28) | ||
| 2379 | # define RADEON_ROUND_PREC_16TH_PIX (0 << 30) | ||
| 2380 | # define RADEON_ROUND_PREC_8TH_PIX (1 << 30) | ||
| 2381 | # define RADEON_ROUND_PREC_4TH_PIX (2 << 30) | ||
| 2382 | # define RADEON_ROUND_PREC_HALF_PIX (3 << 30) | ||
| 2383 | #define R200_RE_CNTL 0x1c50 | ||
| 2384 | # define R200_STIPPLE_ENABLE 0x1 | ||
| 2385 | # define R200_SCISSOR_ENABLE 0x2 | ||
| 2386 | # define R200_PATTERN_ENABLE 0x4 | ||
| 2387 | # define R200_PERSPECTIVE_ENABLE 0x8 | ||
| 2388 | # define R200_POINT_SMOOTH 0x20 | ||
| 2389 | # define R200_VTX_STQ0_D3D 0x00010000 | ||
| 2390 | # define R200_VTX_STQ1_D3D 0x00040000 | ||
| 2391 | # define R200_VTX_STQ2_D3D 0x00100000 | ||
| 2392 | # define R200_VTX_STQ3_D3D 0x00400000 | ||
| 2393 | # define R200_VTX_STQ4_D3D 0x01000000 | ||
| 2394 | # define R200_VTX_STQ5_D3D 0x04000000 | ||
| 2395 | #define RADEON_SE_CNTL_STATUS 0x2140 | ||
| 2396 | # define RADEON_VC_NO_SWAP (0 << 0) | ||
| 2397 | # define RADEON_VC_16BIT_SWAP (1 << 0) | ||
| 2398 | # define RADEON_VC_32BIT_SWAP (2 << 0) | ||
| 2399 | # define RADEON_VC_HALF_DWORD_SWAP (3 << 0) | ||
| 2400 | # define RADEON_TCL_BYPASS (1 << 8) | ||
| 2401 | #define RADEON_SE_COORD_FMT 0x1c50 | ||
| 2402 | # define RADEON_VTX_XY_PRE_MULT_1_OVER_W0 (1 << 0) | ||
| 2403 | # define RADEON_VTX_Z_PRE_MULT_1_OVER_W0 (1 << 1) | ||
| 2404 | # define RADEON_VTX_ST0_NONPARAMETRIC (1 << 8) | ||
| 2405 | # define RADEON_VTX_ST1_NONPARAMETRIC (1 << 9) | ||
| 2406 | # define RADEON_VTX_ST2_NONPARAMETRIC (1 << 10) | ||
| 2407 | # define RADEON_VTX_ST3_NONPARAMETRIC (1 << 11) | ||
| 2408 | # define RADEON_VTX_W0_NORMALIZE (1 << 12) | ||
| 2409 | # define RADEON_VTX_W0_IS_NOT_1_OVER_W0 (1 << 16) | ||
| 2410 | # define RADEON_VTX_ST0_PRE_MULT_1_OVER_W0 (1 << 17) | ||
| 2411 | # define RADEON_VTX_ST1_PRE_MULT_1_OVER_W0 (1 << 19) | ||
| 2412 | # define RADEON_VTX_ST2_PRE_MULT_1_OVER_W0 (1 << 21) | ||
| 2413 | # define RADEON_VTX_ST3_PRE_MULT_1_OVER_W0 (1 << 23) | ||
| 2414 | # define RADEON_TEX1_W_ROUTING_USE_W0 (0 << 26) | ||
| 2415 | # define RADEON_TEX1_W_ROUTING_USE_Q1 (1 << 26) | ||
| 2416 | #define RADEON_SE_LINE_WIDTH 0x1db8 | ||
| 2417 | #define RADEON_SE_TCL_LIGHT_MODEL_CTL 0x226c | ||
| 2418 | # define RADEON_LIGHTING_ENABLE (1 << 0) | ||
| 2419 | # define RADEON_LIGHT_IN_MODELSPACE (1 << 1) | ||
| 2420 | # define RADEON_LOCAL_VIEWER (1 << 2) | ||
| 2421 | # define RADEON_NORMALIZE_NORMALS (1 << 3) | ||
| 2422 | # define RADEON_RESCALE_NORMALS (1 << 4) | ||
| 2423 | # define RADEON_SPECULAR_LIGHTS (1 << 5) | ||
| 2424 | # define RADEON_DIFFUSE_SPECULAR_COMBINE (1 << 6) | ||
| 2425 | # define RADEON_LIGHT_ALPHA (1 << 7) | ||
| 2426 | # define RADEON_LOCAL_LIGHT_VEC_GL (1 << 8) | ||
| 2427 | # define RADEON_LIGHT_NO_NORMAL_AMBIENT_ONLY (1 << 9) | ||
| 2428 | # define RADEON_LM_SOURCE_STATE_PREMULT 0 | ||
| 2429 | # define RADEON_LM_SOURCE_STATE_MULT 1 | ||
| 2430 | # define RADEON_LM_SOURCE_VERTEX_DIFFUSE 2 | ||
| 2431 | # define RADEON_LM_SOURCE_VERTEX_SPECULAR 3 | ||
| 2432 | # define RADEON_EMISSIVE_SOURCE_SHIFT 16 | ||
| 2433 | # define RADEON_AMBIENT_SOURCE_SHIFT 18 | ||
| 2434 | # define RADEON_DIFFUSE_SOURCE_SHIFT 20 | ||
| 2435 | # define RADEON_SPECULAR_SOURCE_SHIFT 22 | ||
| 2436 | #define RADEON_SE_TCL_MATERIAL_AMBIENT_RED 0x2220 | ||
| 2437 | #define RADEON_SE_TCL_MATERIAL_AMBIENT_GREEN 0x2224 | ||
| 2438 | #define RADEON_SE_TCL_MATERIAL_AMBIENT_BLUE 0x2228 | ||
| 2439 | #define RADEON_SE_TCL_MATERIAL_AMBIENT_ALPHA 0x222c | ||
| 2440 | #define RADEON_SE_TCL_MATERIAL_DIFFUSE_RED 0x2230 | ||
| 2441 | #define RADEON_SE_TCL_MATERIAL_DIFFUSE_GREEN 0x2234 | ||
| 2442 | #define RADEON_SE_TCL_MATERIAL_DIFFUSE_BLUE 0x2238 | ||
| 2443 | #define RADEON_SE_TCL_MATERIAL_DIFFUSE_ALPHA 0x223c | ||
| 2444 | #define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210 | ||
| 2445 | #define RADEON_SE_TCL_MATERIAL_EMMISSIVE_GREEN 0x2214 | ||
| 2446 | #define RADEON_SE_TCL_MATERIAL_EMMISSIVE_BLUE 0x2218 | ||
| 2447 | #define RADEON_SE_TCL_MATERIAL_EMMISSIVE_ALPHA 0x221c | ||
| 2448 | #define RADEON_SE_TCL_MATERIAL_SPECULAR_RED 0x2240 | ||
| 2449 | #define RADEON_SE_TCL_MATERIAL_SPECULAR_GREEN 0x2244 | ||
| 2450 | #define RADEON_SE_TCL_MATERIAL_SPECULAR_BLUE 0x2248 | ||
| 2451 | #define RADEON_SE_TCL_MATERIAL_SPECULAR_ALPHA 0x224c | ||
| 2452 | #define RADEON_SE_TCL_MATRIX_SELECT_0 0x225c | ||
| 2453 | # define RADEON_MODELVIEW_0_SHIFT 0 | ||
| 2454 | # define RADEON_MODELVIEW_1_SHIFT 4 | ||
| 2455 | # define RADEON_MODELVIEW_2_SHIFT 8 | ||
| 2456 | # define RADEON_MODELVIEW_3_SHIFT 12 | ||
| 2457 | # define RADEON_IT_MODELVIEW_0_SHIFT 16 | ||
| 2458 | # define RADEON_IT_MODELVIEW_1_SHIFT 20 | ||
| 2459 | # define RADEON_IT_MODELVIEW_2_SHIFT 24 | ||
| 2460 | # define RADEON_IT_MODELVIEW_3_SHIFT 28 | ||
| 2461 | #define RADEON_SE_TCL_MATRIX_SELECT_1 0x2260 | ||
| 2462 | # define RADEON_MODELPROJECT_0_SHIFT 0 | ||
| 2463 | # define RADEON_MODELPROJECT_1_SHIFT 4 | ||
| 2464 | # define RADEON_MODELPROJECT_2_SHIFT 8 | ||
| 2465 | # define RADEON_MODELPROJECT_3_SHIFT 12 | ||
| 2466 | # define RADEON_TEXMAT_0_SHIFT 16 | ||
| 2467 | # define RADEON_TEXMAT_1_SHIFT 20 | ||
| 2468 | # define RADEON_TEXMAT_2_SHIFT 24 | ||
| 2469 | # define RADEON_TEXMAT_3_SHIFT 28 | ||
| 2470 | |||
| 2471 | |||
| 2472 | #define RADEON_SE_TCL_OUTPUT_VTX_FMT 0x2254 | ||
| 2473 | # define RADEON_TCL_VTX_W0 (1 << 0) | ||
| 2474 | # define RADEON_TCL_VTX_FP_DIFFUSE (1 << 1) | ||
| 2475 | # define RADEON_TCL_VTX_FP_ALPHA (1 << 2) | ||
| 2476 | # define RADEON_TCL_VTX_PK_DIFFUSE (1 << 3) | ||
| 2477 | # define RADEON_TCL_VTX_FP_SPEC (1 << 4) | ||
| 2478 | # define RADEON_TCL_VTX_FP_FOG (1 << 5) | ||
| 2479 | # define RADEON_TCL_VTX_PK_SPEC (1 << 6) | ||
| 2480 | # define RADEON_TCL_VTX_ST0 (1 << 7) | ||
| 2481 | # define RADEON_TCL_VTX_ST1 (1 << 8) | ||
| 2482 | # define RADEON_TCL_VTX_Q1 (1 << 9) | ||
| 2483 | # define RADEON_TCL_VTX_ST2 (1 << 10) | ||
| 2484 | # define RADEON_TCL_VTX_Q2 (1 << 11) | ||
| 2485 | # define RADEON_TCL_VTX_ST3 (1 << 12) | ||
| 2486 | # define RADEON_TCL_VTX_Q3 (1 << 13) | ||
| 2487 | # define RADEON_TCL_VTX_Q0 (1 << 14) | ||
| 2488 | # define RADEON_TCL_VTX_WEIGHT_COUNT_SHIFT 15 | ||
| 2489 | # define RADEON_TCL_VTX_NORM0 (1 << 18) | ||
| 2490 | # define RADEON_TCL_VTX_XY1 (1 << 27) | ||
| 2491 | # define RADEON_TCL_VTX_Z1 (1 << 28) | ||
| 2492 | # define RADEON_TCL_VTX_W1 (1 << 29) | ||
| 2493 | # define RADEON_TCL_VTX_NORM1 (1 << 30) | ||
| 2494 | # define RADEON_TCL_VTX_Z0 (1 << 31) | ||
| 2495 | |||
| 2496 | #define RADEON_SE_TCL_OUTPUT_VTX_SEL 0x2258 | ||
| 2497 | # define RADEON_TCL_COMPUTE_XYZW (1 << 0) | ||
| 2498 | # define RADEON_TCL_COMPUTE_DIFFUSE (1 << 1) | ||
| 2499 | # define RADEON_TCL_COMPUTE_SPECULAR (1 << 2) | ||
| 2500 | # define RADEON_TCL_FORCE_NAN_IF_COLOR_NAN (1 << 3) | ||
| 2501 | # define RADEON_TCL_FORCE_INORDER_PROC (1 << 4) | ||
| 2502 | # define RADEON_TCL_TEX_INPUT_TEX_0 0 | ||
| 2503 | # define RADEON_TCL_TEX_INPUT_TEX_1 1 | ||
| 2504 | # define RADEON_TCL_TEX_INPUT_TEX_2 2 | ||
| 2505 | # define RADEON_TCL_TEX_INPUT_TEX_3 3 | ||
| 2506 | # define RADEON_TCL_TEX_COMPUTED_TEX_0 8 | ||
| 2507 | # define RADEON_TCL_TEX_COMPUTED_TEX_1 9 | ||
| 2508 | # define RADEON_TCL_TEX_COMPUTED_TEX_2 10 | ||
| 2509 | # define RADEON_TCL_TEX_COMPUTED_TEX_3 11 | ||
| 2510 | # define RADEON_TCL_TEX_0_OUTPUT_SHIFT 16 | ||
| 2511 | # define RADEON_TCL_TEX_1_OUTPUT_SHIFT 20 | ||
| 2512 | # define RADEON_TCL_TEX_2_OUTPUT_SHIFT 24 | ||
| 2513 | # define RADEON_TCL_TEX_3_OUTPUT_SHIFT 28 | ||
| 2514 | |||
| 2515 | #define RADEON_SE_TCL_PER_LIGHT_CTL_0 0x2270 | ||
| 2516 | # define RADEON_LIGHT_0_ENABLE (1 << 0) | ||
| 2517 | # define RADEON_LIGHT_0_ENABLE_AMBIENT (1 << 1) | ||
| 2518 | # define RADEON_LIGHT_0_ENABLE_SPECULAR (1 << 2) | ||
| 2519 | # define RADEON_LIGHT_0_IS_LOCAL (1 << 3) | ||
| 2520 | # define RADEON_LIGHT_0_IS_SPOT (1 << 4) | ||
| 2521 | # define RADEON_LIGHT_0_DUAL_CONE (1 << 5) | ||
| 2522 | # define RADEON_LIGHT_0_ENABLE_RANGE_ATTEN (1 << 6) | ||
| 2523 | # define RADEON_LIGHT_0_CONSTANT_RANGE_ATTEN (1 << 7) | ||
| 2524 | # define RADEON_LIGHT_0_SHIFT 0 | ||
| 2525 | # define RADEON_LIGHT_1_ENABLE (1 << 16) | ||
| 2526 | # define RADEON_LIGHT_1_ENABLE_AMBIENT (1 << 17) | ||
| 2527 | # define RADEON_LIGHT_1_ENABLE_SPECULAR (1 << 18) | ||
| 2528 | # define RADEON_LIGHT_1_IS_LOCAL (1 << 19) | ||
| 2529 | # define RADEON_LIGHT_1_IS_SPOT (1 << 20) | ||
| 2530 | # define RADEON_LIGHT_1_DUAL_CONE (1 << 21) | ||
| 2531 | # define RADEON_LIGHT_1_ENABLE_RANGE_ATTEN (1 << 22) | ||
| 2532 | # define RADEON_LIGHT_1_CONSTANT_RANGE_ATTEN (1 << 23) | ||
| 2533 | # define RADEON_LIGHT_1_SHIFT 16 | ||
| 2534 | #define RADEON_SE_TCL_PER_LIGHT_CTL_1 0x2274 | ||
| 2535 | # define RADEON_LIGHT_2_SHIFT 0 | ||
| 2536 | # define RADEON_LIGHT_3_SHIFT 16 | ||
| 2537 | #define RADEON_SE_TCL_PER_LIGHT_CTL_2 0x2278 | ||
| 2538 | # define RADEON_LIGHT_4_SHIFT 0 | ||
| 2539 | # define RADEON_LIGHT_5_SHIFT 16 | ||
| 2540 | #define RADEON_SE_TCL_PER_LIGHT_CTL_3 0x227c | ||
| 2541 | # define RADEON_LIGHT_6_SHIFT 0 | ||
| 2542 | # define RADEON_LIGHT_7_SHIFT 16 | ||
| 2543 | |||
| 2544 | #define RADEON_SE_TCL_SHININESS 0x2250 | ||
| 2545 | |||
| 2546 | #define RADEON_SE_TCL_TEXTURE_PROC_CTL 0x2268 | ||
| 2547 | # define RADEON_TEXGEN_TEXMAT_0_ENABLE (1 << 0) | ||
| 2548 | # define RADEON_TEXGEN_TEXMAT_1_ENABLE (1 << 1) | ||
| 2549 | # define RADEON_TEXGEN_TEXMAT_2_ENABLE (1 << 2) | ||
| 2550 | # define RADEON_TEXGEN_TEXMAT_3_ENABLE (1 << 3) | ||
| 2551 | # define RADEON_TEXMAT_0_ENABLE (1 << 4) | ||
| 2552 | # define RADEON_TEXMAT_1_ENABLE (1 << 5) | ||
| 2553 | # define RADEON_TEXMAT_2_ENABLE (1 << 6) | ||
| 2554 | # define RADEON_TEXMAT_3_ENABLE (1 << 7) | ||
| 2555 | # define RADEON_TEXGEN_INPUT_MASK 0xf | ||
| 2556 | # define RADEON_TEXGEN_INPUT_TEXCOORD_0 0 | ||
| 2557 | # define RADEON_TEXGEN_INPUT_TEXCOORD_1 1 | ||
| 2558 | # define RADEON_TEXGEN_INPUT_TEXCOORD_2 2 | ||
| 2559 | # define RADEON_TEXGEN_INPUT_TEXCOORD_3 3 | ||
| 2560 | # define RADEON_TEXGEN_INPUT_OBJ 4 | ||
| 2561 | # define RADEON_TEXGEN_INPUT_EYE 5 | ||
| 2562 | # define RADEON_TEXGEN_INPUT_EYE_NORMAL 6 | ||
| 2563 | # define RADEON_TEXGEN_INPUT_EYE_REFLECT 7 | ||
| 2564 | # define RADEON_TEXGEN_INPUT_EYE_NORMALIZED 8 | ||
| 2565 | # define RADEON_TEXGEN_0_INPUT_SHIFT 16 | ||
| 2566 | # define RADEON_TEXGEN_1_INPUT_SHIFT 20 | ||
| 2567 | # define RADEON_TEXGEN_2_INPUT_SHIFT 24 | ||
| 2568 | # define RADEON_TEXGEN_3_INPUT_SHIFT 28 | ||
| 2569 | |||
| 2570 | #define RADEON_SE_TCL_UCP_VERT_BLEND_CTL 0x2264 | ||
| 2571 | # define RADEON_UCP_IN_CLIP_SPACE (1 << 0) | ||
| 2572 | # define RADEON_UCP_IN_MODEL_SPACE (1 << 1) | ||
| 2573 | # define RADEON_UCP_ENABLE_0 (1 << 2) | ||
| 2574 | # define RADEON_UCP_ENABLE_1 (1 << 3) | ||
| 2575 | # define RADEON_UCP_ENABLE_2 (1 << 4) | ||
| 2576 | # define RADEON_UCP_ENABLE_3 (1 << 5) | ||
| 2577 | # define RADEON_UCP_ENABLE_4 (1 << 6) | ||
| 2578 | # define RADEON_UCP_ENABLE_5 (1 << 7) | ||
| 2579 | # define RADEON_TCL_FOG_MASK (3 << 8) | ||
| 2580 | # define RADEON_TCL_FOG_DISABLE (0 << 8) | ||
| 2581 | # define RADEON_TCL_FOG_EXP (1 << 8) | ||
| 2582 | # define RADEON_TCL_FOG_EXP2 (2 << 8) | ||
| 2583 | # define RADEON_TCL_FOG_LINEAR (3 << 8) | ||
| 2584 | # define RADEON_RNG_BASED_FOG (1 << 10) | ||
| 2585 | # define RADEON_LIGHT_TWOSIDE (1 << 11) | ||
| 2586 | # define RADEON_BLEND_OP_COUNT_MASK (7 << 12) | ||
| 2587 | # define RADEON_BLEND_OP_COUNT_SHIFT 12 | ||
| 2588 | # define RADEON_POSITION_BLEND_OP_ENABLE (1 << 16) | ||
| 2589 | # define RADEON_NORMAL_BLEND_OP_ENABLE (1 << 17) | ||
| 2590 | # define RADEON_VERTEX_BLEND_SRC_0_PRIMARY (1 << 18) | ||
| 2591 | # define RADEON_VERTEX_BLEND_SRC_0_SECONDARY (1 << 18) | ||
| 2592 | # define RADEON_VERTEX_BLEND_SRC_1_PRIMARY (1 << 19) | ||
| 2593 | # define RADEON_VERTEX_BLEND_SRC_1_SECONDARY (1 << 19) | ||
| 2594 | # define RADEON_VERTEX_BLEND_SRC_2_PRIMARY (1 << 20) | ||
| 2595 | # define RADEON_VERTEX_BLEND_SRC_2_SECONDARY (1 << 20) | ||
| 2596 | # define RADEON_VERTEX_BLEND_SRC_3_PRIMARY (1 << 21) | ||
| 2597 | # define RADEON_VERTEX_BLEND_SRC_3_SECONDARY (1 << 21) | ||
| 2598 | # define RADEON_VERTEX_BLEND_WGT_MINUS_ONE (1 << 22) | ||
| 2599 | # define RADEON_CULL_FRONT_IS_CW (0 << 28) | ||
| 2600 | # define RADEON_CULL_FRONT_IS_CCW (1 << 28) | ||
| 2601 | # define RADEON_CULL_FRONT (1 << 29) | ||
| 2602 | # define RADEON_CULL_BACK (1 << 30) | ||
| 2603 | # define RADEON_FORCE_W_TO_ONE (1 << 31) | ||
| 2604 | |||
| 2605 | #define RADEON_SE_VPORT_XSCALE 0x1d98 | ||
| 2606 | #define RADEON_SE_VPORT_XOFFSET 0x1d9c | ||
| 2607 | #define RADEON_SE_VPORT_YSCALE 0x1da0 | ||
| 2608 | #define RADEON_SE_VPORT_YOFFSET 0x1da4 | ||
| 2609 | #define RADEON_SE_VPORT_ZSCALE 0x1da8 | ||
| 2610 | #define RADEON_SE_VPORT_ZOFFSET 0x1dac | ||
| 2611 | #define RADEON_SE_ZBIAS_FACTOR 0x1db0 | ||
| 2612 | #define RADEON_SE_ZBIAS_CONSTANT 0x1db4 | ||
| 2613 | |||
| 2614 | #define RADEON_SE_VTX_FMT 0x2080 | ||
| 2615 | # define RADEON_SE_VTX_FMT_XY 0x00000000 | ||
| 2616 | # define RADEON_SE_VTX_FMT_W0 0x00000001 | ||
| 2617 | # define RADEON_SE_VTX_FMT_FPCOLOR 0x00000002 | ||
| 2618 | # define RADEON_SE_VTX_FMT_FPALPHA 0x00000004 | ||
| 2619 | # define RADEON_SE_VTX_FMT_PKCOLOR 0x00000008 | ||
| 2620 | # define RADEON_SE_VTX_FMT_FPSPEC 0x00000010 | ||
| 2621 | # define RADEON_SE_VTX_FMT_FPFOG 0x00000020 | ||
| 2622 | # define RADEON_SE_VTX_FMT_PKSPEC 0x00000040 | ||
| 2623 | # define RADEON_SE_VTX_FMT_ST0 0x00000080 | ||
| 2624 | # define RADEON_SE_VTX_FMT_ST1 0x00000100 | ||
| 2625 | # define RADEON_SE_VTX_FMT_Q1 0x00000200 | ||
| 2626 | # define RADEON_SE_VTX_FMT_ST2 0x00000400 | ||
| 2627 | # define RADEON_SE_VTX_FMT_Q2 0x00000800 | ||
| 2628 | # define RADEON_SE_VTX_FMT_ST3 0x00001000 | ||
| 2629 | # define RADEON_SE_VTX_FMT_Q3 0x00002000 | ||
| 2630 | # define RADEON_SE_VTX_FMT_Q0 0x00004000 | ||
| 2631 | # define RADEON_SE_VTX_FMT_BLND_WEIGHT_CNT_MASK 0x00038000 | ||
| 2632 | # define RADEON_SE_VTX_FMT_N0 0x00040000 | ||
| 2633 | # define RADEON_SE_VTX_FMT_XY1 0x08000000 | ||
| 2634 | # define RADEON_SE_VTX_FMT_Z1 0x10000000 | ||
| 2635 | # define RADEON_SE_VTX_FMT_W1 0x20000000 | ||
| 2636 | # define RADEON_SE_VTX_FMT_N1 0x40000000 | ||
| 2637 | # define RADEON_SE_VTX_FMT_Z 0x80000000 | ||
| 2638 | |||
| 2639 | #define RADEON_SE_VF_CNTL 0x2084 | ||
| 2640 | # define RADEON_VF_PRIM_TYPE_POINT_LIST 1 | ||
| 2641 | # define RADEON_VF_PRIM_TYPE_LINE_LIST 2 | ||
| 2642 | # define RADEON_VF_PRIM_TYPE_LINE_STRIP 3 | ||
| 2643 | # define RADEON_VF_PRIM_TYPE_TRIANGLE_LIST 4 | ||
| 2644 | # define RADEON_VF_PRIM_TYPE_TRIANGLE_FAN 5 | ||
| 2645 | # define RADEON_VF_PRIM_TYPE_TRIANGLE_STRIP 6 | ||
| 2646 | # define RADEON_VF_PRIM_TYPE_TRIANGLE_FLAG 7 | ||
| 2647 | # define RADEON_VF_PRIM_TYPE_RECTANGLE_LIST 8 | ||
| 2648 | # define RADEON_VF_PRIM_TYPE_POINT_LIST_3 9 | ||
| 2649 | # define RADEON_VF_PRIM_TYPE_LINE_LIST_3 10 | ||
| 2650 | # define RADEON_VF_PRIM_TYPE_SPIRIT_LIST 11 | ||
| 2651 | # define RADEON_VF_PRIM_TYPE_LINE_LOOP 12 | ||
| 2652 | # define RADEON_VF_PRIM_TYPE_QUAD_LIST 13 | ||
| 2653 | # define RADEON_VF_PRIM_TYPE_QUAD_STRIP 14 | ||
| 2654 | # define RADEON_VF_PRIM_TYPE_POLYGON 15 | ||
| 2655 | # define RADEON_VF_PRIM_WALK_STATE (0<<4) | ||
| 2656 | # define RADEON_VF_PRIM_WALK_INDEX (1<<4) | ||
| 2657 | # define RADEON_VF_PRIM_WALK_LIST (2<<4) | ||
| 2658 | # define RADEON_VF_PRIM_WALK_DATA (3<<4) | ||
| 2659 | # define RADEON_VF_COLOR_ORDER_RGBA (1<<6) | ||
| 2660 | # define RADEON_VF_RADEON_MODE (1<<8) | ||
| 2661 | # define RADEON_VF_TCL_OUTPUT_CTL_ENA (1<<9) | ||
| 2662 | # define RADEON_VF_PROG_STREAM_ENA (1<<10) | ||
| 2663 | # define RADEON_VF_INDEX_SIZE_SHIFT 11 | ||
| 2664 | # define RADEON_VF_NUM_VERTICES_SHIFT 16 | ||
| 2665 | |||
| 2666 | #define RADEON_SE_PORT_DATA0 0x2000 | ||
| 2667 | |||
| 2668 | #define R200_SE_VAP_CNTL 0x2080 | ||
| 2669 | # define R200_VAP_TCL_ENABLE 0x00000001 | ||
| 2670 | # define R200_VAP_SINGLE_BUF_STATE_ENABLE 0x00000010 | ||
| 2671 | # define R200_VAP_FORCE_W_TO_ONE 0x00010000 | ||
| 2672 | # define R200_VAP_D3D_TEX_DEFAULT 0x00020000 | ||
| 2673 | # define R200_VAP_VF_MAX_VTX_NUM__SHIFT 18 | ||
| 2674 | # define R200_VAP_VF_MAX_VTX_NUM (9 << 18) | ||
| 2675 | # define R200_VAP_DX_CLIP_SPACE_DEF 0x00400000 | ||
| 2676 | #define R200_VF_MAX_VTX_INDX 0x210c | ||
| 2677 | #define R200_VF_MIN_VTX_INDX 0x2110 | ||
| 2678 | #define R200_SE_VTE_CNTL 0x20b0 | ||
| 2679 | # define R200_VPORT_X_SCALE_ENA 0x00000001 | ||
| 2680 | # define R200_VPORT_X_OFFSET_ENA 0x00000002 | ||
| 2681 | # define R200_VPORT_Y_SCALE_ENA 0x00000004 | ||
| 2682 | # define R200_VPORT_Y_OFFSET_ENA 0x00000008 | ||
| 2683 | # define R200_VPORT_Z_SCALE_ENA 0x00000010 | ||
| 2684 | # define R200_VPORT_Z_OFFSET_ENA 0x00000020 | ||
| 2685 | # define R200_VTX_XY_FMT 0x00000100 | ||
| 2686 | # define R200_VTX_Z_FMT 0x00000200 | ||
| 2687 | # define R200_VTX_W0_FMT 0x00000400 | ||
| 2688 | # define R200_VTX_W0_NORMALIZE 0x00000800 | ||
| 2689 | # define R200_VTX_ST_DENORMALIZED 0x00001000 | ||
| 2690 | #define R200_SE_VAP_CNTL_STATUS 0x2140 | ||
| 2691 | # define R200_VC_NO_SWAP (0 << 0) | ||
| 2692 | # define R200_VC_16BIT_SWAP (1 << 0) | ||
| 2693 | # define R200_VC_32BIT_SWAP (2 << 0) | ||
| 2694 | #define R200_PP_TXFILTER_0 0x2c00 | ||
| 2695 | #define R200_PP_TXFILTER_1 0x2c20 | ||
| 2696 | #define R200_PP_TXFILTER_2 0x2c40 | ||
| 2697 | #define R200_PP_TXFILTER_3 0x2c60 | ||
| 2698 | #define R200_PP_TXFILTER_4 0x2c80 | ||
| 2699 | #define R200_PP_TXFILTER_5 0x2ca0 | ||
| 2700 | # define R200_MAG_FILTER_NEAREST (0 << 0) | ||
| 2701 | # define R200_MAG_FILTER_LINEAR (1 << 0) | ||
| 2702 | # define R200_MAG_FILTER_MASK (1 << 0) | ||
| 2703 | # define R200_MIN_FILTER_NEAREST (0 << 1) | ||
| 2704 | # define R200_MIN_FILTER_LINEAR (1 << 1) | ||
| 2705 | # define R200_MIN_FILTER_NEAREST_MIP_NEAREST (2 << 1) | ||
| 2706 | # define R200_MIN_FILTER_NEAREST_MIP_LINEAR (3 << 1) | ||
| 2707 | # define R200_MIN_FILTER_LINEAR_MIP_NEAREST (6 << 1) | ||
| 2708 | # define R200_MIN_FILTER_LINEAR_MIP_LINEAR (7 << 1) | ||
| 2709 | # define R200_MIN_FILTER_ANISO_NEAREST (8 << 1) | ||
| 2710 | # define R200_MIN_FILTER_ANISO_LINEAR (9 << 1) | ||
| 2711 | # define R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST (10 << 1) | ||
| 2712 | # define R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR (11 << 1) | ||
| 2713 | # define R200_MIN_FILTER_MASK (15 << 1) | ||
| 2714 | # define R200_MAX_ANISO_1_TO_1 (0 << 5) | ||
| 2715 | # define R200_MAX_ANISO_2_TO_1 (1 << 5) | ||
| 2716 | # define R200_MAX_ANISO_4_TO_1 (2 << 5) | ||
| 2717 | # define R200_MAX_ANISO_8_TO_1 (3 << 5) | ||
| 2718 | # define R200_MAX_ANISO_16_TO_1 (4 << 5) | ||
| 2719 | # define R200_MAX_ANISO_MASK (7 << 5) | ||
| 2720 | # define R200_MAX_MIP_LEVEL_MASK (0x0f << 16) | ||
| 2721 | # define R200_MAX_MIP_LEVEL_SHIFT 16 | ||
| 2722 | # define R200_YUV_TO_RGB (1 << 20) | ||
| 2723 | # define R200_YUV_TEMPERATURE_COOL (0 << 21) | ||
| 2724 | # define R200_YUV_TEMPERATURE_HOT (1 << 21) | ||
| 2725 | # define R200_YUV_TEMPERATURE_MASK (1 << 21) | ||
| 2726 | # define R200_WRAPEN_S (1 << 22) | ||
| 2727 | # define R200_CLAMP_S_WRAP (0 << 23) | ||
| 2728 | # define R200_CLAMP_S_MIRROR (1 << 23) | ||
| 2729 | # define R200_CLAMP_S_CLAMP_LAST (2 << 23) | ||
| 2730 | # define R200_CLAMP_S_MIRROR_CLAMP_LAST (3 << 23) | ||
| 2731 | # define R200_CLAMP_S_CLAMP_BORDER (4 << 23) | ||
| 2732 | # define R200_CLAMP_S_MIRROR_CLAMP_BORDER (5 << 23) | ||
| 2733 | # define R200_CLAMP_S_CLAMP_GL (6 << 23) | ||
| 2734 | # define R200_CLAMP_S_MIRROR_CLAMP_GL (7 << 23) | ||
| 2735 | # define R200_CLAMP_S_MASK (7 << 23) | ||
| 2736 | # define R200_WRAPEN_T (1 << 26) | ||
| 2737 | # define R200_CLAMP_T_WRAP (0 << 27) | ||
| 2738 | # define R200_CLAMP_T_MIRROR (1 << 27) | ||
| 2739 | # define R200_CLAMP_T_CLAMP_LAST (2 << 27) | ||
| 2740 | # define R200_CLAMP_T_MIRROR_CLAMP_LAST (3 << 27) | ||
| 2741 | # define R200_CLAMP_T_CLAMP_BORDER (4 << 27) | ||
| 2742 | # define R200_CLAMP_T_MIRROR_CLAMP_BORDER (5 << 27) | ||
| 2743 | # define R200_CLAMP_T_CLAMP_GL (6 << 27) | ||
| 2744 | # define R200_CLAMP_T_MIRROR_CLAMP_GL (7 << 27) | ||
| 2745 | # define R200_CLAMP_T_MASK (7 << 27) | ||
| 2746 | # define R200_KILL_LT_ZERO (1 << 30) | ||
| 2747 | # define R200_BORDER_MODE_OGL (0 << 31) | ||
| 2748 | # define R200_BORDER_MODE_D3D (1 << 31) | ||
| 2749 | #define R200_PP_TXFORMAT_0 0x2c04 | ||
| 2750 | #define R200_PP_TXFORMAT_1 0x2c24 | ||
| 2751 | #define R200_PP_TXFORMAT_2 0x2c44 | ||
| 2752 | #define R200_PP_TXFORMAT_3 0x2c64 | ||
| 2753 | #define R200_PP_TXFORMAT_4 0x2c84 | ||
| 2754 | #define R200_PP_TXFORMAT_5 0x2ca4 | ||
| 2755 | # define R200_TXFORMAT_I8 (0 << 0) | ||
| 2756 | # define R200_TXFORMAT_AI88 (1 << 0) | ||
| 2757 | # define R200_TXFORMAT_RGB332 (2 << 0) | ||
| 2758 | # define R200_TXFORMAT_ARGB1555 (3 << 0) | ||
| 2759 | # define R200_TXFORMAT_RGB565 (4 << 0) | ||
| 2760 | # define R200_TXFORMAT_ARGB4444 (5 << 0) | ||
| 2761 | # define R200_TXFORMAT_ARGB8888 (6 << 0) | ||
| 2762 | # define R200_TXFORMAT_RGBA8888 (7 << 0) | ||
| 2763 | # define R200_TXFORMAT_Y8 (8 << 0) | ||
| 2764 | # define R200_TXFORMAT_AVYU4444 (9 << 0) | ||
| 2765 | # define R200_TXFORMAT_VYUY422 (10 << 0) | ||
| 2766 | # define R200_TXFORMAT_YVYU422 (11 << 0) | ||
| 2767 | # define R200_TXFORMAT_DXT1 (12 << 0) | ||
| 2768 | # define R200_TXFORMAT_DXT23 (14 << 0) | ||
| 2769 | # define R200_TXFORMAT_DXT45 (15 << 0) | ||
| 2770 | # define R200_TXFORMAT_ABGR8888 (22 << 0) | ||
| 2771 | # define R200_TXFORMAT_FORMAT_MASK (31 << 0) | ||
| 2772 | # define R200_TXFORMAT_FORMAT_SHIFT 0 | ||
| 2773 | # define R200_TXFORMAT_ALPHA_IN_MAP (1 << 6) | ||
| 2774 | # define R200_TXFORMAT_NON_POWER2 (1 << 7) | ||
| 2775 | # define R200_TXFORMAT_WIDTH_MASK (15 << 8) | ||
| 2776 | # define R200_TXFORMAT_WIDTH_SHIFT 8 | ||
| 2777 | # define R200_TXFORMAT_HEIGHT_MASK (15 << 12) | ||
| 2778 | # define R200_TXFORMAT_HEIGHT_SHIFT 12 | ||
| 2779 | # define R200_TXFORMAT_F5_WIDTH_MASK (15 << 16) /* cube face 5 */ | ||
| 2780 | # define R200_TXFORMAT_F5_WIDTH_SHIFT 16 | ||
| 2781 | # define R200_TXFORMAT_F5_HEIGHT_MASK (15 << 20) | ||
| 2782 | # define R200_TXFORMAT_F5_HEIGHT_SHIFT 20 | ||
| 2783 | # define R200_TXFORMAT_ST_ROUTE_STQ0 (0 << 24) | ||
| 2784 | # define R200_TXFORMAT_ST_ROUTE_STQ1 (1 << 24) | ||
| 2785 | # define R200_TXFORMAT_ST_ROUTE_STQ2 (2 << 24) | ||
| 2786 | # define R200_TXFORMAT_ST_ROUTE_STQ3 (3 << 24) | ||
| 2787 | # define R200_TXFORMAT_ST_ROUTE_STQ4 (4 << 24) | ||
| 2788 | # define R200_TXFORMAT_ST_ROUTE_STQ5 (5 << 24) | ||
| 2789 | # define R200_TXFORMAT_ST_ROUTE_MASK (7 << 24) | ||
| 2790 | # define R200_TXFORMAT_ST_ROUTE_SHIFT 24 | ||
| 2791 | # define R200_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28) | ||
| 2792 | # define R200_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29) | ||
| 2793 | # define R200_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30) | ||
| 2794 | #define R200_PP_TXFORMAT_X_0 0x2c08 | ||
| 2795 | #define R200_PP_TXFORMAT_X_1 0x2c28 | ||
| 2796 | #define R200_PP_TXFORMAT_X_2 0x2c48 | ||
| 2797 | #define R200_PP_TXFORMAT_X_3 0x2c68 | ||
| 2798 | #define R200_PP_TXFORMAT_X_4 0x2c88 | ||
| 2799 | #define R200_PP_TXFORMAT_X_5 0x2ca8 | ||
| 2800 | |||
| 2801 | #define R200_PP_TXSIZE_0 0x2c0c /* NPOT only */ | ||
| 2802 | #define R200_PP_TXSIZE_1 0x2c2c /* NPOT only */ | ||
| 2803 | #define R200_PP_TXSIZE_2 0x2c4c /* NPOT only */ | ||
| 2804 | #define R200_PP_TXSIZE_3 0x2c6c /* NPOT only */ | ||
| 2805 | #define R200_PP_TXSIZE_4 0x2c8c /* NPOT only */ | ||
| 2806 | #define R200_PP_TXSIZE_5 0x2cac /* NPOT only */ | ||
| 2807 | |||
| 2808 | #define R200_PP_TXPITCH_0 0x2c10 /* NPOT only */ | ||
| 2809 | #define R200_PP_TXPITCH_1 0x2c30 /* NPOT only */ | ||
| 2810 | #define R200_PP_TXPITCH_2 0x2c50 /* NPOT only */ | ||
| 2811 | #define R200_PP_TXPITCH_3 0x2c70 /* NPOT only */ | ||
| 2812 | #define R200_PP_TXPITCH_4 0x2c90 /* NPOT only */ | ||
| 2813 | #define R200_PP_TXPITCH_5 0x2cb0 /* NPOT only */ | ||
| 2814 | |||
| 2815 | #define R200_PP_TXOFFSET_0 0x2d00 | ||
| 2816 | # define R200_TXO_ENDIAN_NO_SWAP (0 << 0) | ||
| 2817 | # define R200_TXO_ENDIAN_BYTE_SWAP (1 << 0) | ||
| 2818 | # define R200_TXO_ENDIAN_WORD_SWAP (2 << 0) | ||
| 2819 | # define R200_TXO_ENDIAN_HALFDW_SWAP (3 << 0) | ||
| 2820 | # define R200_TXO_MACRO_LINEAR (0 << 2) | ||
| 2821 | # define R200_TXO_MACRO_TILE (1 << 2) | ||
| 2822 | # define R200_TXO_MICRO_LINEAR (0 << 3) | ||
| 2823 | # define R200_TXO_MICRO_TILE (1 << 3) | ||
| 2824 | # define R200_TXO_OFFSET_MASK 0xffffffe0 | ||
| 2825 | # define R200_TXO_OFFSET_SHIFT 5 | ||
| 2826 | #define R200_PP_TXOFFSET_1 0x2d18 | ||
| 2827 | #define R200_PP_TXOFFSET_2 0x2d30 | ||
| 2828 | #define R200_PP_TXOFFSET_3 0x2d48 | ||
| 2829 | #define R200_PP_TXOFFSET_4 0x2d60 | ||
| 2830 | #define R200_PP_TXOFFSET_5 0x2d78 | ||
| 2831 | |||
| 2832 | #define R200_PP_TFACTOR_0 0x2ee0 | ||
| 2833 | #define R200_PP_TFACTOR_1 0x2ee4 | ||
| 2834 | #define R200_PP_TFACTOR_2 0x2ee8 | ||
| 2835 | #define R200_PP_TFACTOR_3 0x2eec | ||
| 2836 | #define R200_PP_TFACTOR_4 0x2ef0 | ||
| 2837 | #define R200_PP_TFACTOR_5 0x2ef4 | ||
| 2838 | |||
| 2839 | #define R200_PP_TXCBLEND_0 0x2f00 | ||
| 2840 | # define R200_TXC_ARG_A_ZERO (0) | ||
| 2841 | # define R200_TXC_ARG_A_CURRENT_COLOR (2) | ||
| 2842 | # define R200_TXC_ARG_A_CURRENT_ALPHA (3) | ||
| 2843 | # define R200_TXC_ARG_A_DIFFUSE_COLOR (4) | ||
| 2844 | # define R200_TXC_ARG_A_DIFFUSE_ALPHA (5) | ||
| 2845 | # define R200_TXC_ARG_A_SPECULAR_COLOR (6) | ||
| 2846 | # define R200_TXC_ARG_A_SPECULAR_ALPHA (7) | ||
| 2847 | # define R200_TXC_ARG_A_TFACTOR_COLOR (8) | ||
| 2848 | # define R200_TXC_ARG_A_TFACTOR_ALPHA (9) | ||
| 2849 | # define R200_TXC_ARG_A_R0_COLOR (10) | ||
| 2850 | # define R200_TXC_ARG_A_R0_ALPHA (11) | ||
| 2851 | # define R200_TXC_ARG_A_R1_COLOR (12) | ||
| 2852 | # define R200_TXC_ARG_A_R1_ALPHA (13) | ||
| 2853 | # define R200_TXC_ARG_A_R2_COLOR (14) | ||
| 2854 | # define R200_TXC_ARG_A_R2_ALPHA (15) | ||
| 2855 | # define R200_TXC_ARG_A_R3_COLOR (16) | ||
| 2856 | # define R200_TXC_ARG_A_R3_ALPHA (17) | ||
| 2857 | # define R200_TXC_ARG_A_R4_COLOR (18) | ||
| 2858 | # define R200_TXC_ARG_A_R4_ALPHA (19) | ||
| 2859 | # define R200_TXC_ARG_A_R5_COLOR (20) | ||
| 2860 | # define R200_TXC_ARG_A_R5_ALPHA (21) | ||
| 2861 | # define R200_TXC_ARG_A_TFACTOR1_COLOR (26) | ||
| 2862 | # define R200_TXC_ARG_A_TFACTOR1_ALPHA (27) | ||
| 2863 | # define R200_TXC_ARG_A_MASK (31 << 0) | ||
| 2864 | # define R200_TXC_ARG_A_SHIFT 0 | ||
| 2865 | # define R200_TXC_ARG_B_ZERO (0 << 5) | ||
| 2866 | # define R200_TXC_ARG_B_CURRENT_COLOR (2 << 5) | ||
| 2867 | # define R200_TXC_ARG_B_CURRENT_ALPHA (3 << 5) | ||
| 2868 | # define R200_TXC_ARG_B_DIFFUSE_COLOR (4 << 5) | ||
| 2869 | # define R200_TXC_ARG_B_DIFFUSE_ALPHA (5 << 5) | ||
| 2870 | # define R200_TXC_ARG_B_SPECULAR_COLOR (6 << 5) | ||
| 2871 | # define R200_TXC_ARG_B_SPECULAR_ALPHA (7 << 5) | ||
| 2872 | # define R200_TXC_ARG_B_TFACTOR_COLOR (8 << 5) | ||
| 2873 | # define R200_TXC_ARG_B_TFACTOR_ALPHA (9 << 5) | ||
| 2874 | # define R200_TXC_ARG_B_R0_COLOR (10 << 5) | ||
| 2875 | # define R200_TXC_ARG_B_R0_ALPHA (11 << 5) | ||
| 2876 | # define R200_TXC_ARG_B_R1_COLOR (12 << 5) | ||
| 2877 | # define R200_TXC_ARG_B_R1_ALPHA (13 << 5) | ||
| 2878 | # define R200_TXC_ARG_B_R2_COLOR (14 << 5) | ||
| 2879 | # define R200_TXC_ARG_B_R2_ALPHA (15 << 5) | ||
| 2880 | # define R200_TXC_ARG_B_R3_COLOR (16 << 5) | ||
| 2881 | # define R200_TXC_ARG_B_R3_ALPHA (17 << 5) | ||
| 2882 | # define R200_TXC_ARG_B_R4_COLOR (18 << 5) | ||
| 2883 | # define R200_TXC_ARG_B_R4_ALPHA (19 << 5) | ||
| 2884 | # define R200_TXC_ARG_B_R5_COLOR (20 << 5) | ||
| 2885 | # define R200_TXC_ARG_B_R5_ALPHA (21 << 5) | ||
| 2886 | # define R200_TXC_ARG_B_TFACTOR1_COLOR (26 << 5) | ||
| 2887 | # define R200_TXC_ARG_B_TFACTOR1_ALPHA (27 << 5) | ||
| 2888 | # define R200_TXC_ARG_B_MASK (31 << 5) | ||
| 2889 | # define R200_TXC_ARG_B_SHIFT 5 | ||
| 2890 | # define R200_TXC_ARG_C_ZERO (0 << 10) | ||
| 2891 | # define R200_TXC_ARG_C_CURRENT_COLOR (2 << 10) | ||
| 2892 | # define R200_TXC_ARG_C_CURRENT_ALPHA (3 << 10) | ||
| 2893 | # define R200_TXC_ARG_C_DIFFUSE_COLOR (4 << 10) | ||
| 2894 | # define R200_TXC_ARG_C_DIFFUSE_ALPHA (5 << 10) | ||
| 2895 | # define R200_TXC_ARG_C_SPECULAR_COLOR (6 << 10) | ||
| 2896 | # define R200_TXC_ARG_C_SPECULAR_ALPHA (7 << 10) | ||
| 2897 | # define R200_TXC_ARG_C_TFACTOR_COLOR (8 << 10) | ||
| 2898 | # define R200_TXC_ARG_C_TFACTOR_ALPHA (9 << 10) | ||
| 2899 | # define R200_TXC_ARG_C_R0_COLOR (10 << 10) | ||
| 2900 | # define R200_TXC_ARG_C_R0_ALPHA (11 << 10) | ||
| 2901 | # define R200_TXC_ARG_C_R1_COLOR (12 << 10) | ||
| 2902 | # define R200_TXC_ARG_C_R1_ALPHA (13 << 10) | ||
| 2903 | # define R200_TXC_ARG_C_R2_COLOR (14 << 10) | ||
| 2904 | # define R200_TXC_ARG_C_R2_ALPHA (15 << 10) | ||
| 2905 | # define R200_TXC_ARG_C_R3_COLOR (16 << 10) | ||
| 2906 | # define R200_TXC_ARG_C_R3_ALPHA (17 << 10) | ||
| 2907 | # define R200_TXC_ARG_C_R4_COLOR (18 << 10) | ||
| 2908 | # define R200_TXC_ARG_C_R4_ALPHA (19 << 10) | ||
| 2909 | # define R200_TXC_ARG_C_R5_COLOR (20 << 10) | ||
| 2910 | # define R200_TXC_ARG_C_R5_ALPHA (21 << 10) | ||
| 2911 | # define R200_TXC_ARG_C_TFACTOR1_COLOR (26 << 10) | ||
| 2912 | # define R200_TXC_ARG_C_TFACTOR1_ALPHA (27 << 10) | ||
| 2913 | # define R200_TXC_ARG_C_MASK (31 << 10) | ||
| 2914 | # define R200_TXC_ARG_C_SHIFT 10 | ||
| 2915 | # define R200_TXC_COMP_ARG_A (1 << 16) | ||
| 2916 | # define R200_TXC_COMP_ARG_A_SHIFT (16) | ||
| 2917 | # define R200_TXC_BIAS_ARG_A (1 << 17) | ||
| 2918 | # define R200_TXC_SCALE_ARG_A (1 << 18) | ||
| 2919 | # define R200_TXC_NEG_ARG_A (1 << 19) | ||
| 2920 | # define R200_TXC_COMP_ARG_B (1 << 20) | ||
| 2921 | # define R200_TXC_COMP_ARG_B_SHIFT (20) | ||
| 2922 | # define R200_TXC_BIAS_ARG_B (1 << 21) | ||
| 2923 | # define R200_TXC_SCALE_ARG_B (1 << 22) | ||
| 2924 | # define R200_TXC_NEG_ARG_B (1 << 23) | ||
| 2925 | # define R200_TXC_COMP_ARG_C (1 << 24) | ||
| 2926 | # define R200_TXC_COMP_ARG_C_SHIFT (24) | ||
| 2927 | # define R200_TXC_BIAS_ARG_C (1 << 25) | ||
| 2928 | # define R200_TXC_SCALE_ARG_C (1 << 26) | ||
| 2929 | # define R200_TXC_NEG_ARG_C (1 << 27) | ||
| 2930 | # define R200_TXC_OP_MADD (0 << 28) | ||
| 2931 | # define R200_TXC_OP_CND0 (2 << 28) | ||
| 2932 | # define R200_TXC_OP_LERP (3 << 28) | ||
| 2933 | # define R200_TXC_OP_DOT3 (4 << 28) | ||
| 2934 | # define R200_TXC_OP_DOT4 (5 << 28) | ||
| 2935 | # define R200_TXC_OP_CONDITIONAL (6 << 28) | ||
| 2936 | # define R200_TXC_OP_DOT2_ADD (7 << 28) | ||
| 2937 | # define R200_TXC_OP_MASK (7 << 28) | ||
| 2938 | #define R200_PP_TXCBLEND2_0 0x2f04 | ||
| 2939 | # define R200_TXC_TFACTOR_SEL_SHIFT 0 | ||
| 2940 | # define R200_TXC_TFACTOR_SEL_MASK 0x7 | ||
| 2941 | # define R200_TXC_TFACTOR1_SEL_SHIFT 4 | ||
| 2942 | # define R200_TXC_TFACTOR1_SEL_MASK (0x7 << 4) | ||
| 2943 | # define R200_TXC_SCALE_SHIFT 8 | ||
| 2944 | # define R200_TXC_SCALE_MASK (7 << 8) | ||
| 2945 | # define R200_TXC_SCALE_1X (0 << 8) | ||
| 2946 | # define R200_TXC_SCALE_2X (1 << 8) | ||
| 2947 | # define R200_TXC_SCALE_4X (2 << 8) | ||
| 2948 | # define R200_TXC_SCALE_8X (3 << 8) | ||
| 2949 | # define R200_TXC_SCALE_INV2 (5 << 8) | ||
| 2950 | # define R200_TXC_SCALE_INV4 (6 << 8) | ||
| 2951 | # define R200_TXC_SCALE_INV8 (7 << 8) | ||
| 2952 | # define R200_TXC_CLAMP_SHIFT 12 | ||
| 2953 | # define R200_TXC_CLAMP_MASK (3 << 12) | ||
| 2954 | # define R200_TXC_CLAMP_WRAP (0 << 12) | ||
| 2955 | # define R200_TXC_CLAMP_0_1 (1 << 12) | ||
| 2956 | # define R200_TXC_CLAMP_8_8 (2 << 12) | ||
| 2957 | # define R200_TXC_OUTPUT_REG_MASK (7 << 16) | ||
| 2958 | # define R200_TXC_OUTPUT_REG_NONE (0 << 16) | ||
| 2959 | # define R200_TXC_OUTPUT_REG_R0 (1 << 16) | ||
| 2960 | # define R200_TXC_OUTPUT_REG_R1 (2 << 16) | ||
| 2961 | # define R200_TXC_OUTPUT_REG_R2 (3 << 16) | ||
| 2962 | # define R200_TXC_OUTPUT_REG_R3 (4 << 16) | ||
| 2963 | # define R200_TXC_OUTPUT_REG_R4 (5 << 16) | ||
| 2964 | # define R200_TXC_OUTPUT_REG_R5 (6 << 16) | ||
| 2965 | # define R200_TXC_OUTPUT_MASK_MASK (7 << 20) | ||
| 2966 | # define R200_TXC_OUTPUT_MASK_RGB (0 << 20) | ||
| 2967 | # define R200_TXC_OUTPUT_MASK_RG (1 << 20) | ||
| 2968 | # define R200_TXC_OUTPUT_MASK_RB (2 << 20) | ||
| 2969 | # define R200_TXC_OUTPUT_MASK_R (3 << 20) | ||
| 2970 | # define R200_TXC_OUTPUT_MASK_GB (4 << 20) | ||
| 2971 | # define R200_TXC_OUTPUT_MASK_G (5 << 20) | ||
| 2972 | # define R200_TXC_OUTPUT_MASK_B (6 << 20) | ||
| 2973 | # define R200_TXC_OUTPUT_MASK_NONE (7 << 20) | ||
| 2974 | # define R200_TXC_REPL_NORMAL 0 | ||
| 2975 | # define R200_TXC_REPL_RED 1 | ||
| 2976 | # define R200_TXC_REPL_GREEN 2 | ||
| 2977 | # define R200_TXC_REPL_BLUE 3 | ||
| 2978 | # define R200_TXC_REPL_ARG_A_SHIFT 26 | ||
| 2979 | # define R200_TXC_REPL_ARG_A_MASK (3 << 26) | ||
| 2980 | # define R200_TXC_REPL_ARG_B_SHIFT 28 | ||
| 2981 | # define R200_TXC_REPL_ARG_B_MASK (3 << 28) | ||
| 2982 | # define R200_TXC_REPL_ARG_C_SHIFT 30 | ||
| 2983 | # define R200_TXC_REPL_ARG_C_MASK (3 << 30) | ||
| 2984 | #define R200_PP_TXABLEND_0 0x2f08 | ||
| 2985 | # define R200_TXA_ARG_A_ZERO (0) | ||
| 2986 | # define R200_TXA_ARG_A_CURRENT_ALPHA (2) /* guess */ | ||
| 2987 | # define R200_TXA_ARG_A_CURRENT_BLUE (3) /* guess */ | ||
| 2988 | # define R200_TXA_ARG_A_DIFFUSE_ALPHA (4) | ||
| 2989 | # define R200_TXA_ARG_A_DIFFUSE_BLUE (5) | ||
| 2990 | # define R200_TXA_ARG_A_SPECULAR_ALPHA (6) | ||
| 2991 | # define R200_TXA_ARG_A_SPECULAR_BLUE (7) | ||
| 2992 | # define R200_TXA_ARG_A_TFACTOR_ALPHA (8) | ||
| 2993 | # define R200_TXA_ARG_A_TFACTOR_BLUE (9) | ||
| 2994 | # define R200_TXA_ARG_A_R0_ALPHA (10) | ||
| 2995 | # define R200_TXA_ARG_A_R0_BLUE (11) | ||
| 2996 | # define R200_TXA_ARG_A_R1_ALPHA (12) | ||
| 2997 | # define R200_TXA_ARG_A_R1_BLUE (13) | ||
| 2998 | # define R200_TXA_ARG_A_R2_ALPHA (14) | ||
| 2999 | # define R200_TXA_ARG_A_R2_BLUE (15) | ||
| 3000 | # define R200_TXA_ARG_A_R3_ALPHA (16) | ||
| 3001 | # define R200_TXA_ARG_A_R3_BLUE (17) | ||
| 3002 | # define R200_TXA_ARG_A_R4_ALPHA (18) | ||
| 3003 | # define R200_TXA_ARG_A_R4_BLUE (19) | ||
| 3004 | # define R200_TXA_ARG_A_R5_ALPHA (20) | ||
| 3005 | # define R200_TXA_ARG_A_R5_BLUE (21) | ||
| 3006 | # define R200_TXA_ARG_A_TFACTOR1_ALPHA (26) | ||
| 3007 | # define R200_TXA_ARG_A_TFACTOR1_BLUE (27) | ||
| 3008 | # define R200_TXA_ARG_A_MASK (31 << 0) | ||
| 3009 | # define R200_TXA_ARG_A_SHIFT 0 | ||
| 3010 | # define R200_TXA_ARG_B_ZERO (0 << 5) | ||
| 3011 | # define R200_TXA_ARG_B_CURRENT_ALPHA (2 << 5) /* guess */ | ||
| 3012 | # define R200_TXA_ARG_B_CURRENT_BLUE (3 << 5) /* guess */ | ||
| 3013 | # define R200_TXA_ARG_B_DIFFUSE_ALPHA (4 << 5) | ||
| 3014 | # define R200_TXA_ARG_B_DIFFUSE_BLUE (5 << 5) | ||
| 3015 | # define R200_TXA_ARG_B_SPECULAR_ALPHA (6 << 5) | ||
| 3016 | # define R200_TXA_ARG_B_SPECULAR_BLUE (7 << 5) | ||
| 3017 | # define R200_TXA_ARG_B_TFACTOR_ALPHA (8 << 5) | ||
| 3018 | # define R200_TXA_ARG_B_TFACTOR_BLUE (9 << 5) | ||
| 3019 | # define R200_TXA_ARG_B_R0_ALPHA (10 << 5) | ||
| 3020 | # define R200_TXA_ARG_B_R0_BLUE (11 << 5) | ||
| 3021 | # define R200_TXA_ARG_B_R1_ALPHA (12 << 5) | ||
| 3022 | # define R200_TXA_ARG_B_R1_BLUE (13 << 5) | ||
| 3023 | # define R200_TXA_ARG_B_R2_ALPHA (14 << 5) | ||
| 3024 | # define R200_TXA_ARG_B_R2_BLUE (15 << 5) | ||
| 3025 | # define R200_TXA_ARG_B_R3_ALPHA (16 << 5) | ||
| 3026 | # define R200_TXA_ARG_B_R3_BLUE (17 << 5) | ||
| 3027 | # define R200_TXA_ARG_B_R4_ALPHA (18 << 5) | ||
| 3028 | # define R200_TXA_ARG_B_R4_BLUE (19 << 5) | ||
| 3029 | # define R200_TXA_ARG_B_R5_ALPHA (20 << 5) | ||
| 3030 | # define R200_TXA_ARG_B_R5_BLUE (21 << 5) | ||
| 3031 | # define R200_TXA_ARG_B_TFACTOR1_ALPHA (26 << 5) | ||
| 3032 | # define R200_TXA_ARG_B_TFACTOR1_BLUE (27 << 5) | ||
| 3033 | # define R200_TXA_ARG_B_MASK (31 << 5) | ||
| 3034 | # define R200_TXA_ARG_B_SHIFT 5 | ||
| 3035 | # define R200_TXA_ARG_C_ZERO (0 << 10) | ||
| 3036 | # define R200_TXA_ARG_C_CURRENT_ALPHA (2 << 10) /* guess */ | ||
| 3037 | # define R200_TXA_ARG_C_CURRENT_BLUE (3 << 10) /* guess */ | ||
| 3038 | # define R200_TXA_ARG_C_DIFFUSE_ALPHA (4 << 10) | ||
| 3039 | # define R200_TXA_ARG_C_DIFFUSE_BLUE (5 << 10) | ||
| 3040 | # define R200_TXA_ARG_C_SPECULAR_ALPHA (6 << 10) | ||
| 3041 | # define R200_TXA_ARG_C_SPECULAR_BLUE (7 << 10) | ||
| 3042 | # define R200_TXA_ARG_C_TFACTOR_ALPHA (8 << 10) | ||
| 3043 | # define R200_TXA_ARG_C_TFACTOR_BLUE (9 << 10) | ||
| 3044 | # define R200_TXA_ARG_C_R0_ALPHA (10 << 10) | ||
| 3045 | # define R200_TXA_ARG_C_R0_BLUE (11 << 10) | ||
| 3046 | # define R200_TXA_ARG_C_R1_ALPHA (12 << 10) | ||
| 3047 | # define R200_TXA_ARG_C_R1_BLUE (13 << 10) | ||
| 3048 | # define R200_TXA_ARG_C_R2_ALPHA (14 << 10) | ||
| 3049 | # define R200_TXA_ARG_C_R2_BLUE (15 << 10) | ||
| 3050 | # define R200_TXA_ARG_C_R3_ALPHA (16 << 10) | ||
| 3051 | # define R200_TXA_ARG_C_R3_BLUE (17 << 10) | ||
| 3052 | # define R200_TXA_ARG_C_R4_ALPHA (18 << 10) | ||
| 3053 | # define R200_TXA_ARG_C_R4_BLUE (19 << 10) | ||
| 3054 | # define R200_TXA_ARG_C_R5_ALPHA (20 << 10) | ||
| 3055 | # define R200_TXA_ARG_C_R5_BLUE (21 << 10) | ||
| 3056 | # define R200_TXA_ARG_C_TFACTOR1_ALPHA (26 << 10) | ||
| 3057 | # define R200_TXA_ARG_C_TFACTOR1_BLUE (27 << 10) | ||
| 3058 | # define R200_TXA_ARG_C_MASK (31 << 10) | ||
| 3059 | # define R200_TXA_ARG_C_SHIFT 10 | ||
| 3060 | # define R200_TXA_COMP_ARG_A (1 << 16) | ||
| 3061 | # define R200_TXA_COMP_ARG_A_SHIFT (16) | ||
| 3062 | # define R200_TXA_BIAS_ARG_A (1 << 17) | ||
| 3063 | # define R200_TXA_SCALE_ARG_A (1 << 18) | ||
| 3064 | # define R200_TXA_NEG_ARG_A (1 << 19) | ||
| 3065 | # define R200_TXA_COMP_ARG_B (1 << 20) | ||
| 3066 | # define R200_TXA_COMP_ARG_B_SHIFT (20) | ||
| 3067 | # define R200_TXA_BIAS_ARG_B (1 << 21) | ||
| 3068 | # define R200_TXA_SCALE_ARG_B (1 << 22) | ||
| 3069 | # define R200_TXA_NEG_ARG_B (1 << 23) | ||
| 3070 | # define R200_TXA_COMP_ARG_C (1 << 24) | ||
| 3071 | # define R200_TXA_COMP_ARG_C_SHIFT (24) | ||
| 3072 | # define R200_TXA_BIAS_ARG_C (1 << 25) | ||
| 3073 | # define R200_TXA_SCALE_ARG_C (1 << 26) | ||
| 3074 | # define R200_TXA_NEG_ARG_C (1 << 27) | ||
| 3075 | # define R200_TXA_OP_MADD (0 << 28) | ||
| 3076 | # define R200_TXA_OP_CND0 (2 << 28) | ||
| 3077 | # define R200_TXA_OP_LERP (3 << 28) | ||
| 3078 | # define R200_TXA_OP_CONDITIONAL (6 << 28) | ||
| 3079 | # define R200_TXA_OP_MASK (7 << 28) | ||
| 3080 | #define R200_PP_TXABLEND2_0 0x2f0c | ||
| 3081 | # define R200_TXA_TFACTOR_SEL_SHIFT 0 | ||
| 3082 | # define R200_TXA_TFACTOR_SEL_MASK 0x7 | ||
| 3083 | # define R200_TXA_TFACTOR1_SEL_SHIFT 4 | ||
| 3084 | # define R200_TXA_TFACTOR1_SEL_MASK (0x7 << 4) | ||
| 3085 | # define R200_TXA_SCALE_SHIFT 8 | ||
| 3086 | # define R200_TXA_SCALE_MASK (7 << 8) | ||
| 3087 | # define R200_TXA_SCALE_1X (0 << 8) | ||
| 3088 | # define R200_TXA_SCALE_2X (1 << 8) | ||
| 3089 | # define R200_TXA_SCALE_4X (2 << 8) | ||
| 3090 | # define R200_TXA_SCALE_8X (3 << 8) | ||
| 3091 | # define R200_TXA_SCALE_INV2 (5 << 8) | ||
| 3092 | # define R200_TXA_SCALE_INV4 (6 << 8) | ||
| 3093 | # define R200_TXA_SCALE_INV8 (7 << 8) | ||
| 3094 | # define R200_TXA_CLAMP_SHIFT 12 | ||
| 3095 | # define R200_TXA_CLAMP_MASK (3 << 12) | ||
| 3096 | # define R200_TXA_CLAMP_WRAP (0 << 12) | ||
| 3097 | # define R200_TXA_CLAMP_0_1 (1 << 12) | ||
| 3098 | # define R200_TXA_CLAMP_8_8 (2 << 12) | ||
| 3099 | # define R200_TXA_OUTPUT_REG_MASK (7 << 16) | ||
| 3100 | # define R200_TXA_OUTPUT_REG_NONE (0 << 16) | ||
| 3101 | # define R200_TXA_OUTPUT_REG_R0 (1 << 16) | ||
| 3102 | # define R200_TXA_OUTPUT_REG_R1 (2 << 16) | ||
| 3103 | # define R200_TXA_OUTPUT_REG_R2 (3 << 16) | ||
| 3104 | # define R200_TXA_OUTPUT_REG_R3 (4 << 16) | ||
| 3105 | # define R200_TXA_OUTPUT_REG_R4 (5 << 16) | ||
| 3106 | # define R200_TXA_OUTPUT_REG_R5 (6 << 16) | ||
| 3107 | # define R200_TXA_DOT_ALPHA (1 << 20) | ||
| 3108 | # define R200_TXA_REPL_NORMAL 0 | ||
| 3109 | # define R200_TXA_REPL_RED 1 | ||
| 3110 | # define R200_TXA_REPL_GREEN 2 | ||
| 3111 | # define R200_TXA_REPL_ARG_A_SHIFT 26 | ||
| 3112 | # define R200_TXA_REPL_ARG_A_MASK (3 << 26) | ||
| 3113 | # define R200_TXA_REPL_ARG_B_SHIFT 28 | ||
| 3114 | # define R200_TXA_REPL_ARG_B_MASK (3 << 28) | ||
| 3115 | # define R200_TXA_REPL_ARG_C_SHIFT 30 | ||
| 3116 | # define R200_TXA_REPL_ARG_C_MASK (3 << 30) | ||
| 3117 | |||
| 3118 | #define R200_SE_VTX_FMT_0 0x2088 | ||
| 3119 | # define R200_VTX_XY 0 /* always have xy */ | ||
| 3120 | # define R200_VTX_Z0 (1<<0) | ||
| 3121 | # define R200_VTX_W0 (1<<1) | ||
| 3122 | # define R200_VTX_WEIGHT_COUNT_SHIFT (2) | ||
| 3123 | # define R200_VTX_PV_MATRIX_SEL (1<<5) | ||
| 3124 | # define R200_VTX_N0 (1<<6) | ||
| 3125 | # define R200_VTX_POINT_SIZE (1<<7) | ||
| 3126 | # define R200_VTX_DISCRETE_FOG (1<<8) | ||
| 3127 | # define R200_VTX_SHININESS_0 (1<<9) | ||
| 3128 | # define R200_VTX_SHININESS_1 (1<<10) | ||
| 3129 | # define R200_VTX_COLOR_NOT_PRESENT 0 | ||
| 3130 | # define R200_VTX_PK_RGBA 1 | ||
| 3131 | # define R200_VTX_FP_RGB 2 | ||
| 3132 | # define R200_VTX_FP_RGBA 3 | ||
| 3133 | # define R200_VTX_COLOR_MASK 3 | ||
| 3134 | # define R200_VTX_COLOR_0_SHIFT 11 | ||
| 3135 | # define R200_VTX_COLOR_1_SHIFT 13 | ||
| 3136 | # define R200_VTX_COLOR_2_SHIFT 15 | ||
| 3137 | # define R200_VTX_COLOR_3_SHIFT 17 | ||
| 3138 | # define R200_VTX_COLOR_4_SHIFT 19 | ||
| 3139 | # define R200_VTX_COLOR_5_SHIFT 21 | ||
| 3140 | # define R200_VTX_COLOR_6_SHIFT 23 | ||
| 3141 | # define R200_VTX_COLOR_7_SHIFT 25 | ||
| 3142 | # define R200_VTX_XY1 (1<<28) | ||
| 3143 | # define R200_VTX_Z1 (1<<29) | ||
| 3144 | # define R200_VTX_W1 (1<<30) | ||
| 3145 | # define R200_VTX_N1 (1<<31) | ||
| 3146 | #define R200_SE_VTX_FMT_1 0x208c | ||
| 3147 | # define R200_VTX_TEX0_COMP_CNT_SHIFT 0 | ||
| 3148 | # define R200_VTX_TEX1_COMP_CNT_SHIFT 3 | ||
| 3149 | # define R200_VTX_TEX2_COMP_CNT_SHIFT 6 | ||
| 3150 | # define R200_VTX_TEX3_COMP_CNT_SHIFT 9 | ||
| 3151 | # define R200_VTX_TEX4_COMP_CNT_SHIFT 12 | ||
| 3152 | # define R200_VTX_TEX5_COMP_CNT_SHIFT 15 | ||
| 3153 | |||
| 3154 | #define R200_SE_TCL_OUTPUT_VTX_FMT_0 0x2090 | ||
| 3155 | #define R200_SE_TCL_OUTPUT_VTX_FMT_1 0x2094 | ||
| 3156 | #define R200_SE_TCL_OUTPUT_VTX_COMP_SEL 0x2250 | ||
| 3157 | # define R200_OUTPUT_XYZW (1<<0) | ||
| 3158 | # define R200_OUTPUT_COLOR_0 (1<<8) | ||
| 3159 | # define R200_OUTPUT_COLOR_1 (1<<9) | ||
| 3160 | # define R200_OUTPUT_TEX_0 (1<<16) | ||
| 3161 | # define R200_OUTPUT_TEX_1 (1<<17) | ||
| 3162 | # define R200_OUTPUT_TEX_2 (1<<18) | ||
| 3163 | # define R200_OUTPUT_TEX_3 (1<<19) | ||
| 3164 | # define R200_OUTPUT_TEX_4 (1<<20) | ||
| 3165 | # define R200_OUTPUT_TEX_5 (1<<21) | ||
| 3166 | # define R200_OUTPUT_TEX_MASK (0x3f<<16) | ||
| 3167 | # define R200_OUTPUT_DISCRETE_FOG (1<<24) | ||
| 3168 | # define R200_OUTPUT_PT_SIZE (1<<25) | ||
| 3169 | # define R200_FORCE_INORDER_PROC (1<<31) | ||
| 3170 | #define R200_PP_CNTL_X 0x2cc4 | ||
| 3171 | #define R200_PP_TXMULTI_CTL_0 0x2c1c | ||
| 3172 | #define R200_SE_VTX_STATE_CNTL 0x2180 | ||
| 3173 | # define R200_UPDATE_USER_COLOR_0_ENA_MASK (1<<16) | ||
| 3174 | |||
| 3175 | /* Registers for CP and Microcode Engine */ | ||
| 3176 | #define RADEON_CP_ME_RAM_ADDR 0x07d4 | ||
| 3177 | #define RADEON_CP_ME_RAM_RADDR 0x07d8 | ||
| 3178 | #define RADEON_CP_ME_RAM_DATAH 0x07dc | ||
| 3179 | #define RADEON_CP_ME_RAM_DATAL 0x07e0 | ||
| 3180 | |||
| 3181 | #define RADEON_CP_RB_BASE 0x0700 | ||
| 3182 | #define RADEON_CP_RB_CNTL 0x0704 | ||
| 3183 | # define RADEON_RB_BUFSZ_SHIFT 0 | ||
| 3184 | # define RADEON_RB_BUFSZ_MASK (0x3f << 0) | ||
| 3185 | # define RADEON_RB_BLKSZ_SHIFT 8 | ||
| 3186 | # define RADEON_RB_BLKSZ_MASK (0x3f << 8) | ||
| 3187 | # define RADEON_MAX_FETCH_SHIFT 18 | ||
| 3188 | # define RADEON_MAX_FETCH_MASK (0x3 << 18) | ||
| 3189 | # define RADEON_RB_NO_UPDATE (1 << 27) | ||
| 3190 | # define RADEON_RB_RPTR_WR_ENA (1 << 31) | ||
| 3191 | #define RADEON_CP_RB_RPTR_ADDR 0x070c | ||
| 3192 | #define RADEON_CP_RB_RPTR 0x0710 | ||
| 3193 | #define RADEON_CP_RB_WPTR 0x0714 | ||
| 3194 | #define RADEON_CP_RB_RPTR_WR 0x071c | ||
| 3195 | |||
| 3196 | #define RADEON_CP_IB_BASE 0x0738 | ||
| 3197 | #define RADEON_CP_IB_BUFSZ 0x073c | ||
| 3198 | |||
| 3199 | #define RADEON_CP_CSQ_CNTL 0x0740 | ||
| 3200 | # define RADEON_CSQ_CNT_PRIMARY_MASK (0xff << 0) | ||
| 3201 | # define RADEON_CSQ_PRIDIS_INDDIS (0 << 28) | ||
| 3202 | # define RADEON_CSQ_PRIPIO_INDDIS (1 << 28) | ||
| 3203 | # define RADEON_CSQ_PRIBM_INDDIS (2 << 28) | ||
| 3204 | # define RADEON_CSQ_PRIPIO_INDBM (3 << 28) | ||
| 3205 | # define RADEON_CSQ_PRIBM_INDBM (4 << 28) | ||
| 3206 | # define RADEON_CSQ_PRIPIO_INDPIO (15 << 28) | ||
| 3207 | |||
| 3208 | #define R300_CP_RESYNC_ADDR 0x778 | ||
| 3209 | #define R300_CP_RESYNC_DATA 0x77c | ||
| 3210 | |||
| 3211 | #define RADEON_CP_CSQ_STAT 0x07f8 | ||
| 3212 | # define RADEON_CSQ_RPTR_PRIMARY_MASK (0xff << 0) | ||
| 3213 | # define RADEON_CSQ_WPTR_PRIMARY_MASK (0xff << 8) | ||
| 3214 | # define RADEON_CSQ_RPTR_INDIRECT_MASK (0xff << 16) | ||
| 3215 | # define RADEON_CSQ_WPTR_INDIRECT_MASK (0xff << 24) | ||
| 3216 | #define RADEON_CP_CSQ2_STAT 0x07fc | ||
| 3217 | #define RADEON_CP_CSQ_ADDR 0x07f0 | ||
| 3218 | #define RADEON_CP_CSQ_DATA 0x07f4 | ||
| 3219 | #define RADEON_CP_CSQ_APER_PRIMARY 0x1000 | ||
| 3220 | #define RADEON_CP_CSQ_APER_INDIRECT 0x1300 | ||
| 3221 | |||
| 3222 | #define RADEON_CP_RB_WPTR_DELAY 0x0718 | ||
| 3223 | # define RADEON_PRE_WRITE_TIMER_SHIFT 0 | ||
| 3224 | # define RADEON_PRE_WRITE_LIMIT_SHIFT 23 | ||
| 3225 | #define RADEON_CP_CSQ_MODE 0x0744 | ||
| 3226 | # define RADEON_INDIRECT2_START_SHIFT 0 | ||
| 3227 | # define RADEON_INDIRECT2_START_MASK (0x7f << 0) | ||
| 3228 | # define RADEON_INDIRECT1_START_SHIFT 8 | ||
| 3229 | # define RADEON_INDIRECT1_START_MASK (0x7f << 8) | ||
| 3230 | |||
| 3231 | #define RADEON_AIC_CNTL 0x01d0 | ||
| 3232 | # define RADEON_PCIGART_TRANSLATE_EN (1 << 0) | ||
| 3233 | # define RADEON_DIS_OUT_OF_PCI_GART_ACCESS (1 << 1) | ||
| 3234 | #define RADEON_AIC_LO_ADDR 0x01dc | ||
| 3235 | #define RADEON_AIC_PT_BASE 0x01d8 | ||
| 3236 | #define RADEON_AIC_HI_ADDR 0x01e0 | ||
| 3237 | |||
| 3238 | |||
| 3239 | |||
| 3240 | /* Constants */ | ||
| 3241 | /* #define RADEON_LAST_FRAME_REG RADEON_GUI_SCRATCH_REG0 */ | ||
| 3242 | /* efine RADEON_LAST_CLEAR_REG RADEON_GUI_SCRATCH_REG2 */ | ||
| 3243 | |||
| 3244 | |||
| 3245 | |||
| 3246 | /* CP packet types */ | ||
| 3247 | #define RADEON_CP_PACKET0 0x00000000 | ||
| 3248 | #define RADEON_CP_PACKET1 0x40000000 | ||
| 3249 | #define RADEON_CP_PACKET2 0x80000000 | ||
| 3250 | #define RADEON_CP_PACKET3 0xC0000000 | ||
| 3251 | # define RADEON_CP_PACKET_MASK 0xC0000000 | ||
| 3252 | # define RADEON_CP_PACKET_COUNT_MASK 0x3fff0000 | ||
| 3253 | # define RADEON_CP_PACKET_MAX_DWORDS (1 << 12) | ||
| 3254 | # define RADEON_CP_PACKET0_REG_MASK 0x000007ff | ||
| 3255 | # define R300_CP_PACKET0_REG_MASK 0x00001fff | ||
| 3256 | # define RADEON_CP_PACKET1_REG0_MASK 0x000007ff | ||
| 3257 | # define RADEON_CP_PACKET1_REG1_MASK 0x003ff800 | ||
| 3258 | |||
| 3259 | #define RADEON_CP_PACKET0_ONE_REG_WR 0x00008000 | ||
| 3260 | |||
| 3261 | #define RADEON_CP_PACKET3_NOP 0xC0001000 | ||
| 3262 | #define RADEON_CP_PACKET3_NEXT_CHAR 0xC0001900 | ||
| 3263 | #define RADEON_CP_PACKET3_PLY_NEXTSCAN 0xC0001D00 | ||
| 3264 | #define RADEON_CP_PACKET3_SET_SCISSORS 0xC0001E00 | ||
| 3265 | #define RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM 0xC0002300 | ||
| 3266 | #define RADEON_CP_PACKET3_LOAD_MICROCODE 0xC0002400 | ||
| 3267 | #define RADEON_CP_PACKET3_WAIT_FOR_IDLE 0xC0002600 | ||
| 3268 | #define RADEON_CP_PACKET3_3D_DRAW_VBUF 0xC0002800 | ||
| 3269 | #define RADEON_CP_PACKET3_3D_DRAW_IMMD 0xC0002900 | ||
| 3270 | #define RADEON_CP_PACKET3_3D_DRAW_INDX 0xC0002A00 | ||
| 3271 | #define RADEON_CP_PACKET3_LOAD_PALETTE 0xC0002C00 | ||
| 3272 | #define R200_CP_PACKET3_3D_DRAW_IMMD_2 0xc0003500 | ||
| 3273 | #define RADEON_CP_PACKET3_3D_LOAD_VBPNTR 0xC0002F00 | ||
| 3274 | #define RADEON_CP_PACKET3_CNTL_PAINT 0xC0009100 | ||
| 3275 | #define RADEON_CP_PACKET3_CNTL_BITBLT 0xC0009200 | ||
| 3276 | #define RADEON_CP_PACKET3_CNTL_SMALLTEXT 0xC0009300 | ||
| 3277 | #define RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT 0xC0009400 | ||
| 3278 | #define RADEON_CP_PACKET3_CNTL_POLYLINE 0xC0009500 | ||
| 3279 | #define RADEON_CP_PACKET3_CNTL_POLYSCANLINES 0xC0009800 | ||
| 3280 | #define RADEON_CP_PACKET3_CNTL_PAINT_MULTI 0xC0009A00 | ||
| 3281 | #define RADEON_CP_PACKET3_CNTL_BITBLT_MULTI 0xC0009B00 | ||
| 3282 | #define RADEON_CP_PACKET3_CNTL_TRANS_BITBLT 0xC0009C00 | ||
| 3283 | |||
| 3284 | |||
| 3285 | #define RADEON_CP_VC_FRMT_XY 0x00000000 | ||
| 3286 | #define RADEON_CP_VC_FRMT_W0 0x00000001 | ||
| 3287 | #define RADEON_CP_VC_FRMT_FPCOLOR 0x00000002 | ||
| 3288 | #define RADEON_CP_VC_FRMT_FPALPHA 0x00000004 | ||
| 3289 | #define RADEON_CP_VC_FRMT_PKCOLOR 0x00000008 | ||
| 3290 | #define RADEON_CP_VC_FRMT_FPSPEC 0x00000010 | ||
| 3291 | #define RADEON_CP_VC_FRMT_FPFOG 0x00000020 | ||
| 3292 | #define RADEON_CP_VC_FRMT_PKSPEC 0x00000040 | ||
| 3293 | #define RADEON_CP_VC_FRMT_ST0 0x00000080 | ||
| 3294 | #define RADEON_CP_VC_FRMT_ST1 0x00000100 | ||
| 3295 | #define RADEON_CP_VC_FRMT_Q1 0x00000200 | ||
| 3296 | #define RADEON_CP_VC_FRMT_ST2 0x00000400 | ||
| 3297 | #define RADEON_CP_VC_FRMT_Q2 0x00000800 | ||
| 3298 | #define RADEON_CP_VC_FRMT_ST3 0x00001000 | ||
| 3299 | #define RADEON_CP_VC_FRMT_Q3 0x00002000 | ||
| 3300 | #define RADEON_CP_VC_FRMT_Q0 0x00004000 | ||
| 3301 | #define RADEON_CP_VC_FRMT_BLND_WEIGHT_CNT_MASK 0x00038000 | ||
| 3302 | #define RADEON_CP_VC_FRMT_N0 0x00040000 | ||
| 3303 | #define RADEON_CP_VC_FRMT_XY1 0x08000000 | ||
| 3304 | #define RADEON_CP_VC_FRMT_Z1 0x10000000 | ||
| 3305 | #define RADEON_CP_VC_FRMT_W1 0x20000000 | ||
| 3306 | #define RADEON_CP_VC_FRMT_N1 0x40000000 | ||
| 3307 | #define RADEON_CP_VC_FRMT_Z 0x80000000 | ||
| 3308 | |||
| 3309 | #define RADEON_CP_VC_CNTL_PRIM_TYPE_NONE 0x00000000 | ||
| 3310 | #define RADEON_CP_VC_CNTL_PRIM_TYPE_POINT 0x00000001 | ||
| 3311 | #define RADEON_CP_VC_CNTL_PRIM_TYPE_LINE 0x00000002 | ||
| 3312 | #define RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP 0x00000003 | ||
| 3313 | #define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004 | ||
| 3314 | #define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005 | ||
| 3315 | #define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006 | ||
| 3316 | #define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_TYPE_2 0x00000007 | ||
| 3317 | #define RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST 0x00000008 | ||
| 3318 | #define RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST 0x00000009 | ||
| 3319 | #define RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST 0x0000000a | ||
| 3320 | #define RADEON_CP_VC_CNTL_PRIM_WALK_IND 0x00000010 | ||
| 3321 | #define RADEON_CP_VC_CNTL_PRIM_WALK_LIST 0x00000020 | ||
| 3322 | #define RADEON_CP_VC_CNTL_PRIM_WALK_RING 0x00000030 | ||
| 3323 | #define RADEON_CP_VC_CNTL_COLOR_ORDER_BGRA 0x00000000 | ||
| 3324 | #define RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA 0x00000040 | ||
| 3325 | #define RADEON_CP_VC_CNTL_MAOS_ENABLE 0x00000080 | ||
| 3326 | #define RADEON_CP_VC_CNTL_VTX_FMT_NON_RADEON_MODE 0x00000000 | ||
| 3327 | #define RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE 0x00000100 | ||
| 3328 | #define RADEON_CP_VC_CNTL_TCL_DISABLE 0x00000000 | ||
| 3329 | #define RADEON_CP_VC_CNTL_TCL_ENABLE 0x00000200 | ||
| 3330 | #define RADEON_CP_VC_CNTL_NUM_SHIFT 16 | ||
| 3331 | |||
| 3332 | #define RADEON_VS_MATRIX_0_ADDR 0 | ||
| 3333 | #define RADEON_VS_MATRIX_1_ADDR 4 | ||
| 3334 | #define RADEON_VS_MATRIX_2_ADDR 8 | ||
| 3335 | #define RADEON_VS_MATRIX_3_ADDR 12 | ||
| 3336 | #define RADEON_VS_MATRIX_4_ADDR 16 | ||
| 3337 | #define RADEON_VS_MATRIX_5_ADDR 20 | ||
| 3338 | #define RADEON_VS_MATRIX_6_ADDR 24 | ||
| 3339 | #define RADEON_VS_MATRIX_7_ADDR 28 | ||
| 3340 | #define RADEON_VS_MATRIX_8_ADDR 32 | ||
| 3341 | #define RADEON_VS_MATRIX_9_ADDR 36 | ||
| 3342 | #define RADEON_VS_MATRIX_10_ADDR 40 | ||
| 3343 | #define RADEON_VS_MATRIX_11_ADDR 44 | ||
| 3344 | #define RADEON_VS_MATRIX_12_ADDR 48 | ||
| 3345 | #define RADEON_VS_MATRIX_13_ADDR 52 | ||
| 3346 | #define RADEON_VS_MATRIX_14_ADDR 56 | ||
| 3347 | #define RADEON_VS_MATRIX_15_ADDR 60 | ||
| 3348 | #define RADEON_VS_LIGHT_AMBIENT_ADDR 64 | ||
| 3349 | #define RADEON_VS_LIGHT_DIFFUSE_ADDR 72 | ||
| 3350 | #define RADEON_VS_LIGHT_SPECULAR_ADDR 80 | ||
| 3351 | #define RADEON_VS_LIGHT_DIRPOS_ADDR 88 | ||
| 3352 | #define RADEON_VS_LIGHT_HWVSPOT_ADDR 96 | ||
| 3353 | #define RADEON_VS_LIGHT_ATTENUATION_ADDR 104 | ||
| 3354 | #define RADEON_VS_MATRIX_EYE2CLIP_ADDR 112 | ||
| 3355 | #define RADEON_VS_UCP_ADDR 116 | ||
| 3356 | #define RADEON_VS_GLOBAL_AMBIENT_ADDR 122 | ||
| 3357 | #define RADEON_VS_FOG_PARAM_ADDR 123 | ||
| 3358 | #define RADEON_VS_EYE_VECTOR_ADDR 124 | ||
| 3359 | |||
| 3360 | #define RADEON_SS_LIGHT_DCD_ADDR 0 | ||
| 3361 | #define RADEON_SS_LIGHT_SPOT_EXPONENT_ADDR 8 | ||
| 3362 | #define RADEON_SS_LIGHT_SPOT_CUTOFF_ADDR 16 | ||
| 3363 | #define RADEON_SS_LIGHT_SPECULAR_THRESH_ADDR 24 | ||
| 3364 | #define RADEON_SS_LIGHT_RANGE_CUTOFF_ADDR 32 | ||
| 3365 | #define RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR 48 | ||
| 3366 | #define RADEON_SS_VERT_GUARD_DISCARD_ADJ_ADDR 49 | ||
| 3367 | #define RADEON_SS_HORZ_GUARD_CLIP_ADJ_ADDR 50 | ||
| 3368 | #define RADEON_SS_HORZ_GUARD_DISCARD_ADJ_ADDR 51 | ||
| 3369 | #define RADEON_SS_SHININESS 60 | ||
| 3370 | |||
| 3371 | #define RADEON_TV_MASTER_CNTL 0x0800 | ||
| 3372 | # define RADEON_TV_ASYNC_RST (1 << 0) | ||
| 3373 | # define RADEON_CRT_ASYNC_RST (1 << 1) | ||
| 3374 | # define RADEON_RESTART_PHASE_FIX (1 << 3) | ||
| 3375 | # define RADEON_TV_FIFO_ASYNC_RST (1 << 4) | ||
| 3376 | # define RADEON_VIN_ASYNC_RST (1 << 5) | ||
| 3377 | # define RADEON_AUD_ASYNC_RST (1 << 6) | ||
| 3378 | # define RADEON_DVS_ASYNC_RST (1 << 7) | ||
| 3379 | # define RADEON_CRT_FIFO_CE_EN (1 << 9) | ||
| 3380 | # define RADEON_TV_FIFO_CE_EN (1 << 10) | ||
| 3381 | # define RADEON_RE_SYNC_NOW_SEL_MASK (3 << 14) | ||
| 3382 | # define RADEON_TVCLK_ALWAYS_ONb (1 << 30) | ||
| 3383 | # define RADEON_TV_ON (1 << 31) | ||
| 3384 | #define RADEON_TV_PRE_DAC_MUX_CNTL 0x0888 | ||
| 3385 | # define RADEON_Y_RED_EN (1 << 0) | ||
| 3386 | # define RADEON_C_GRN_EN (1 << 1) | ||
| 3387 | # define RADEON_CMP_BLU_EN (1 << 2) | ||
| 3388 | # define RADEON_DAC_DITHER_EN (1 << 3) | ||
| 3389 | # define RADEON_RED_MX_FORCE_DAC_DATA (6 << 4) | ||
| 3390 | # define RADEON_GRN_MX_FORCE_DAC_DATA (6 << 8) | ||
| 3391 | # define RADEON_BLU_MX_FORCE_DAC_DATA (6 << 12) | ||
| 3392 | # define RADEON_TV_FORCE_DAC_DATA_SHIFT 16 | ||
| 3393 | #define RADEON_TV_RGB_CNTL 0x0804 | ||
| 3394 | # define RADEON_SWITCH_TO_BLUE (1 << 4) | ||
| 3395 | # define RADEON_RGB_DITHER_EN (1 << 5) | ||
| 3396 | # define RADEON_RGB_SRC_SEL_MASK (3 << 8) | ||
| 3397 | # define RADEON_RGB_SRC_SEL_CRTC1 (0 << 8) | ||
| 3398 | # define RADEON_RGB_SRC_SEL_RMX (1 << 8) | ||
| 3399 | # define RADEON_RGB_SRC_SEL_CRTC2 (2 << 8) | ||
| 3400 | # define RADEON_RGB_CONVERT_BY_PASS (1 << 10) | ||
| 3401 | # define RADEON_UVRAM_READ_MARGIN_SHIFT 16 | ||
| 3402 | # define RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT 20 | ||
| 3403 | # define RADEON_TVOUT_SCALE_EN (1 << 26) | ||
| 3404 | #define RADEON_TV_SYNC_CNTL 0x0808 | ||
| 3405 | # define RADEON_SYNC_OE (1 << 0) | ||
| 3406 | # define RADEON_SYNC_OUT (1 << 1) | ||
| 3407 | # define RADEON_SYNC_IN (1 << 2) | ||
| 3408 | # define RADEON_SYNC_PUB (1 << 3) | ||
| 3409 | # define RADEON_SYNC_PD (1 << 4) | ||
| 3410 | # define RADEON_TV_SYNC_IO_DRIVE (1 << 5) | ||
| 3411 | #define RADEON_TV_HTOTAL 0x080c | ||
| 3412 | #define RADEON_TV_HDISP 0x0810 | ||
| 3413 | #define RADEON_TV_HSTART 0x0818 | ||
| 3414 | #define RADEON_TV_HCOUNT 0x081C | ||
| 3415 | #define RADEON_TV_VTOTAL 0x0820 | ||
| 3416 | #define RADEON_TV_VDISP 0x0824 | ||
| 3417 | #define RADEON_TV_VCOUNT 0x0828 | ||
| 3418 | #define RADEON_TV_FTOTAL 0x082c | ||
| 3419 | #define RADEON_TV_FCOUNT 0x0830 | ||
| 3420 | #define RADEON_TV_FRESTART 0x0834 | ||
| 3421 | #define RADEON_TV_HRESTART 0x0838 | ||
| 3422 | #define RADEON_TV_VRESTART 0x083c | ||
| 3423 | #define RADEON_TV_HOST_READ_DATA 0x0840 | ||
| 3424 | #define RADEON_TV_HOST_WRITE_DATA 0x0844 | ||
| 3425 | #define RADEON_TV_HOST_RD_WT_CNTL 0x0848 | ||
| 3426 | # define RADEON_HOST_FIFO_RD (1 << 12) | ||
| 3427 | # define RADEON_HOST_FIFO_RD_ACK (1 << 13) | ||
| 3428 | # define RADEON_HOST_FIFO_WT (1 << 14) | ||
| 3429 | # define RADEON_HOST_FIFO_WT_ACK (1 << 15) | ||
| 3430 | #define RADEON_TV_VSCALER_CNTL1 0x084c | ||
| 3431 | # define RADEON_UV_INC_MASK 0xffff | ||
| 3432 | # define RADEON_UV_INC_SHIFT 0 | ||
| 3433 | # define RADEON_Y_W_EN (1 << 24) | ||
| 3434 | # define RADEON_RESTART_FIELD (1 << 29) /* restart on field 0 */ | ||
| 3435 | # define RADEON_Y_DEL_W_SIG_SHIFT 26 | ||
| 3436 | #define RADEON_TV_TIMING_CNTL 0x0850 | ||
| 3437 | # define RADEON_H_INC_MASK 0xfff | ||
| 3438 | # define RADEON_H_INC_SHIFT 0 | ||
| 3439 | # define RADEON_REQ_Y_FIRST (1 << 19) | ||
| 3440 | # define RADEON_FORCE_BURST_ALWAYS (1 << 21) | ||
| 3441 | # define RADEON_UV_POST_SCALE_BYPASS (1 << 23) | ||
| 3442 | # define RADEON_UV_OUTPUT_POST_SCALE_SHIFT 24 | ||
| 3443 | #define RADEON_TV_VSCALER_CNTL2 0x0854 | ||
| 3444 | # define RADEON_DITHER_MODE (1 << 0) | ||
| 3445 | # define RADEON_Y_OUTPUT_DITHER_EN (1 << 1) | ||
| 3446 | # define RADEON_UV_OUTPUT_DITHER_EN (1 << 2) | ||
| 3447 | # define RADEON_UV_TO_BUF_DITHER_EN (1 << 3) | ||
| 3448 | #define RADEON_TV_Y_FALL_CNTL 0x0858 | ||
| 3449 | # define RADEON_Y_FALL_PING_PONG (1 << 16) | ||
| 3450 | # define RADEON_Y_COEF_EN (1 << 17) | ||
| 3451 | #define RADEON_TV_Y_RISE_CNTL 0x085c | ||
| 3452 | # define RADEON_Y_RISE_PING_PONG (1 << 16) | ||
| 3453 | #define RADEON_TV_Y_SAW_TOOTH_CNTL 0x0860 | ||
| 3454 | #define RADEON_TV_UPSAMP_AND_GAIN_CNTL 0x0864 | ||
| 3455 | # define RADEON_YUPSAMP_EN (1 << 0) | ||
| 3456 | # define RADEON_UVUPSAMP_EN (1 << 2) | ||
| 3457 | #define RADEON_TV_GAIN_LIMIT_SETTINGS 0x0868 | ||
| 3458 | # define RADEON_Y_GAIN_LIMIT_SHIFT 0 | ||
| 3459 | # define RADEON_UV_GAIN_LIMIT_SHIFT 16 | ||
| 3460 | #define RADEON_TV_LINEAR_GAIN_SETTINGS 0x086c | ||
| 3461 | # define RADEON_Y_GAIN_SHIFT 0 | ||
| 3462 | # define RADEON_UV_GAIN_SHIFT 16 | ||
| 3463 | #define RADEON_TV_MODULATOR_CNTL1 0x0870 | ||
| 3464 | # define RADEON_YFLT_EN (1 << 2) | ||
| 3465 | # define RADEON_UVFLT_EN (1 << 3) | ||
| 3466 | # define RADEON_ALT_PHASE_EN (1 << 6) | ||
| 3467 | # define RADEON_SYNC_TIP_LEVEL (1 << 7) | ||
| 3468 | # define RADEON_BLANK_LEVEL_SHIFT 8 | ||
| 3469 | # define RADEON_SET_UP_LEVEL_SHIFT 16 | ||
| 3470 | # define RADEON_SLEW_RATE_LIMIT (1 << 23) | ||
| 3471 | # define RADEON_CY_FILT_BLEND_SHIFT 28 | ||
| 3472 | #define RADEON_TV_MODULATOR_CNTL2 0x0874 | ||
| 3473 | # define RADEON_TV_U_BURST_LEVEL_MASK 0x1ff | ||
| 3474 | # define RADEON_TV_V_BURST_LEVEL_MASK 0x1ff | ||
| 3475 | # define RADEON_TV_V_BURST_LEVEL_SHIFT 16 | ||
| 3476 | #define RADEON_TV_CRC_CNTL 0x0890 | ||
| 3477 | #define RADEON_TV_UV_ADR 0x08ac | ||
| 3478 | # define RADEON_MAX_UV_ADR_MASK 0x000000ff | ||
| 3479 | # define RADEON_MAX_UV_ADR_SHIFT 0 | ||
| 3480 | # define RADEON_TABLE1_BOT_ADR_MASK 0x0000ff00 | ||
| 3481 | # define RADEON_TABLE1_BOT_ADR_SHIFT 8 | ||
| 3482 | # define RADEON_TABLE3_TOP_ADR_MASK 0x00ff0000 | ||
| 3483 | # define RADEON_TABLE3_TOP_ADR_SHIFT 16 | ||
| 3484 | # define RADEON_HCODE_TABLE_SEL_MASK 0x06000000 | ||
| 3485 | # define RADEON_HCODE_TABLE_SEL_SHIFT 25 | ||
| 3486 | # define RADEON_VCODE_TABLE_SEL_MASK 0x18000000 | ||
| 3487 | # define RADEON_VCODE_TABLE_SEL_SHIFT 27 | ||
| 3488 | # define RADEON_TV_MAX_FIFO_ADDR 0x1a7 | ||
| 3489 | # define RADEON_TV_MAX_FIFO_ADDR_INTERNAL 0x1ff | ||
| 3490 | #define RADEON_TV_PLL_FINE_CNTL 0x0020 /* PLL */ | ||
| 3491 | #define RADEON_TV_PLL_CNTL 0x0021 /* PLL */ | ||
| 3492 | # define RADEON_TV_M0LO_MASK 0xff | ||
| 3493 | # define RADEON_TV_M0HI_MASK 0x7 | ||
| 3494 | # define RADEON_TV_M0HI_SHIFT 18 | ||
| 3495 | # define RADEON_TV_N0LO_MASK 0x1ff | ||
| 3496 | # define RADEON_TV_N0LO_SHIFT 8 | ||
| 3497 | # define RADEON_TV_N0HI_MASK 0x3 | ||
| 3498 | # define RADEON_TV_N0HI_SHIFT 21 | ||
| 3499 | # define RADEON_TV_P_MASK 0xf | ||
| 3500 | # define RADEON_TV_P_SHIFT 24 | ||
| 3501 | # define RADEON_TV_SLIP_EN (1 << 23) | ||
| 3502 | # define RADEON_TV_DTO_EN (1 << 28) | ||
| 3503 | #define RADEON_TV_PLL_CNTL1 0x0022 /* PLL */ | ||
| 3504 | # define RADEON_TVPLL_RESET (1 << 1) | ||
| 3505 | # define RADEON_TVPLL_SLEEP (1 << 3) | ||
| 3506 | # define RADEON_TVPLL_REFCLK_SEL (1 << 4) | ||
| 3507 | # define RADEON_TVPCP_SHIFT 8 | ||
| 3508 | # define RADEON_TVPCP_MASK (7 << 8) | ||
| 3509 | # define RADEON_TVPVG_SHIFT 11 | ||
| 3510 | # define RADEON_TVPVG_MASK (7 << 11) | ||
| 3511 | # define RADEON_TVPDC_SHIFT 14 | ||
| 3512 | # define RADEON_TVPDC_MASK (3 << 14) | ||
| 3513 | # define RADEON_TVPLL_TEST_DIS (1 << 31) | ||
| 3514 | # define RADEON_TVCLK_SRC_SEL_TVPLL (1 << 30) | ||
| 3515 | |||
| 3516 | #define RS400_DISP2_REQ_CNTL1 0xe30 | ||
| 3517 | # define RS400_DISP2_START_REQ_LEVEL_SHIFT 0 | ||
| 3518 | # define RS400_DISP2_START_REQ_LEVEL_MASK 0x3ff | ||
| 3519 | # define RS400_DISP2_STOP_REQ_LEVEL_SHIFT 12 | ||
| 3520 | # define RS400_DISP2_STOP_REQ_LEVEL_MASK 0x3ff | ||
| 3521 | # define RS400_DISP2_ALLOW_FID_LEVEL_SHIFT 22 | ||
| 3522 | # define RS400_DISP2_ALLOW_FID_LEVEL_MASK 0x3ff | ||
| 3523 | #define RS400_DISP2_REQ_CNTL2 0xe34 | ||
| 3524 | # define RS400_DISP2_CRITICAL_POINT_START_SHIFT 12 | ||
| 3525 | # define RS400_DISP2_CRITICAL_POINT_START_MASK 0x3ff | ||
| 3526 | # define RS400_DISP2_CRITICAL_POINT_STOP_SHIFT 22 | ||
| 3527 | # define RS400_DISP2_CRITICAL_POINT_STOP_MASK 0x3ff | ||
| 3528 | #define RS400_DMIF_MEM_CNTL1 0xe38 | ||
| 3529 | # define RS400_DISP2_START_ADR_SHIFT 0 | ||
| 3530 | # define RS400_DISP2_START_ADR_MASK 0x3ff | ||
| 3531 | # define RS400_DISP1_CRITICAL_POINT_START_SHIFT 12 | ||
| 3532 | # define RS400_DISP1_CRITICAL_POINT_START_MASK 0x3ff | ||
| 3533 | # define RS400_DISP1_CRITICAL_POINT_STOP_SHIFT 22 | ||
| 3534 | # define RS400_DISP1_CRITICAL_POINT_STOP_MASK 0x3ff | ||
| 3535 | #define RS400_DISP1_REQ_CNTL1 0xe3c | ||
| 3536 | # define RS400_DISP1_START_REQ_LEVEL_SHIFT 0 | ||
| 3537 | # define RS400_DISP1_START_REQ_LEVEL_MASK 0x3ff | ||
| 3538 | # define RS400_DISP1_STOP_REQ_LEVEL_SHIFT 12 | ||
| 3539 | # define RS400_DISP1_STOP_REQ_LEVEL_MASK 0x3ff | ||
| 3540 | # define RS400_DISP1_ALLOW_FID_LEVEL_SHIFT 22 | ||
| 3541 | # define RS400_DISP1_ALLOW_FID_LEVEL_MASK 0x3ff | ||
| 3542 | |||
| 3543 | #define RADEON_PCIE_INDEX 0x0030 | ||
| 3544 | #define RADEON_PCIE_DATA 0x0034 | ||
| 3545 | #define RADEON_PCIE_TX_GART_CNTL 0x10 | ||
| 3546 | # define RADEON_PCIE_TX_GART_EN (1 << 0) | ||
| 3547 | # define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_PASS_THRU (0 << 1) | ||
| 3548 | # define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_CLAMP_LO (1 << 1) | ||
| 3549 | # define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD (3 << 1) | ||
| 3550 | # define RADEON_PCIE_TX_GART_MODE_32_128_CACHE (0 << 3) | ||
| 3551 | # define RADEON_PCIE_TX_GART_MODE_8_4_128_CACHE (1 << 3) | ||
| 3552 | # define RADEON_PCIE_TX_GART_CHK_RW_VALID_EN (1 << 5) | ||
| 3553 | # define RADEON_PCIE_TX_GART_INVALIDATE_TLB (1 << 8) | ||
| 3554 | #define RADEON_PCIE_TX_DISCARD_RD_ADDR_LO 0x11 | ||
| 3555 | #define RADEON_PCIE_TX_DISCARD_RD_ADDR_HI 0x12 | ||
| 3556 | #define RADEON_PCIE_TX_GART_BASE 0x13 | ||
| 3557 | #define RADEON_PCIE_TX_GART_START_LO 0x14 | ||
| 3558 | #define RADEON_PCIE_TX_GART_START_HI 0x15 | ||
| 3559 | #define RADEON_PCIE_TX_GART_END_LO 0x16 | ||
| 3560 | #define RADEON_PCIE_TX_GART_END_HI 0x17 | ||
| 3561 | #define RADEON_PCIE_TX_GART_ERROR 0x18 | ||
| 3562 | |||
| 3563 | #define RADEON_SCRATCH_REG0 0x15e0 | ||
| 3564 | #define RADEON_SCRATCH_REG1 0x15e4 | ||
| 3565 | #define RADEON_SCRATCH_REG2 0x15e8 | ||
| 3566 | #define RADEON_SCRATCH_REG3 0x15ec | ||
| 3567 | #define RADEON_SCRATCH_REG4 0x15f0 | ||
| 3568 | #define RADEON_SCRATCH_REG5 0x15f4 | ||
| 3569 | |||
| 3570 | #endif | ||
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c new file mode 100644 index 000000000000..a853261d1881 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_ring.c | |||
| @@ -0,0 +1,485 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include <linux/seq_file.h> | ||
| 29 | #include "drmP.h" | ||
| 30 | #include "radeon_drm.h" | ||
| 31 | #include "radeon_reg.h" | ||
| 32 | #include "radeon.h" | ||
| 33 | #include "atom.h" | ||
| 34 | |||
| 35 | int radeon_debugfs_ib_init(struct radeon_device *rdev); | ||
| 36 | |||
| 37 | /* | ||
| 38 | * IB. | ||
| 39 | */ | ||
| 40 | int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib) | ||
| 41 | { | ||
| 42 | struct radeon_fence *fence; | ||
| 43 | struct radeon_ib *nib; | ||
| 44 | unsigned long i; | ||
| 45 | int r = 0; | ||
| 46 | |||
| 47 | *ib = NULL; | ||
| 48 | r = radeon_fence_create(rdev, &fence); | ||
| 49 | if (r) { | ||
| 50 | DRM_ERROR("failed to create fence for new IB\n"); | ||
| 51 | return r; | ||
| 52 | } | ||
| 53 | mutex_lock(&rdev->ib_pool.mutex); | ||
| 54 | i = find_first_zero_bit(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE); | ||
| 55 | if (i < RADEON_IB_POOL_SIZE) { | ||
| 56 | set_bit(i, rdev->ib_pool.alloc_bm); | ||
| 57 | rdev->ib_pool.ibs[i].length_dw = 0; | ||
| 58 | *ib = &rdev->ib_pool.ibs[i]; | ||
| 59 | goto out; | ||
| 60 | } | ||
| 61 | if (list_empty(&rdev->ib_pool.scheduled_ibs)) { | ||
| 62 | /* we go do nothings here */ | ||
| 63 | DRM_ERROR("all IB allocated none scheduled.\n"); | ||
| 64 | r = -EINVAL; | ||
| 65 | goto out; | ||
| 66 | } | ||
| 67 | /* get the first ib on the scheduled list */ | ||
| 68 | nib = list_entry(rdev->ib_pool.scheduled_ibs.next, | ||
| 69 | struct radeon_ib, list); | ||
| 70 | if (nib->fence == NULL) { | ||
| 71 | /* we go do nothings here */ | ||
| 72 | DRM_ERROR("IB %lu scheduled without a fence.\n", nib->idx); | ||
| 73 | r = -EINVAL; | ||
| 74 | goto out; | ||
| 75 | } | ||
| 76 | r = radeon_fence_wait(nib->fence, false); | ||
| 77 | if (r) { | ||
| 78 | DRM_ERROR("radeon: IB(%lu:0x%016lX:%u)\n", nib->idx, | ||
| 79 | (unsigned long)nib->gpu_addr, nib->length_dw); | ||
| 80 | DRM_ERROR("radeon: GPU lockup detected, fail to get a IB\n"); | ||
| 81 | goto out; | ||
| 82 | } | ||
| 83 | radeon_fence_unref(&nib->fence); | ||
| 84 | nib->length_dw = 0; | ||
| 85 | list_del(&nib->list); | ||
| 86 | INIT_LIST_HEAD(&nib->list); | ||
| 87 | *ib = nib; | ||
| 88 | out: | ||
| 89 | mutex_unlock(&rdev->ib_pool.mutex); | ||
| 90 | if (r) { | ||
| 91 | radeon_fence_unref(&fence); | ||
| 92 | } else { | ||
| 93 | (*ib)->fence = fence; | ||
| 94 | } | ||
| 95 | return r; | ||
| 96 | } | ||
| 97 | |||
| 98 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib) | ||
| 99 | { | ||
| 100 | struct radeon_ib *tmp = *ib; | ||
| 101 | |||
| 102 | *ib = NULL; | ||
| 103 | if (tmp == NULL) { | ||
| 104 | return; | ||
| 105 | } | ||
| 106 | mutex_lock(&rdev->ib_pool.mutex); | ||
| 107 | if (!list_empty(&tmp->list) && !radeon_fence_signaled(tmp->fence)) { | ||
| 108 | /* IB is scheduled & not signaled don't do anythings */ | ||
| 109 | mutex_unlock(&rdev->ib_pool.mutex); | ||
| 110 | return; | ||
| 111 | } | ||
| 112 | list_del(&tmp->list); | ||
| 113 | INIT_LIST_HEAD(&tmp->list); | ||
| 114 | if (tmp->fence) { | ||
| 115 | radeon_fence_unref(&tmp->fence); | ||
| 116 | } | ||
| 117 | tmp->length_dw = 0; | ||
| 118 | clear_bit(tmp->idx, rdev->ib_pool.alloc_bm); | ||
| 119 | mutex_unlock(&rdev->ib_pool.mutex); | ||
| 120 | } | ||
| 121 | |||
| 122 | static void radeon_ib_align(struct radeon_device *rdev, struct radeon_ib *ib) | ||
| 123 | { | ||
| 124 | while ((ib->length_dw & rdev->cp.align_mask)) { | ||
| 125 | ib->ptr[ib->length_dw++] = PACKET2(0); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | static void radeon_ib_cpu_flush(struct radeon_device *rdev, | ||
| 130 | struct radeon_ib *ib) | ||
| 131 | { | ||
| 132 | unsigned long tmp; | ||
| 133 | unsigned i; | ||
| 134 | |||
| 135 | /* To force CPU cache flush ugly but seems reliable */ | ||
| 136 | for (i = 0; i < ib->length_dw; i += (rdev->cp.align_mask + 1)) { | ||
| 137 | tmp = readl(&ib->ptr[i]); | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) | ||
| 142 | { | ||
| 143 | int r = 0; | ||
| 144 | |||
| 145 | mutex_lock(&rdev->ib_pool.mutex); | ||
| 146 | radeon_ib_align(rdev, ib); | ||
| 147 | radeon_ib_cpu_flush(rdev, ib); | ||
| 148 | if (!ib->length_dw || !rdev->cp.ready) { | ||
| 149 | /* TODO: Nothings in the ib we should report. */ | ||
| 150 | mutex_unlock(&rdev->ib_pool.mutex); | ||
| 151 | DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx); | ||
| 152 | return -EINVAL; | ||
| 153 | } | ||
| 154 | /* 64 dwords should be enought for fence too */ | ||
| 155 | r = radeon_ring_lock(rdev, 64); | ||
| 156 | if (r) { | ||
| 157 | DRM_ERROR("radeon: scheduling IB failled (%d).\n", r); | ||
| 158 | mutex_unlock(&rdev->ib_pool.mutex); | ||
| 159 | return r; | ||
| 160 | } | ||
| 161 | radeon_ring_write(rdev, PACKET0(RADEON_CP_IB_BASE, 1)); | ||
| 162 | radeon_ring_write(rdev, ib->gpu_addr); | ||
| 163 | radeon_ring_write(rdev, ib->length_dw); | ||
| 164 | radeon_fence_emit(rdev, ib->fence); | ||
| 165 | radeon_ring_unlock_commit(rdev); | ||
| 166 | list_add_tail(&ib->list, &rdev->ib_pool.scheduled_ibs); | ||
| 167 | mutex_unlock(&rdev->ib_pool.mutex); | ||
| 168 | return 0; | ||
| 169 | } | ||
| 170 | |||
| 171 | int radeon_ib_pool_init(struct radeon_device *rdev) | ||
| 172 | { | ||
| 173 | void *ptr; | ||
| 174 | uint64_t gpu_addr; | ||
| 175 | int i; | ||
| 176 | int r = 0; | ||
| 177 | |||
| 178 | /* Allocate 1M object buffer */ | ||
| 179 | INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs); | ||
| 180 | r = radeon_object_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024, | ||
| 181 | true, RADEON_GEM_DOMAIN_GTT, | ||
| 182 | false, &rdev->ib_pool.robj); | ||
| 183 | if (r) { | ||
| 184 | DRM_ERROR("radeon: failed to ib pool (%d).\n", r); | ||
| 185 | return r; | ||
| 186 | } | ||
| 187 | r = radeon_object_pin(rdev->ib_pool.robj, RADEON_GEM_DOMAIN_GTT, &gpu_addr); | ||
| 188 | if (r) { | ||
| 189 | DRM_ERROR("radeon: failed to pin ib pool (%d).\n", r); | ||
| 190 | return r; | ||
| 191 | } | ||
| 192 | r = radeon_object_kmap(rdev->ib_pool.robj, &ptr); | ||
| 193 | if (r) { | ||
| 194 | DRM_ERROR("radeon: failed to map ib poll (%d).\n", r); | ||
| 195 | return r; | ||
| 196 | } | ||
| 197 | for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { | ||
| 198 | unsigned offset; | ||
| 199 | |||
| 200 | offset = i * 64 * 1024; | ||
| 201 | rdev->ib_pool.ibs[i].gpu_addr = gpu_addr + offset; | ||
| 202 | rdev->ib_pool.ibs[i].ptr = ptr + offset; | ||
| 203 | rdev->ib_pool.ibs[i].idx = i; | ||
| 204 | rdev->ib_pool.ibs[i].length_dw = 0; | ||
| 205 | INIT_LIST_HEAD(&rdev->ib_pool.ibs[i].list); | ||
| 206 | } | ||
| 207 | bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE); | ||
| 208 | rdev->ib_pool.ready = true; | ||
| 209 | DRM_INFO("radeon: ib pool ready.\n"); | ||
| 210 | if (radeon_debugfs_ib_init(rdev)) { | ||
| 211 | DRM_ERROR("Failed to register debugfs file for IB !\n"); | ||
| 212 | } | ||
| 213 | return r; | ||
| 214 | } | ||
| 215 | |||
| 216 | void radeon_ib_pool_fini(struct radeon_device *rdev) | ||
| 217 | { | ||
| 218 | if (!rdev->ib_pool.ready) { | ||
| 219 | return; | ||
| 220 | } | ||
| 221 | mutex_lock(&rdev->ib_pool.mutex); | ||
| 222 | bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE); | ||
| 223 | if (rdev->ib_pool.robj) { | ||
| 224 | radeon_object_kunmap(rdev->ib_pool.robj); | ||
| 225 | radeon_object_unref(&rdev->ib_pool.robj); | ||
| 226 | rdev->ib_pool.robj = NULL; | ||
| 227 | } | ||
| 228 | mutex_unlock(&rdev->ib_pool.mutex); | ||
| 229 | } | ||
| 230 | |||
| 231 | int radeon_ib_test(struct radeon_device *rdev) | ||
| 232 | { | ||
| 233 | struct radeon_ib *ib; | ||
| 234 | uint32_t scratch; | ||
| 235 | uint32_t tmp = 0; | ||
| 236 | unsigned i; | ||
| 237 | int r; | ||
| 238 | |||
| 239 | r = radeon_scratch_get(rdev, &scratch); | ||
| 240 | if (r) { | ||
| 241 | DRM_ERROR("radeon: failed to get scratch reg (%d).\n", r); | ||
| 242 | return r; | ||
| 243 | } | ||
| 244 | WREG32(scratch, 0xCAFEDEAD); | ||
| 245 | r = radeon_ib_get(rdev, &ib); | ||
| 246 | if (r) { | ||
| 247 | return r; | ||
| 248 | } | ||
| 249 | ib->ptr[0] = PACKET0(scratch, 0); | ||
| 250 | ib->ptr[1] = 0xDEADBEEF; | ||
| 251 | ib->ptr[2] = PACKET2(0); | ||
| 252 | ib->ptr[3] = PACKET2(0); | ||
| 253 | ib->ptr[4] = PACKET2(0); | ||
| 254 | ib->ptr[5] = PACKET2(0); | ||
| 255 | ib->ptr[6] = PACKET2(0); | ||
| 256 | ib->ptr[7] = PACKET2(0); | ||
| 257 | ib->length_dw = 8; | ||
| 258 | r = radeon_ib_schedule(rdev, ib); | ||
| 259 | if (r) { | ||
| 260 | radeon_scratch_free(rdev, scratch); | ||
| 261 | radeon_ib_free(rdev, &ib); | ||
| 262 | return r; | ||
| 263 | } | ||
| 264 | r = radeon_fence_wait(ib->fence, false); | ||
| 265 | if (r) { | ||
| 266 | return r; | ||
| 267 | } | ||
| 268 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 269 | tmp = RREG32(scratch); | ||
| 270 | if (tmp == 0xDEADBEEF) { | ||
| 271 | break; | ||
| 272 | } | ||
| 273 | DRM_UDELAY(1); | ||
| 274 | } | ||
| 275 | if (i < rdev->usec_timeout) { | ||
| 276 | DRM_INFO("ib test succeeded in %u usecs\n", i); | ||
| 277 | } else { | ||
| 278 | DRM_ERROR("radeon: ib test failed (sracth(0x%04X)=0x%08X)\n", | ||
| 279 | scratch, tmp); | ||
| 280 | r = -EINVAL; | ||
| 281 | } | ||
| 282 | radeon_scratch_free(rdev, scratch); | ||
| 283 | radeon_ib_free(rdev, &ib); | ||
| 284 | return r; | ||
| 285 | } | ||
| 286 | |||
| 287 | |||
| 288 | /* | ||
| 289 | * Ring. | ||
| 290 | */ | ||
| 291 | void radeon_ring_free_size(struct radeon_device *rdev) | ||
| 292 | { | ||
| 293 | rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR); | ||
| 294 | /* This works because ring_size is a power of 2 */ | ||
| 295 | rdev->cp.ring_free_dw = (rdev->cp.rptr + (rdev->cp.ring_size / 4)); | ||
| 296 | rdev->cp.ring_free_dw -= rdev->cp.wptr; | ||
| 297 | rdev->cp.ring_free_dw &= rdev->cp.ptr_mask; | ||
| 298 | if (!rdev->cp.ring_free_dw) { | ||
| 299 | rdev->cp.ring_free_dw = rdev->cp.ring_size / 4; | ||
| 300 | } | ||
| 301 | } | ||
| 302 | |||
| 303 | int radeon_ring_lock(struct radeon_device *rdev, unsigned ndw) | ||
| 304 | { | ||
| 305 | int r; | ||
| 306 | |||
| 307 | /* Align requested size with padding so unlock_commit can | ||
| 308 | * pad safely */ | ||
| 309 | ndw = (ndw + rdev->cp.align_mask) & ~rdev->cp.align_mask; | ||
| 310 | mutex_lock(&rdev->cp.mutex); | ||
| 311 | while (ndw > (rdev->cp.ring_free_dw - 1)) { | ||
| 312 | radeon_ring_free_size(rdev); | ||
| 313 | if (ndw < rdev->cp.ring_free_dw) { | ||
| 314 | break; | ||
| 315 | } | ||
| 316 | r = radeon_fence_wait_next(rdev); | ||
| 317 | if (r) { | ||
| 318 | mutex_unlock(&rdev->cp.mutex); | ||
| 319 | return r; | ||
| 320 | } | ||
| 321 | } | ||
| 322 | rdev->cp.count_dw = ndw; | ||
| 323 | rdev->cp.wptr_old = rdev->cp.wptr; | ||
| 324 | return 0; | ||
| 325 | } | ||
| 326 | |||
| 327 | void radeon_ring_unlock_commit(struct radeon_device *rdev) | ||
| 328 | { | ||
| 329 | unsigned count_dw_pad; | ||
| 330 | unsigned i; | ||
| 331 | |||
| 332 | /* We pad to match fetch size */ | ||
| 333 | count_dw_pad = (rdev->cp.align_mask + 1) - | ||
| 334 | (rdev->cp.wptr & rdev->cp.align_mask); | ||
| 335 | for (i = 0; i < count_dw_pad; i++) { | ||
| 336 | radeon_ring_write(rdev, PACKET2(0)); | ||
| 337 | } | ||
| 338 | DRM_MEMORYBARRIER(); | ||
| 339 | WREG32(RADEON_CP_RB_WPTR, rdev->cp.wptr); | ||
| 340 | (void)RREG32(RADEON_CP_RB_WPTR); | ||
| 341 | mutex_unlock(&rdev->cp.mutex); | ||
| 342 | } | ||
| 343 | |||
| 344 | void radeon_ring_unlock_undo(struct radeon_device *rdev) | ||
| 345 | { | ||
| 346 | rdev->cp.wptr = rdev->cp.wptr_old; | ||
| 347 | mutex_unlock(&rdev->cp.mutex); | ||
| 348 | } | ||
| 349 | |||
| 350 | int radeon_ring_test(struct radeon_device *rdev) | ||
| 351 | { | ||
| 352 | uint32_t scratch; | ||
| 353 | uint32_t tmp = 0; | ||
| 354 | unsigned i; | ||
| 355 | int r; | ||
| 356 | |||
| 357 | r = radeon_scratch_get(rdev, &scratch); | ||
| 358 | if (r) { | ||
| 359 | DRM_ERROR("radeon: cp failed to get scratch reg (%d).\n", r); | ||
| 360 | return r; | ||
| 361 | } | ||
| 362 | WREG32(scratch, 0xCAFEDEAD); | ||
| 363 | r = radeon_ring_lock(rdev, 2); | ||
| 364 | if (r) { | ||
| 365 | DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); | ||
| 366 | radeon_scratch_free(rdev, scratch); | ||
| 367 | return r; | ||
| 368 | } | ||
| 369 | radeon_ring_write(rdev, PACKET0(scratch, 0)); | ||
| 370 | radeon_ring_write(rdev, 0xDEADBEEF); | ||
| 371 | radeon_ring_unlock_commit(rdev); | ||
| 372 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 373 | tmp = RREG32(scratch); | ||
| 374 | if (tmp == 0xDEADBEEF) { | ||
| 375 | break; | ||
| 376 | } | ||
| 377 | DRM_UDELAY(1); | ||
| 378 | } | ||
| 379 | if (i < rdev->usec_timeout) { | ||
| 380 | DRM_INFO("ring test succeeded in %d usecs\n", i); | ||
| 381 | } else { | ||
| 382 | DRM_ERROR("radeon: ring test failed (sracth(0x%04X)=0x%08X)\n", | ||
| 383 | scratch, tmp); | ||
| 384 | r = -EINVAL; | ||
| 385 | } | ||
| 386 | radeon_scratch_free(rdev, scratch); | ||
| 387 | return r; | ||
| 388 | } | ||
| 389 | |||
| 390 | int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size) | ||
| 391 | { | ||
| 392 | int r; | ||
| 393 | |||
| 394 | rdev->cp.ring_size = ring_size; | ||
| 395 | /* Allocate ring buffer */ | ||
| 396 | if (rdev->cp.ring_obj == NULL) { | ||
| 397 | r = radeon_object_create(rdev, NULL, rdev->cp.ring_size, | ||
| 398 | true, | ||
| 399 | RADEON_GEM_DOMAIN_GTT, | ||
| 400 | false, | ||
| 401 | &rdev->cp.ring_obj); | ||
| 402 | if (r) { | ||
| 403 | DRM_ERROR("radeon: failed to create ring buffer (%d).\n", r); | ||
| 404 | mutex_unlock(&rdev->cp.mutex); | ||
| 405 | return r; | ||
| 406 | } | ||
| 407 | r = radeon_object_pin(rdev->cp.ring_obj, | ||
| 408 | RADEON_GEM_DOMAIN_GTT, | ||
| 409 | &rdev->cp.gpu_addr); | ||
| 410 | if (r) { | ||
| 411 | DRM_ERROR("radeon: failed to pin ring buffer (%d).\n", r); | ||
| 412 | mutex_unlock(&rdev->cp.mutex); | ||
| 413 | return r; | ||
| 414 | } | ||
| 415 | r = radeon_object_kmap(rdev->cp.ring_obj, | ||
| 416 | (void **)&rdev->cp.ring); | ||
| 417 | if (r) { | ||
| 418 | DRM_ERROR("radeon: failed to map ring buffer (%d).\n", r); | ||
| 419 | mutex_unlock(&rdev->cp.mutex); | ||
| 420 | return r; | ||
| 421 | } | ||
| 422 | } | ||
| 423 | rdev->cp.ptr_mask = (rdev->cp.ring_size / 4) - 1; | ||
| 424 | rdev->cp.ring_free_dw = rdev->cp.ring_size / 4; | ||
| 425 | return 0; | ||
| 426 | } | ||
| 427 | |||
| 428 | void radeon_ring_fini(struct radeon_device *rdev) | ||
| 429 | { | ||
| 430 | mutex_lock(&rdev->cp.mutex); | ||
| 431 | if (rdev->cp.ring_obj) { | ||
| 432 | radeon_object_kunmap(rdev->cp.ring_obj); | ||
| 433 | radeon_object_unpin(rdev->cp.ring_obj); | ||
| 434 | radeon_object_unref(&rdev->cp.ring_obj); | ||
| 435 | rdev->cp.ring = NULL; | ||
| 436 | rdev->cp.ring_obj = NULL; | ||
| 437 | } | ||
| 438 | mutex_unlock(&rdev->cp.mutex); | ||
| 439 | } | ||
| 440 | |||
| 441 | |||
| 442 | /* | ||
| 443 | * Debugfs info | ||
| 444 | */ | ||
| 445 | #if defined(CONFIG_DEBUG_FS) | ||
| 446 | static int radeon_debugfs_ib_info(struct seq_file *m, void *data) | ||
| 447 | { | ||
| 448 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
| 449 | struct radeon_ib *ib = node->info_ent->data; | ||
| 450 | unsigned i; | ||
| 451 | |||
| 452 | if (ib == NULL) { | ||
| 453 | return 0; | ||
| 454 | } | ||
| 455 | seq_printf(m, "IB %04lu\n", ib->idx); | ||
| 456 | seq_printf(m, "IB fence %p\n", ib->fence); | ||
| 457 | seq_printf(m, "IB size %05u dwords\n", ib->length_dw); | ||
| 458 | for (i = 0; i < ib->length_dw; i++) { | ||
| 459 | seq_printf(m, "[%05u]=0x%08X\n", i, ib->ptr[i]); | ||
| 460 | } | ||
| 461 | return 0; | ||
| 462 | } | ||
| 463 | |||
| 464 | static struct drm_info_list radeon_debugfs_ib_list[RADEON_IB_POOL_SIZE]; | ||
| 465 | static char radeon_debugfs_ib_names[RADEON_IB_POOL_SIZE][32]; | ||
| 466 | #endif | ||
| 467 | |||
| 468 | int radeon_debugfs_ib_init(struct radeon_device *rdev) | ||
| 469 | { | ||
| 470 | #if defined(CONFIG_DEBUG_FS) | ||
| 471 | unsigned i; | ||
| 472 | |||
| 473 | for (i = 0; i < RADEON_IB_POOL_SIZE; i++) { | ||
| 474 | sprintf(radeon_debugfs_ib_names[i], "radeon_ib_%04u", i); | ||
| 475 | radeon_debugfs_ib_list[i].name = radeon_debugfs_ib_names[i]; | ||
| 476 | radeon_debugfs_ib_list[i].show = &radeon_debugfs_ib_info; | ||
| 477 | radeon_debugfs_ib_list[i].driver_features = 0; | ||
| 478 | radeon_debugfs_ib_list[i].data = &rdev->ib_pool.ibs[i]; | ||
| 479 | } | ||
| 480 | return radeon_debugfs_add_files(rdev, radeon_debugfs_ib_list, | ||
| 481 | RADEON_IB_POOL_SIZE); | ||
| 482 | #else | ||
| 483 | return 0; | ||
| 484 | #endif | ||
| 485 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c new file mode 100644 index 000000000000..4c087c1510d7 --- /dev/null +++ b/drivers/gpu/drm/radeon/radeon_ttm.c | |||
| @@ -0,0 +1,653 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2009 Jerome Glisse. | ||
| 3 | * All Rights Reserved. | ||
| 4 | * | ||
| 5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 6 | * 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, sub license, 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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 16 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 17 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 18 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 19 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 20 | * | ||
| 21 | * The above copyright notice and this permission notice (including the | ||
| 22 | * next paragraph) shall be included in all copies or substantial portions | ||
| 23 | * of the Software. | ||
| 24 | * | ||
| 25 | */ | ||
| 26 | /* | ||
| 27 | * Authors: | ||
| 28 | * Jerome Glisse <glisse@freedesktop.org> | ||
| 29 | * Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> | ||
| 30 | * Dave Airlie | ||
| 31 | */ | ||
| 32 | #include <ttm/ttm_bo_api.h> | ||
| 33 | #include <ttm/ttm_bo_driver.h> | ||
| 34 | #include <ttm/ttm_placement.h> | ||
| 35 | #include <ttm/ttm_module.h> | ||
| 36 | #include <drm/drmP.h> | ||
| 37 | #include <drm/radeon_drm.h> | ||
| 38 | #include "radeon_reg.h" | ||
| 39 | #include "radeon.h" | ||
| 40 | |||
| 41 | #define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) | ||
| 42 | |||
| 43 | static struct radeon_device *radeon_get_rdev(struct ttm_bo_device *bdev) | ||
| 44 | { | ||
| 45 | struct radeon_mman *mman; | ||
| 46 | struct radeon_device *rdev; | ||
| 47 | |||
| 48 | mman = container_of(bdev, struct radeon_mman, bdev); | ||
| 49 | rdev = container_of(mman, struct radeon_device, mman); | ||
| 50 | return rdev; | ||
| 51 | } | ||
| 52 | |||
| 53 | |||
| 54 | /* | ||
| 55 | * Global memory. | ||
| 56 | */ | ||
| 57 | static int radeon_ttm_mem_global_init(struct ttm_global_reference *ref) | ||
| 58 | { | ||
| 59 | return ttm_mem_global_init(ref->object); | ||
| 60 | } | ||
| 61 | |||
| 62 | static void radeon_ttm_mem_global_release(struct ttm_global_reference *ref) | ||
| 63 | { | ||
| 64 | ttm_mem_global_release(ref->object); | ||
| 65 | } | ||
| 66 | |||
| 67 | static int radeon_ttm_global_init(struct radeon_device *rdev) | ||
| 68 | { | ||
| 69 | struct ttm_global_reference *global_ref; | ||
| 70 | int r; | ||
| 71 | |||
| 72 | rdev->mman.mem_global_referenced = false; | ||
| 73 | global_ref = &rdev->mman.mem_global_ref; | ||
| 74 | global_ref->global_type = TTM_GLOBAL_TTM_MEM; | ||
| 75 | global_ref->size = sizeof(struct ttm_mem_global); | ||
| 76 | global_ref->init = &radeon_ttm_mem_global_init; | ||
| 77 | global_ref->release = &radeon_ttm_mem_global_release; | ||
| 78 | r = ttm_global_item_ref(global_ref); | ||
| 79 | if (r != 0) { | ||
| 80 | DRM_ERROR("Failed referencing a global TTM memory object.\n"); | ||
| 81 | return r; | ||
| 82 | } | ||
| 83 | rdev->mman.mem_global_referenced = true; | ||
| 84 | return 0; | ||
| 85 | } | ||
| 86 | |||
| 87 | static void radeon_ttm_global_fini(struct radeon_device *rdev) | ||
| 88 | { | ||
| 89 | if (rdev->mman.mem_global_referenced) { | ||
| 90 | ttm_global_item_unref(&rdev->mman.mem_global_ref); | ||
| 91 | rdev->mman.mem_global_referenced = false; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | struct ttm_backend *radeon_ttm_backend_create(struct radeon_device *rdev); | ||
| 96 | |||
| 97 | static struct ttm_backend* | ||
| 98 | radeon_create_ttm_backend_entry(struct ttm_bo_device *bdev) | ||
| 99 | { | ||
| 100 | struct radeon_device *rdev; | ||
| 101 | |||
| 102 | rdev = radeon_get_rdev(bdev); | ||
| 103 | #if __OS_HAS_AGP | ||
| 104 | if (rdev->flags & RADEON_IS_AGP) { | ||
| 105 | return ttm_agp_backend_init(bdev, rdev->ddev->agp->bridge); | ||
| 106 | } else | ||
| 107 | #endif | ||
| 108 | { | ||
| 109 | return radeon_ttm_backend_create(rdev); | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | static int radeon_invalidate_caches(struct ttm_bo_device *bdev, uint32_t flags) | ||
| 114 | { | ||
| 115 | return 0; | ||
| 116 | } | ||
| 117 | |||
| 118 | static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, | ||
| 119 | struct ttm_mem_type_manager *man) | ||
| 120 | { | ||
| 121 | struct radeon_device *rdev; | ||
| 122 | |||
| 123 | rdev = radeon_get_rdev(bdev); | ||
| 124 | |||
| 125 | switch (type) { | ||
| 126 | case TTM_PL_SYSTEM: | ||
| 127 | /* System memory */ | ||
| 128 | man->flags = TTM_MEMTYPE_FLAG_MAPPABLE; | ||
| 129 | man->available_caching = TTM_PL_MASK_CACHING; | ||
| 130 | man->default_caching = TTM_PL_FLAG_CACHED; | ||
| 131 | break; | ||
| 132 | case TTM_PL_TT: | ||
| 133 | man->gpu_offset = 0; | ||
| 134 | man->available_caching = TTM_PL_MASK_CACHING; | ||
| 135 | man->default_caching = TTM_PL_FLAG_CACHED; | ||
| 136 | #if __OS_HAS_AGP | ||
| 137 | if (rdev->flags & RADEON_IS_AGP) { | ||
| 138 | if (!(drm_core_has_AGP(rdev->ddev) && rdev->ddev->agp)) { | ||
| 139 | DRM_ERROR("AGP is not enabled for memory type %u\n", | ||
| 140 | (unsigned)type); | ||
| 141 | return -EINVAL; | ||
| 142 | } | ||
| 143 | man->io_offset = rdev->mc.agp_base; | ||
| 144 | man->io_size = rdev->mc.gtt_size; | ||
| 145 | man->io_addr = NULL; | ||
| 146 | man->flags = TTM_MEMTYPE_FLAG_NEEDS_IOREMAP | | ||
| 147 | TTM_MEMTYPE_FLAG_MAPPABLE; | ||
| 148 | man->available_caching = TTM_PL_FLAG_UNCACHED | | ||
| 149 | TTM_PL_FLAG_WC; | ||
| 150 | man->default_caching = TTM_PL_FLAG_WC; | ||
| 151 | } else | ||
| 152 | #endif | ||
| 153 | { | ||
| 154 | man->io_offset = 0; | ||
| 155 | man->io_size = 0; | ||
| 156 | man->io_addr = NULL; | ||
| 157 | man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | | ||
| 158 | TTM_MEMTYPE_FLAG_CMA; | ||
| 159 | } | ||
| 160 | break; | ||
| 161 | case TTM_PL_VRAM: | ||
| 162 | /* "On-card" video ram */ | ||
| 163 | man->gpu_offset = 0; | ||
| 164 | man->flags = TTM_MEMTYPE_FLAG_FIXED | | ||
| 165 | TTM_MEMTYPE_FLAG_NEEDS_IOREMAP | | ||
| 166 | TTM_MEMTYPE_FLAG_MAPPABLE; | ||
| 167 | man->available_caching = TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_WC; | ||
| 168 | man->default_caching = TTM_PL_FLAG_WC; | ||
| 169 | man->io_addr = NULL; | ||
| 170 | man->io_offset = rdev->mc.aper_base; | ||
| 171 | man->io_size = rdev->mc.aper_size; | ||
| 172 | break; | ||
| 173 | default: | ||
| 174 | DRM_ERROR("Unsupported memory type %u\n", (unsigned)type); | ||
| 175 | return -EINVAL; | ||
| 176 | } | ||
| 177 | return 0; | ||
| 178 | } | ||
| 179 | |||
| 180 | static uint32_t radeon_evict_flags(struct ttm_buffer_object *bo) | ||
| 181 | { | ||
| 182 | uint32_t cur_placement = bo->mem.placement & ~TTM_PL_MASK_MEMTYPE; | ||
| 183 | |||
| 184 | switch (bo->mem.mem_type) { | ||
| 185 | default: | ||
| 186 | return (cur_placement & ~TTM_PL_MASK_CACHING) | | ||
| 187 | TTM_PL_FLAG_SYSTEM | | ||
| 188 | TTM_PL_FLAG_CACHED; | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | static int radeon_verify_access(struct ttm_buffer_object *bo, struct file *filp) | ||
| 193 | { | ||
| 194 | return 0; | ||
| 195 | } | ||
| 196 | |||
| 197 | static void radeon_move_null(struct ttm_buffer_object *bo, | ||
| 198 | struct ttm_mem_reg *new_mem) | ||
| 199 | { | ||
| 200 | struct ttm_mem_reg *old_mem = &bo->mem; | ||
| 201 | |||
| 202 | BUG_ON(old_mem->mm_node != NULL); | ||
| 203 | *old_mem = *new_mem; | ||
| 204 | new_mem->mm_node = NULL; | ||
| 205 | } | ||
| 206 | |||
| 207 | static int radeon_move_blit(struct ttm_buffer_object *bo, | ||
| 208 | bool evict, int no_wait, | ||
| 209 | struct ttm_mem_reg *new_mem, | ||
| 210 | struct ttm_mem_reg *old_mem) | ||
| 211 | { | ||
| 212 | struct radeon_device *rdev; | ||
| 213 | uint64_t old_start, new_start; | ||
| 214 | struct radeon_fence *fence; | ||
| 215 | int r; | ||
| 216 | |||
| 217 | rdev = radeon_get_rdev(bo->bdev); | ||
| 218 | r = radeon_fence_create(rdev, &fence); | ||
| 219 | if (unlikely(r)) { | ||
| 220 | return r; | ||
| 221 | } | ||
| 222 | old_start = old_mem->mm_node->start << PAGE_SHIFT; | ||
| 223 | new_start = new_mem->mm_node->start << PAGE_SHIFT; | ||
| 224 | |||
| 225 | switch (old_mem->mem_type) { | ||
| 226 | case TTM_PL_VRAM: | ||
| 227 | old_start += rdev->mc.vram_location; | ||
| 228 | break; | ||
| 229 | case TTM_PL_TT: | ||
| 230 | old_start += rdev->mc.gtt_location; | ||
| 231 | break; | ||
| 232 | default: | ||
| 233 | DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); | ||
| 234 | return -EINVAL; | ||
| 235 | } | ||
| 236 | switch (new_mem->mem_type) { | ||
| 237 | case TTM_PL_VRAM: | ||
| 238 | new_start += rdev->mc.vram_location; | ||
| 239 | break; | ||
| 240 | case TTM_PL_TT: | ||
| 241 | new_start += rdev->mc.gtt_location; | ||
| 242 | break; | ||
| 243 | default: | ||
| 244 | DRM_ERROR("Unknown placement %d\n", old_mem->mem_type); | ||
| 245 | return -EINVAL; | ||
| 246 | } | ||
| 247 | if (!rdev->cp.ready) { | ||
| 248 | DRM_ERROR("Trying to move memory with CP turned off.\n"); | ||
| 249 | return -EINVAL; | ||
| 250 | } | ||
| 251 | r = radeon_copy(rdev, old_start, new_start, new_mem->num_pages, fence); | ||
| 252 | /* FIXME: handle copy error */ | ||
| 253 | r = ttm_bo_move_accel_cleanup(bo, (void *)fence, NULL, | ||
| 254 | evict, no_wait, new_mem); | ||
| 255 | radeon_fence_unref(&fence); | ||
| 256 | return r; | ||
| 257 | } | ||
| 258 | |||
| 259 | static int radeon_move_vram_ram(struct ttm_buffer_object *bo, | ||
| 260 | bool evict, bool interruptible, bool no_wait, | ||
| 261 | struct ttm_mem_reg *new_mem) | ||
| 262 | { | ||
| 263 | struct radeon_device *rdev; | ||
| 264 | struct ttm_mem_reg *old_mem = &bo->mem; | ||
| 265 | struct ttm_mem_reg tmp_mem; | ||
| 266 | uint32_t proposed_placement; | ||
| 267 | int r; | ||
| 268 | |||
| 269 | rdev = radeon_get_rdev(bo->bdev); | ||
| 270 | tmp_mem = *new_mem; | ||
| 271 | tmp_mem.mm_node = NULL; | ||
| 272 | proposed_placement = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; | ||
| 273 | r = ttm_bo_mem_space(bo, proposed_placement, &tmp_mem, | ||
| 274 | interruptible, no_wait); | ||
| 275 | if (unlikely(r)) { | ||
| 276 | return r; | ||
| 277 | } | ||
| 278 | r = ttm_tt_bind(bo->ttm, &tmp_mem); | ||
| 279 | if (unlikely(r)) { | ||
| 280 | goto out_cleanup; | ||
| 281 | } | ||
| 282 | r = radeon_move_blit(bo, true, no_wait, &tmp_mem, old_mem); | ||
| 283 | if (unlikely(r)) { | ||
| 284 | goto out_cleanup; | ||
| 285 | } | ||
| 286 | r = ttm_bo_move_ttm(bo, true, no_wait, new_mem); | ||
| 287 | out_cleanup: | ||
| 288 | if (tmp_mem.mm_node) { | ||
| 289 | spin_lock(&rdev->mman.bdev.lru_lock); | ||
| 290 | drm_mm_put_block(tmp_mem.mm_node); | ||
| 291 | spin_unlock(&rdev->mman.bdev.lru_lock); | ||
| 292 | return r; | ||
| 293 | } | ||
| 294 | return r; | ||
| 295 | } | ||
| 296 | |||
| 297 | static int radeon_move_ram_vram(struct ttm_buffer_object *bo, | ||
| 298 | bool evict, bool interruptible, bool no_wait, | ||
| 299 | struct ttm_mem_reg *new_mem) | ||
| 300 | { | ||
| 301 | struct radeon_device *rdev; | ||
| 302 | struct ttm_mem_reg *old_mem = &bo->mem; | ||
| 303 | struct ttm_mem_reg tmp_mem; | ||
| 304 | uint32_t proposed_flags; | ||
| 305 | int r; | ||
| 306 | |||
| 307 | rdev = radeon_get_rdev(bo->bdev); | ||
| 308 | tmp_mem = *new_mem; | ||
| 309 | tmp_mem.mm_node = NULL; | ||
| 310 | proposed_flags = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING; | ||
| 311 | r = ttm_bo_mem_space(bo, proposed_flags, &tmp_mem, | ||
| 312 | interruptible, no_wait); | ||
| 313 | if (unlikely(r)) { | ||
| 314 | return r; | ||
| 315 | } | ||
| 316 | r = ttm_bo_move_ttm(bo, true, no_wait, &tmp_mem); | ||
| 317 | if (unlikely(r)) { | ||
| 318 | goto out_cleanup; | ||
| 319 | } | ||
| 320 | r = radeon_move_blit(bo, true, no_wait, new_mem, old_mem); | ||
| 321 | if (unlikely(r)) { | ||
| 322 | goto out_cleanup; | ||
| 323 | } | ||
| 324 | out_cleanup: | ||
| 325 | if (tmp_mem.mm_node) { | ||
| 326 | spin_lock(&rdev->mman.bdev.lru_lock); | ||
| 327 | drm_mm_put_block(tmp_mem.mm_node); | ||
| 328 | spin_unlock(&rdev->mman.bdev.lru_lock); | ||
| 329 | return r; | ||
| 330 | } | ||
| 331 | return r; | ||
| 332 | } | ||
| 333 | |||
| 334 | static int radeon_bo_move(struct ttm_buffer_object *bo, | ||
| 335 | bool evict, bool interruptible, bool no_wait, | ||
| 336 | struct ttm_mem_reg *new_mem) | ||
| 337 | { | ||
| 338 | struct radeon_device *rdev; | ||
| 339 | struct ttm_mem_reg *old_mem = &bo->mem; | ||
| 340 | int r; | ||
| 341 | |||
| 342 | rdev = radeon_get_rdev(bo->bdev); | ||
| 343 | if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { | ||
| 344 | radeon_move_null(bo, new_mem); | ||
| 345 | return 0; | ||
| 346 | } | ||
| 347 | if ((old_mem->mem_type == TTM_PL_TT && | ||
| 348 | new_mem->mem_type == TTM_PL_SYSTEM) || | ||
| 349 | (old_mem->mem_type == TTM_PL_SYSTEM && | ||
| 350 | new_mem->mem_type == TTM_PL_TT)) { | ||
| 351 | /* bind is enought */ | ||
| 352 | radeon_move_null(bo, new_mem); | ||
| 353 | return 0; | ||
| 354 | } | ||
| 355 | if (!rdev->cp.ready) { | ||
| 356 | /* use memcpy */ | ||
| 357 | DRM_ERROR("CP is not ready use memcpy.\n"); | ||
| 358 | return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); | ||
| 359 | } | ||
| 360 | |||
| 361 | if (old_mem->mem_type == TTM_PL_VRAM && | ||
| 362 | new_mem->mem_type == TTM_PL_SYSTEM) { | ||
| 363 | return radeon_move_vram_ram(bo, evict, interruptible, | ||
| 364 | no_wait, new_mem); | ||
| 365 | } else if (old_mem->mem_type == TTM_PL_SYSTEM && | ||
| 366 | new_mem->mem_type == TTM_PL_VRAM) { | ||
| 367 | return radeon_move_ram_vram(bo, evict, interruptible, | ||
| 368 | no_wait, new_mem); | ||
| 369 | } else { | ||
| 370 | r = radeon_move_blit(bo, evict, no_wait, new_mem, old_mem); | ||
| 371 | if (unlikely(r)) { | ||
| 372 | return r; | ||
| 373 | } | ||
| 374 | } | ||
| 375 | return r; | ||
| 376 | } | ||
| 377 | |||
| 378 | const uint32_t radeon_mem_prios[] = { | ||
| 379 | TTM_PL_VRAM, | ||
| 380 | TTM_PL_TT, | ||
| 381 | TTM_PL_SYSTEM, | ||
| 382 | }; | ||
| 383 | |||
| 384 | const uint32_t radeon_busy_prios[] = { | ||
| 385 | TTM_PL_TT, | ||
| 386 | TTM_PL_VRAM, | ||
| 387 | TTM_PL_SYSTEM, | ||
| 388 | }; | ||
| 389 | |||
| 390 | static int radeon_sync_obj_wait(void *sync_obj, void *sync_arg, | ||
| 391 | bool lazy, bool interruptible) | ||
| 392 | { | ||
| 393 | return radeon_fence_wait((struct radeon_fence *)sync_obj, interruptible); | ||
| 394 | } | ||
| 395 | |||
| 396 | static int radeon_sync_obj_flush(void *sync_obj, void *sync_arg) | ||
| 397 | { | ||
| 398 | return 0; | ||
| 399 | } | ||
| 400 | |||
| 401 | static void radeon_sync_obj_unref(void **sync_obj) | ||
| 402 | { | ||
| 403 | radeon_fence_unref((struct radeon_fence **)sync_obj); | ||
| 404 | } | ||
| 405 | |||
| 406 | static void *radeon_sync_obj_ref(void *sync_obj) | ||
| 407 | { | ||
| 408 | return radeon_fence_ref((struct radeon_fence *)sync_obj); | ||
| 409 | } | ||
| 410 | |||
| 411 | static bool radeon_sync_obj_signaled(void *sync_obj, void *sync_arg) | ||
| 412 | { | ||
| 413 | return radeon_fence_signaled((struct radeon_fence *)sync_obj); | ||
| 414 | } | ||
| 415 | |||
| 416 | static struct ttm_bo_driver radeon_bo_driver = { | ||
| 417 | .mem_type_prio = radeon_mem_prios, | ||
| 418 | .mem_busy_prio = radeon_busy_prios, | ||
| 419 | .num_mem_type_prio = ARRAY_SIZE(radeon_mem_prios), | ||
| 420 | .num_mem_busy_prio = ARRAY_SIZE(radeon_busy_prios), | ||
| 421 | .create_ttm_backend_entry = &radeon_create_ttm_backend_entry, | ||
| 422 | .invalidate_caches = &radeon_invalidate_caches, | ||
| 423 | .init_mem_type = &radeon_init_mem_type, | ||
| 424 | .evict_flags = &radeon_evict_flags, | ||
| 425 | .move = &radeon_bo_move, | ||
| 426 | .verify_access = &radeon_verify_access, | ||
| 427 | .sync_obj_signaled = &radeon_sync_obj_signaled, | ||
| 428 | .sync_obj_wait = &radeon_sync_obj_wait, | ||
| 429 | .sync_obj_flush = &radeon_sync_obj_flush, | ||
| 430 | .sync_obj_unref = &radeon_sync_obj_unref, | ||
| 431 | .sync_obj_ref = &radeon_sync_obj_ref, | ||
| 432 | }; | ||
| 433 | |||
| 434 | int radeon_ttm_init(struct radeon_device *rdev) | ||
| 435 | { | ||
| 436 | int r; | ||
| 437 | |||
| 438 | r = radeon_ttm_global_init(rdev); | ||
| 439 | if (r) { | ||
| 440 | return r; | ||
| 441 | } | ||
| 442 | /* No others user of address space so set it to 0 */ | ||
| 443 | r = ttm_bo_device_init(&rdev->mman.bdev, | ||
| 444 | rdev->mman.mem_global_ref.object, | ||
| 445 | &radeon_bo_driver, DRM_FILE_PAGE_OFFSET); | ||
| 446 | if (r) { | ||
| 447 | DRM_ERROR("failed initializing buffer object driver(%d).\n", r); | ||
| 448 | return r; | ||
| 449 | } | ||
| 450 | r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, 0, | ||
| 451 | ((rdev->mc.aper_size) >> PAGE_SHIFT)); | ||
| 452 | if (r) { | ||
| 453 | DRM_ERROR("Failed initializing VRAM heap.\n"); | ||
| 454 | return r; | ||
| 455 | } | ||
| 456 | r = radeon_object_create(rdev, NULL, 256 * 1024, true, | ||
| 457 | RADEON_GEM_DOMAIN_VRAM, false, | ||
| 458 | &rdev->stollen_vga_memory); | ||
| 459 | if (r) { | ||
| 460 | return r; | ||
| 461 | } | ||
| 462 | r = radeon_object_pin(rdev->stollen_vga_memory, RADEON_GEM_DOMAIN_VRAM, NULL); | ||
| 463 | if (r) { | ||
| 464 | radeon_object_unref(&rdev->stollen_vga_memory); | ||
| 465 | return r; | ||
| 466 | } | ||
| 467 | DRM_INFO("radeon: %uM of VRAM memory ready\n", | ||
| 468 | rdev->mc.vram_size / (1024 * 1024)); | ||
| 469 | r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, 0, | ||
| 470 | ((rdev->mc.gtt_size) >> PAGE_SHIFT)); | ||
| 471 | if (r) { | ||
| 472 | DRM_ERROR("Failed initializing GTT heap.\n"); | ||
| 473 | return r; | ||
| 474 | } | ||
| 475 | DRM_INFO("radeon: %uM of GTT memory ready.\n", | ||
| 476 | rdev->mc.gtt_size / (1024 * 1024)); | ||
| 477 | if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) { | ||
| 478 | rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping; | ||
| 479 | } | ||
| 480 | return 0; | ||
| 481 | } | ||
| 482 | |||
| 483 | void radeon_ttm_fini(struct radeon_device *rdev) | ||
| 484 | { | ||
| 485 | if (rdev->stollen_vga_memory) { | ||
| 486 | radeon_object_unpin(rdev->stollen_vga_memory); | ||
| 487 | radeon_object_unref(&rdev->stollen_vga_memory); | ||
| 488 | } | ||
| 489 | ttm_bo_clean_mm(&rdev->mman.bdev, TTM_PL_VRAM); | ||
| 490 | ttm_bo_clean_mm(&rdev->mman.bdev, TTM_PL_TT); | ||
| 491 | ttm_bo_device_release(&rdev->mman.bdev); | ||
| 492 | radeon_gart_fini(rdev); | ||
| 493 | radeon_ttm_global_fini(rdev); | ||
| 494 | DRM_INFO("radeon: ttm finalized\n"); | ||
| 495 | } | ||
| 496 | |||
| 497 | static struct vm_operations_struct radeon_ttm_vm_ops; | ||
| 498 | static struct vm_operations_struct *ttm_vm_ops = NULL; | ||
| 499 | |||
| 500 | static int radeon_ttm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | ||
| 501 | { | ||
| 502 | struct ttm_buffer_object *bo; | ||
| 503 | int r; | ||
| 504 | |||
| 505 | bo = (struct ttm_buffer_object *)vma->vm_private_data; | ||
| 506 | if (bo == NULL) { | ||
| 507 | return VM_FAULT_NOPAGE; | ||
| 508 | } | ||
| 509 | r = ttm_vm_ops->fault(vma, vmf); | ||
| 510 | return r; | ||
| 511 | } | ||
| 512 | |||
| 513 | int radeon_mmap(struct file *filp, struct vm_area_struct *vma) | ||
| 514 | { | ||
| 515 | struct drm_file *file_priv; | ||
| 516 | struct radeon_device *rdev; | ||
| 517 | int r; | ||
| 518 | |||
| 519 | if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) { | ||
| 520 | return drm_mmap(filp, vma); | ||
| 521 | } | ||
| 522 | |||
| 523 | file_priv = (struct drm_file *)filp->private_data; | ||
| 524 | rdev = file_priv->minor->dev->dev_private; | ||
| 525 | if (rdev == NULL) { | ||
| 526 | return -EINVAL; | ||
| 527 | } | ||
| 528 | r = ttm_bo_mmap(filp, vma, &rdev->mman.bdev); | ||
| 529 | if (unlikely(r != 0)) { | ||
| 530 | return r; | ||
| 531 | } | ||
| 532 | if (unlikely(ttm_vm_ops == NULL)) { | ||
| 533 | ttm_vm_ops = vma->vm_ops; | ||
| 534 | radeon_ttm_vm_ops = *ttm_vm_ops; | ||
| 535 | radeon_ttm_vm_ops.fault = &radeon_ttm_fault; | ||
| 536 | } | ||
| 537 | vma->vm_ops = &radeon_ttm_vm_ops; | ||
| 538 | return 0; | ||
| 539 | } | ||
| 540 | |||
| 541 | |||
| 542 | /* | ||
| 543 | * TTM backend functions. | ||
| 544 | */ | ||
| 545 | struct radeon_ttm_backend { | ||
| 546 | struct ttm_backend backend; | ||
| 547 | struct radeon_device *rdev; | ||
| 548 | unsigned long num_pages; | ||
| 549 | struct page **pages; | ||
| 550 | struct page *dummy_read_page; | ||
| 551 | bool populated; | ||
| 552 | bool bound; | ||
| 553 | unsigned offset; | ||
| 554 | }; | ||
| 555 | |||
| 556 | static int radeon_ttm_backend_populate(struct ttm_backend *backend, | ||
| 557 | unsigned long num_pages, | ||
| 558 | struct page **pages, | ||
| 559 | struct page *dummy_read_page) | ||
| 560 | { | ||
| 561 | struct radeon_ttm_backend *gtt; | ||
| 562 | |||
| 563 | gtt = container_of(backend, struct radeon_ttm_backend, backend); | ||
| 564 | gtt->pages = pages; | ||
| 565 | gtt->num_pages = num_pages; | ||
| 566 | gtt->dummy_read_page = dummy_read_page; | ||
| 567 | gtt->populated = true; | ||
| 568 | return 0; | ||
| 569 | } | ||
| 570 | |||
| 571 | static void radeon_ttm_backend_clear(struct ttm_backend *backend) | ||
| 572 | { | ||
| 573 | struct radeon_ttm_backend *gtt; | ||
| 574 | |||
| 575 | gtt = container_of(backend, struct radeon_ttm_backend, backend); | ||
| 576 | gtt->pages = NULL; | ||
| 577 | gtt->num_pages = 0; | ||
| 578 | gtt->dummy_read_page = NULL; | ||
| 579 | gtt->populated = false; | ||
| 580 | gtt->bound = false; | ||
| 581 | } | ||
| 582 | |||
| 583 | |||
| 584 | static int radeon_ttm_backend_bind(struct ttm_backend *backend, | ||
| 585 | struct ttm_mem_reg *bo_mem) | ||
| 586 | { | ||
| 587 | struct radeon_ttm_backend *gtt; | ||
| 588 | int r; | ||
| 589 | |||
| 590 | gtt = container_of(backend, struct radeon_ttm_backend, backend); | ||
| 591 | gtt->offset = bo_mem->mm_node->start << PAGE_SHIFT; | ||
| 592 | if (!gtt->num_pages) { | ||
| 593 | WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n", gtt->num_pages, bo_mem, backend); | ||
| 594 | } | ||
| 595 | r = radeon_gart_bind(gtt->rdev, gtt->offset, | ||
| 596 | gtt->num_pages, gtt->pages); | ||
| 597 | if (r) { | ||
| 598 | DRM_ERROR("failed to bind %lu pages at 0x%08X\n", | ||
| 599 | gtt->num_pages, gtt->offset); | ||
| 600 | return r; | ||
| 601 | } | ||
| 602 | gtt->bound = true; | ||
| 603 | return 0; | ||
| 604 | } | ||
| 605 | |||
| 606 | static int radeon_ttm_backend_unbind(struct ttm_backend *backend) | ||
| 607 | { | ||
| 608 | struct radeon_ttm_backend *gtt; | ||
| 609 | |||
| 610 | gtt = container_of(backend, struct radeon_ttm_backend, backend); | ||
| 611 | radeon_gart_unbind(gtt->rdev, gtt->offset, gtt->num_pages); | ||
| 612 | gtt->bound = false; | ||
| 613 | return 0; | ||
| 614 | } | ||
| 615 | |||
| 616 | static void radeon_ttm_backend_destroy(struct ttm_backend *backend) | ||
| 617 | { | ||
| 618 | struct radeon_ttm_backend *gtt; | ||
| 619 | |||
| 620 | gtt = container_of(backend, struct radeon_ttm_backend, backend); | ||
| 621 | if (gtt->bound) { | ||
| 622 | radeon_ttm_backend_unbind(backend); | ||
| 623 | } | ||
| 624 | kfree(gtt); | ||
| 625 | } | ||
| 626 | |||
| 627 | static struct ttm_backend_func radeon_backend_func = { | ||
| 628 | .populate = &radeon_ttm_backend_populate, | ||
| 629 | .clear = &radeon_ttm_backend_clear, | ||
| 630 | .bind = &radeon_ttm_backend_bind, | ||
| 631 | .unbind = &radeon_ttm_backend_unbind, | ||
| 632 | .destroy = &radeon_ttm_backend_destroy, | ||
| 633 | }; | ||
| 634 | |||
| 635 | struct ttm_backend *radeon_ttm_backend_create(struct radeon_device *rdev) | ||
| 636 | { | ||
| 637 | struct radeon_ttm_backend *gtt; | ||
| 638 | |||
| 639 | gtt = kzalloc(sizeof(struct radeon_ttm_backend), GFP_KERNEL); | ||
| 640 | if (gtt == NULL) { | ||
| 641 | return NULL; | ||
| 642 | } | ||
| 643 | gtt->backend.bdev = &rdev->mman.bdev; | ||
| 644 | gtt->backend.flags = 0; | ||
| 645 | gtt->backend.func = &radeon_backend_func; | ||
| 646 | gtt->rdev = rdev; | ||
| 647 | gtt->pages = NULL; | ||
| 648 | gtt->num_pages = 0; | ||
| 649 | gtt->dummy_read_page = NULL; | ||
| 650 | gtt->populated = false; | ||
| 651 | gtt->bound = false; | ||
| 652 | return >t->backend; | ||
| 653 | } | ||
diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c new file mode 100644 index 000000000000..cc074b5a8f74 --- /dev/null +++ b/drivers/gpu/drm/radeon/rs400.c | |||
| @@ -0,0 +1,411 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include <linux/seq_file.h> | ||
| 29 | #include <drm/drmP.h> | ||
| 30 | #include "radeon_reg.h" | ||
| 31 | #include "radeon.h" | ||
| 32 | |||
| 33 | /* rs400,rs480 depends on : */ | ||
| 34 | void r100_hdp_reset(struct radeon_device *rdev); | ||
| 35 | void r100_mc_disable_clients(struct radeon_device *rdev); | ||
| 36 | int r300_mc_wait_for_idle(struct radeon_device *rdev); | ||
| 37 | void r420_pipes_init(struct radeon_device *rdev); | ||
| 38 | |||
| 39 | /* This files gather functions specifics to : | ||
| 40 | * rs400,rs480 | ||
| 41 | * | ||
| 42 | * Some of these functions might be used by newer ASICs. | ||
| 43 | */ | ||
| 44 | void rs400_gpu_init(struct radeon_device *rdev); | ||
| 45 | int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev); | ||
| 46 | |||
| 47 | |||
| 48 | /* | ||
| 49 | * GART functions. | ||
| 50 | */ | ||
| 51 | void rs400_gart_adjust_size(struct radeon_device *rdev) | ||
| 52 | { | ||
| 53 | /* Check gart size */ | ||
| 54 | switch (rdev->mc.gtt_size/(1024*1024)) { | ||
| 55 | case 32: | ||
| 56 | case 64: | ||
| 57 | case 128: | ||
| 58 | case 256: | ||
| 59 | case 512: | ||
| 60 | case 1024: | ||
| 61 | case 2048: | ||
| 62 | break; | ||
| 63 | default: | ||
| 64 | DRM_ERROR("Unable to use IGP GART size %uM\n", | ||
| 65 | rdev->mc.gtt_size >> 20); | ||
| 66 | DRM_ERROR("Valid GART size for IGP are 32M,64M,128M,256M,512M,1G,2G\n"); | ||
| 67 | DRM_ERROR("Forcing to 32M GART size\n"); | ||
| 68 | rdev->mc.gtt_size = 32 * 1024 * 1024; | ||
| 69 | return; | ||
| 70 | } | ||
| 71 | if (rdev->family == CHIP_RS400 || rdev->family == CHIP_RS480) { | ||
| 72 | /* FIXME: RS400 & RS480 seems to have issue with GART size | ||
| 73 | * if 4G of system memory (needs more testing) */ | ||
| 74 | rdev->mc.gtt_size = 32 * 1024 * 1024; | ||
| 75 | DRM_ERROR("Forcing to 32M GART size (because of ASIC bug ?)\n"); | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | void rs400_gart_tlb_flush(struct radeon_device *rdev) | ||
| 80 | { | ||
| 81 | uint32_t tmp; | ||
| 82 | unsigned int timeout = rdev->usec_timeout; | ||
| 83 | |||
| 84 | WREG32_MC(RS480_GART_CACHE_CNTRL, RS480_GART_CACHE_INVALIDATE); | ||
| 85 | do { | ||
| 86 | tmp = RREG32_MC(RS480_GART_CACHE_CNTRL); | ||
| 87 | if ((tmp & RS480_GART_CACHE_INVALIDATE) == 0) | ||
| 88 | break; | ||
| 89 | DRM_UDELAY(1); | ||
| 90 | timeout--; | ||
| 91 | } while (timeout > 0); | ||
| 92 | WREG32_MC(RS480_GART_CACHE_CNTRL, 0); | ||
| 93 | } | ||
| 94 | |||
| 95 | int rs400_gart_enable(struct radeon_device *rdev) | ||
| 96 | { | ||
| 97 | uint32_t size_reg; | ||
| 98 | uint32_t tmp; | ||
| 99 | int r; | ||
| 100 | |||
| 101 | /* Initialize common gart structure */ | ||
| 102 | r = radeon_gart_init(rdev); | ||
| 103 | if (r) { | ||
| 104 | return r; | ||
| 105 | } | ||
| 106 | if (rs400_debugfs_pcie_gart_info_init(rdev)) { | ||
| 107 | DRM_ERROR("Failed to register debugfs file for RS400 GART !\n"); | ||
| 108 | } | ||
| 109 | |||
| 110 | tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH); | ||
| 111 | tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS; | ||
| 112 | WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp); | ||
| 113 | /* Check gart size */ | ||
| 114 | switch(rdev->mc.gtt_size / (1024 * 1024)) { | ||
| 115 | case 32: | ||
| 116 | size_reg = RS480_VA_SIZE_32MB; | ||
| 117 | break; | ||
| 118 | case 64: | ||
| 119 | size_reg = RS480_VA_SIZE_64MB; | ||
| 120 | break; | ||
| 121 | case 128: | ||
| 122 | size_reg = RS480_VA_SIZE_128MB; | ||
| 123 | break; | ||
| 124 | case 256: | ||
| 125 | size_reg = RS480_VA_SIZE_256MB; | ||
| 126 | break; | ||
| 127 | case 512: | ||
| 128 | size_reg = RS480_VA_SIZE_512MB; | ||
| 129 | break; | ||
| 130 | case 1024: | ||
| 131 | size_reg = RS480_VA_SIZE_1GB; | ||
| 132 | break; | ||
| 133 | case 2048: | ||
| 134 | size_reg = RS480_VA_SIZE_2GB; | ||
| 135 | break; | ||
| 136 | default: | ||
| 137 | return -EINVAL; | ||
| 138 | } | ||
| 139 | if (rdev->gart.table.ram.ptr == NULL) { | ||
| 140 | rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; | ||
| 141 | r = radeon_gart_table_ram_alloc(rdev); | ||
| 142 | if (r) { | ||
| 143 | return r; | ||
| 144 | } | ||
| 145 | } | ||
| 146 | /* It should be fine to program it to max value */ | ||
| 147 | if (rdev->family == CHIP_RS690 || (rdev->family == CHIP_RS740)) { | ||
| 148 | WREG32_MC(RS690_MCCFG_AGP_BASE, 0xFFFFFFFF); | ||
| 149 | WREG32_MC(RS690_MCCFG_AGP_BASE_2, 0); | ||
| 150 | } else { | ||
| 151 | WREG32(RADEON_AGP_BASE, 0xFFFFFFFF); | ||
| 152 | WREG32(RS480_AGP_BASE_2, 0); | ||
| 153 | } | ||
| 154 | tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; | ||
| 155 | tmp = REG_SET(RS690_MC_AGP_TOP, tmp >> 16); | ||
| 156 | tmp |= REG_SET(RS690_MC_AGP_START, rdev->mc.gtt_location >> 16); | ||
| 157 | if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) { | ||
| 158 | WREG32_MC(RS690_MCCFG_AGP_LOCATION, tmp); | ||
| 159 | tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS; | ||
| 160 | WREG32(RADEON_BUS_CNTL, tmp); | ||
| 161 | } else { | ||
| 162 | WREG32(RADEON_MC_AGP_LOCATION, tmp); | ||
| 163 | tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; | ||
| 164 | WREG32(RADEON_BUS_CNTL, tmp); | ||
| 165 | } | ||
| 166 | /* Table should be in 32bits address space so ignore bits above. */ | ||
| 167 | tmp = rdev->gart.table_addr & 0xfffff000; | ||
| 168 | WREG32_MC(RS480_GART_BASE, tmp); | ||
| 169 | /* TODO: more tweaking here */ | ||
| 170 | WREG32_MC(RS480_GART_FEATURE_ID, | ||
| 171 | (RS480_TLB_ENABLE | | ||
| 172 | RS480_GTW_LAC_EN | RS480_1LEVEL_GART)); | ||
| 173 | /* Disable snooping */ | ||
| 174 | WREG32_MC(RS480_AGP_MODE_CNTL, | ||
| 175 | (1 << RS480_REQ_TYPE_SNOOP_SHIFT) | RS480_REQ_TYPE_SNOOP_DIS); | ||
| 176 | /* Disable AGP mode */ | ||
| 177 | /* FIXME: according to doc we should set HIDE_MMCFG_BAR=0, | ||
| 178 | * AGPMODE30=0 & AGP30ENHANCED=0 in NB_CNTL */ | ||
| 179 | if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) { | ||
| 180 | WREG32_MC(RS480_MC_MISC_CNTL, | ||
| 181 | (RS480_GART_INDEX_REG_EN | RS690_BLOCK_GFX_D3_EN)); | ||
| 182 | } else { | ||
| 183 | WREG32_MC(RS480_MC_MISC_CNTL, RS480_GART_INDEX_REG_EN); | ||
| 184 | } | ||
| 185 | /* Enable gart */ | ||
| 186 | WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | size_reg)); | ||
| 187 | rs400_gart_tlb_flush(rdev); | ||
| 188 | rdev->gart.ready = true; | ||
| 189 | return 0; | ||
| 190 | } | ||
| 191 | |||
| 192 | void rs400_gart_disable(struct radeon_device *rdev) | ||
| 193 | { | ||
| 194 | uint32_t tmp; | ||
| 195 | |||
| 196 | tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH); | ||
| 197 | tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS; | ||
| 198 | WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp); | ||
| 199 | WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, 0); | ||
| 200 | } | ||
| 201 | |||
| 202 | int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) | ||
| 203 | { | ||
| 204 | if (i < 0 || i > rdev->gart.num_gpu_pages) { | ||
| 205 | return -EINVAL; | ||
| 206 | } | ||
| 207 | rdev->gart.table.ram.ptr[i] = cpu_to_le32(((uint32_t)addr) | 0xC); | ||
| 208 | return 0; | ||
| 209 | } | ||
| 210 | |||
| 211 | |||
| 212 | /* | ||
| 213 | * MC functions. | ||
| 214 | */ | ||
| 215 | int rs400_mc_init(struct radeon_device *rdev) | ||
| 216 | { | ||
| 217 | uint32_t tmp; | ||
| 218 | int r; | ||
| 219 | |||
| 220 | if (r100_debugfs_rbbm_init(rdev)) { | ||
| 221 | DRM_ERROR("Failed to register debugfs file for RBBM !\n"); | ||
| 222 | } | ||
| 223 | |||
| 224 | rs400_gpu_init(rdev); | ||
| 225 | rs400_gart_disable(rdev); | ||
| 226 | rdev->mc.gtt_location = rdev->mc.vram_size; | ||
| 227 | rdev->mc.gtt_location += (rdev->mc.gtt_size - 1); | ||
| 228 | rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1); | ||
| 229 | rdev->mc.vram_location = 0xFFFFFFFFUL; | ||
| 230 | r = radeon_mc_setup(rdev); | ||
| 231 | if (r) { | ||
| 232 | return r; | ||
| 233 | } | ||
| 234 | |||
| 235 | r100_mc_disable_clients(rdev); | ||
| 236 | if (r300_mc_wait_for_idle(rdev)) { | ||
| 237 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 238 | "programming pipes. Bad things might happen.\n"); | ||
| 239 | } | ||
| 240 | |||
| 241 | tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; | ||
| 242 | tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16); | ||
| 243 | tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16); | ||
| 244 | WREG32(RADEON_MC_FB_LOCATION, tmp); | ||
| 245 | tmp = RREG32(RADEON_HOST_PATH_CNTL) | RADEON_HP_LIN_RD_CACHE_DIS; | ||
| 246 | WREG32(RADEON_HOST_PATH_CNTL, tmp | RADEON_HDP_SOFT_RESET | RADEON_HDP_READ_BUFFER_INVALIDATE); | ||
| 247 | (void)RREG32(RADEON_HOST_PATH_CNTL); | ||
| 248 | WREG32(RADEON_HOST_PATH_CNTL, tmp); | ||
| 249 | (void)RREG32(RADEON_HOST_PATH_CNTL); | ||
| 250 | return 0; | ||
| 251 | } | ||
| 252 | |||
| 253 | void rs400_mc_fini(struct radeon_device *rdev) | ||
| 254 | { | ||
| 255 | rs400_gart_disable(rdev); | ||
| 256 | radeon_gart_table_ram_free(rdev); | ||
| 257 | radeon_gart_fini(rdev); | ||
| 258 | } | ||
| 259 | |||
| 260 | |||
| 261 | /* | ||
| 262 | * Global GPU functions | ||
| 263 | */ | ||
| 264 | void rs400_errata(struct radeon_device *rdev) | ||
| 265 | { | ||
| 266 | rdev->pll_errata = 0; | ||
| 267 | } | ||
| 268 | |||
| 269 | void rs400_gpu_init(struct radeon_device *rdev) | ||
| 270 | { | ||
| 271 | /* FIXME: HDP same place on rs400 ? */ | ||
| 272 | r100_hdp_reset(rdev); | ||
| 273 | /* FIXME: is this correct ? */ | ||
| 274 | r420_pipes_init(rdev); | ||
| 275 | if (r300_mc_wait_for_idle(rdev)) { | ||
| 276 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 277 | "programming pipes. Bad things might happen.\n"); | ||
| 278 | } | ||
| 279 | } | ||
| 280 | |||
| 281 | |||
| 282 | /* | ||
| 283 | * VRAM info. | ||
| 284 | */ | ||
| 285 | void rs400_vram_info(struct radeon_device *rdev) | ||
| 286 | { | ||
| 287 | uint32_t tom; | ||
| 288 | |||
| 289 | rs400_gart_adjust_size(rdev); | ||
| 290 | /* DDR for all card after R300 & IGP */ | ||
| 291 | rdev->mc.vram_is_ddr = true; | ||
| 292 | rdev->mc.vram_width = 128; | ||
| 293 | |||
| 294 | /* read NB_TOM to get the amount of ram stolen for the GPU */ | ||
| 295 | tom = RREG32(RADEON_NB_TOM); | ||
| 296 | rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); | ||
| 297 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); | ||
| 298 | |||
| 299 | /* Could aper size report 0 ? */ | ||
| 300 | rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); | ||
| 301 | rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); | ||
| 302 | } | ||
| 303 | |||
| 304 | |||
| 305 | /* | ||
| 306 | * Indirect registers accessor | ||
| 307 | */ | ||
| 308 | uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg) | ||
| 309 | { | ||
| 310 | uint32_t r; | ||
| 311 | |||
| 312 | WREG32(RS480_NB_MC_INDEX, reg & 0xff); | ||
| 313 | r = RREG32(RS480_NB_MC_DATA); | ||
| 314 | WREG32(RS480_NB_MC_INDEX, 0xff); | ||
| 315 | return r; | ||
| 316 | } | ||
| 317 | |||
| 318 | void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | ||
| 319 | { | ||
| 320 | WREG32(RS480_NB_MC_INDEX, ((reg) & 0xff) | RS480_NB_MC_IND_WR_EN); | ||
| 321 | WREG32(RS480_NB_MC_DATA, (v)); | ||
| 322 | WREG32(RS480_NB_MC_INDEX, 0xff); | ||
| 323 | } | ||
| 324 | |||
| 325 | |||
| 326 | /* | ||
| 327 | * Debugfs info | ||
| 328 | */ | ||
| 329 | #if defined(CONFIG_DEBUG_FS) | ||
| 330 | static int rs400_debugfs_gart_info(struct seq_file *m, void *data) | ||
| 331 | { | ||
| 332 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
| 333 | struct drm_device *dev = node->minor->dev; | ||
| 334 | struct radeon_device *rdev = dev->dev_private; | ||
| 335 | uint32_t tmp; | ||
| 336 | |||
| 337 | tmp = RREG32(RADEON_HOST_PATH_CNTL); | ||
| 338 | seq_printf(m, "HOST_PATH_CNTL 0x%08x\n", tmp); | ||
| 339 | tmp = RREG32(RADEON_BUS_CNTL); | ||
| 340 | seq_printf(m, "BUS_CNTL 0x%08x\n", tmp); | ||
| 341 | tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH); | ||
| 342 | seq_printf(m, "AIC_CTRL_SCRATCH 0x%08x\n", tmp); | ||
| 343 | if (rdev->family == CHIP_RS690 || (rdev->family == CHIP_RS740)) { | ||
| 344 | tmp = RREG32_MC(RS690_MCCFG_AGP_BASE); | ||
| 345 | seq_printf(m, "MCCFG_AGP_BASE 0x%08x\n", tmp); | ||
| 346 | tmp = RREG32_MC(RS690_MCCFG_AGP_BASE_2); | ||
| 347 | seq_printf(m, "MCCFG_AGP_BASE_2 0x%08x\n", tmp); | ||
| 348 | tmp = RREG32_MC(RS690_MCCFG_AGP_LOCATION); | ||
| 349 | seq_printf(m, "MCCFG_AGP_LOCATION 0x%08x\n", tmp); | ||
| 350 | tmp = RREG32_MC(0x100); | ||
| 351 | seq_printf(m, "MCCFG_FB_LOCATION 0x%08x\n", tmp); | ||
| 352 | tmp = RREG32(0x134); | ||
| 353 | seq_printf(m, "HDP_FB_LOCATION 0x%08x\n", tmp); | ||
| 354 | } else { | ||
| 355 | tmp = RREG32(RADEON_AGP_BASE); | ||
| 356 | seq_printf(m, "AGP_BASE 0x%08x\n", tmp); | ||
| 357 | tmp = RREG32(RS480_AGP_BASE_2); | ||
| 358 | seq_printf(m, "AGP_BASE_2 0x%08x\n", tmp); | ||
| 359 | tmp = RREG32(RADEON_MC_AGP_LOCATION); | ||
| 360 | seq_printf(m, "MC_AGP_LOCATION 0x%08x\n", tmp); | ||
| 361 | } | ||
| 362 | tmp = RREG32_MC(RS480_GART_BASE); | ||
| 363 | seq_printf(m, "GART_BASE 0x%08x\n", tmp); | ||
| 364 | tmp = RREG32_MC(RS480_GART_FEATURE_ID); | ||
| 365 | seq_printf(m, "GART_FEATURE_ID 0x%08x\n", tmp); | ||
| 366 | tmp = RREG32_MC(RS480_AGP_MODE_CNTL); | ||
| 367 | seq_printf(m, "AGP_MODE_CONTROL 0x%08x\n", tmp); | ||
| 368 | tmp = RREG32_MC(RS480_MC_MISC_CNTL); | ||
| 369 | seq_printf(m, "MC_MISC_CNTL 0x%08x\n", tmp); | ||
| 370 | tmp = RREG32_MC(0x5F); | ||
| 371 | seq_printf(m, "MC_MISC_UMA_CNTL 0x%08x\n", tmp); | ||
| 372 | tmp = RREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE); | ||
| 373 | seq_printf(m, "AGP_ADDRESS_SPACE_SIZE 0x%08x\n", tmp); | ||
| 374 | tmp = RREG32_MC(RS480_GART_CACHE_CNTRL); | ||
| 375 | seq_printf(m, "GART_CACHE_CNTRL 0x%08x\n", tmp); | ||
| 376 | tmp = RREG32_MC(0x3B); | ||
| 377 | seq_printf(m, "MC_GART_ERROR_ADDRESS 0x%08x\n", tmp); | ||
| 378 | tmp = RREG32_MC(0x3C); | ||
| 379 | seq_printf(m, "MC_GART_ERROR_ADDRESS_HI 0x%08x\n", tmp); | ||
| 380 | tmp = RREG32_MC(0x30); | ||
| 381 | seq_printf(m, "GART_ERROR_0 0x%08x\n", tmp); | ||
| 382 | tmp = RREG32_MC(0x31); | ||
| 383 | seq_printf(m, "GART_ERROR_1 0x%08x\n", tmp); | ||
| 384 | tmp = RREG32_MC(0x32); | ||
| 385 | seq_printf(m, "GART_ERROR_2 0x%08x\n", tmp); | ||
| 386 | tmp = RREG32_MC(0x33); | ||
| 387 | seq_printf(m, "GART_ERROR_3 0x%08x\n", tmp); | ||
| 388 | tmp = RREG32_MC(0x34); | ||
| 389 | seq_printf(m, "GART_ERROR_4 0x%08x\n", tmp); | ||
| 390 | tmp = RREG32_MC(0x35); | ||
| 391 | seq_printf(m, "GART_ERROR_5 0x%08x\n", tmp); | ||
| 392 | tmp = RREG32_MC(0x36); | ||
| 393 | seq_printf(m, "GART_ERROR_6 0x%08x\n", tmp); | ||
| 394 | tmp = RREG32_MC(0x37); | ||
| 395 | seq_printf(m, "GART_ERROR_7 0x%08x\n", tmp); | ||
| 396 | return 0; | ||
| 397 | } | ||
| 398 | |||
| 399 | static struct drm_info_list rs400_gart_info_list[] = { | ||
| 400 | {"rs400_gart_info", rs400_debugfs_gart_info, 0, NULL}, | ||
| 401 | }; | ||
| 402 | #endif | ||
| 403 | |||
| 404 | int rs400_debugfs_pcie_gart_info_init(struct radeon_device *rdev) | ||
| 405 | { | ||
| 406 | #if defined(CONFIG_DEBUG_FS) | ||
| 407 | return radeon_debugfs_add_files(rdev, rs400_gart_info_list, 1); | ||
| 408 | #else | ||
| 409 | return 0; | ||
| 410 | #endif | ||
| 411 | } | ||
diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c new file mode 100644 index 000000000000..ab0c967553e6 --- /dev/null +++ b/drivers/gpu/drm/radeon/rs600.c | |||
| @@ -0,0 +1,324 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include "drmP.h" | ||
| 29 | #include "radeon_reg.h" | ||
| 30 | #include "radeon.h" | ||
| 31 | |||
| 32 | /* rs600 depends on : */ | ||
| 33 | void r100_hdp_reset(struct radeon_device *rdev); | ||
| 34 | int r100_gui_wait_for_idle(struct radeon_device *rdev); | ||
| 35 | int r300_mc_wait_for_idle(struct radeon_device *rdev); | ||
| 36 | void r420_pipes_init(struct radeon_device *rdev); | ||
| 37 | |||
| 38 | /* This files gather functions specifics to : | ||
| 39 | * rs600 | ||
| 40 | * | ||
| 41 | * Some of these functions might be used by newer ASICs. | ||
| 42 | */ | ||
| 43 | void rs600_gpu_init(struct radeon_device *rdev); | ||
| 44 | int rs600_mc_wait_for_idle(struct radeon_device *rdev); | ||
| 45 | void rs600_disable_vga(struct radeon_device *rdev); | ||
| 46 | |||
| 47 | |||
| 48 | /* | ||
| 49 | * GART. | ||
| 50 | */ | ||
| 51 | void rs600_gart_tlb_flush(struct radeon_device *rdev) | ||
| 52 | { | ||
| 53 | uint32_t tmp; | ||
| 54 | |||
| 55 | tmp = RREG32_MC(RS600_MC_PT0_CNTL); | ||
| 56 | tmp &= ~(RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE); | ||
| 57 | WREG32_MC(RS600_MC_PT0_CNTL, tmp); | ||
| 58 | |||
| 59 | tmp = RREG32_MC(RS600_MC_PT0_CNTL); | ||
| 60 | tmp |= RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE; | ||
| 61 | WREG32_MC(RS600_MC_PT0_CNTL, tmp); | ||
| 62 | |||
| 63 | tmp = RREG32_MC(RS600_MC_PT0_CNTL); | ||
| 64 | tmp &= ~(RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE); | ||
| 65 | WREG32_MC(RS600_MC_PT0_CNTL, tmp); | ||
| 66 | tmp = RREG32_MC(RS600_MC_PT0_CNTL); | ||
| 67 | } | ||
| 68 | |||
| 69 | int rs600_gart_enable(struct radeon_device *rdev) | ||
| 70 | { | ||
| 71 | uint32_t tmp; | ||
| 72 | int i; | ||
| 73 | int r; | ||
| 74 | |||
| 75 | /* Initialize common gart structure */ | ||
| 76 | r = radeon_gart_init(rdev); | ||
| 77 | if (r) { | ||
| 78 | return r; | ||
| 79 | } | ||
| 80 | rdev->gart.table_size = rdev->gart.num_gpu_pages * 8; | ||
| 81 | r = radeon_gart_table_vram_alloc(rdev); | ||
| 82 | if (r) { | ||
| 83 | return r; | ||
| 84 | } | ||
| 85 | /* FIXME: setup default page */ | ||
| 86 | WREG32_MC(RS600_MC_PT0_CNTL, | ||
| 87 | (RS600_EFFECTIVE_L2_CACHE_SIZE(6) | | ||
| 88 | RS600_EFFECTIVE_L2_QUEUE_SIZE(6))); | ||
| 89 | for (i = 0; i < 19; i++) { | ||
| 90 | WREG32_MC(RS600_MC_PT0_CLIENT0_CNTL + i, | ||
| 91 | (RS600_ENABLE_TRANSLATION_MODE_OVERRIDE | | ||
| 92 | RS600_SYSTEM_ACCESS_MODE_IN_SYS | | ||
| 93 | RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_DEFAULT_PAGE | | ||
| 94 | RS600_EFFECTIVE_L1_CACHE_SIZE(3) | | ||
| 95 | RS600_ENABLE_FRAGMENT_PROCESSING | | ||
| 96 | RS600_EFFECTIVE_L1_QUEUE_SIZE(3))); | ||
| 97 | } | ||
| 98 | |||
| 99 | /* System context map to GART space */ | ||
| 100 | WREG32_MC(RS600_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.gtt_location); | ||
| 101 | tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; | ||
| 102 | WREG32_MC(RS600_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, tmp); | ||
| 103 | |||
| 104 | /* enable first context */ | ||
| 105 | WREG32_MC(RS600_MC_PT0_CONTEXT0_FLAT_START_ADDR, rdev->mc.gtt_location); | ||
| 106 | tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; | ||
| 107 | WREG32_MC(RS600_MC_PT0_CONTEXT0_FLAT_END_ADDR, tmp); | ||
| 108 | WREG32_MC(RS600_MC_PT0_CONTEXT0_CNTL, | ||
| 109 | (RS600_ENABLE_PAGE_TABLE | RS600_PAGE_TABLE_TYPE_FLAT)); | ||
| 110 | /* disable all other contexts */ | ||
| 111 | for (i = 1; i < 8; i++) { | ||
| 112 | WREG32_MC(RS600_MC_PT0_CONTEXT0_CNTL + i, 0); | ||
| 113 | } | ||
| 114 | |||
| 115 | /* setup the page table */ | ||
| 116 | WREG32_MC(RS600_MC_PT0_CONTEXT0_FLAT_BASE_ADDR, | ||
| 117 | rdev->gart.table_addr); | ||
| 118 | WREG32_MC(RS600_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR, 0); | ||
| 119 | |||
| 120 | /* enable page tables */ | ||
| 121 | tmp = RREG32_MC(RS600_MC_PT0_CNTL); | ||
| 122 | WREG32_MC(RS600_MC_PT0_CNTL, (tmp | RS600_ENABLE_PT)); | ||
| 123 | tmp = RREG32_MC(RS600_MC_CNTL1); | ||
| 124 | WREG32_MC(RS600_MC_CNTL1, (tmp | RS600_ENABLE_PAGE_TABLES)); | ||
| 125 | rs600_gart_tlb_flush(rdev); | ||
| 126 | rdev->gart.ready = true; | ||
| 127 | return 0; | ||
| 128 | } | ||
| 129 | |||
| 130 | void rs600_gart_disable(struct radeon_device *rdev) | ||
| 131 | { | ||
| 132 | uint32_t tmp; | ||
| 133 | |||
| 134 | /* FIXME: disable out of gart access */ | ||
| 135 | WREG32_MC(RS600_MC_PT0_CNTL, 0); | ||
| 136 | tmp = RREG32_MC(RS600_MC_CNTL1); | ||
| 137 | tmp &= ~RS600_ENABLE_PAGE_TABLES; | ||
| 138 | WREG32_MC(RS600_MC_CNTL1, tmp); | ||
| 139 | radeon_object_kunmap(rdev->gart.table.vram.robj); | ||
| 140 | radeon_object_unpin(rdev->gart.table.vram.robj); | ||
| 141 | } | ||
| 142 | |||
| 143 | #define R600_PTE_VALID (1 << 0) | ||
| 144 | #define R600_PTE_SYSTEM (1 << 1) | ||
| 145 | #define R600_PTE_SNOOPED (1 << 2) | ||
| 146 | #define R600_PTE_READABLE (1 << 5) | ||
| 147 | #define R600_PTE_WRITEABLE (1 << 6) | ||
| 148 | |||
| 149 | int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) | ||
| 150 | { | ||
| 151 | void __iomem *ptr = (void *)rdev->gart.table.vram.ptr; | ||
| 152 | |||
| 153 | if (i < 0 || i > rdev->gart.num_gpu_pages) { | ||
| 154 | return -EINVAL; | ||
| 155 | } | ||
| 156 | addr = addr & 0xFFFFFFFFFFFFF000ULL; | ||
| 157 | addr |= R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED; | ||
| 158 | addr |= R600_PTE_READABLE | R600_PTE_WRITEABLE; | ||
| 159 | writeq(addr, ((void __iomem *)ptr) + (i * 8)); | ||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | |||
| 163 | |||
| 164 | /* | ||
| 165 | * MC. | ||
| 166 | */ | ||
| 167 | void rs600_mc_disable_clients(struct radeon_device *rdev) | ||
| 168 | { | ||
| 169 | unsigned tmp; | ||
| 170 | |||
| 171 | if (r100_gui_wait_for_idle(rdev)) { | ||
| 172 | printk(KERN_WARNING "Failed to wait GUI idle while " | ||
| 173 | "programming pipes. Bad things might happen.\n"); | ||
| 174 | } | ||
| 175 | |||
| 176 | tmp = RREG32(AVIVO_D1VGA_CONTROL); | ||
| 177 | WREG32(AVIVO_D1VGA_CONTROL, tmp & ~AVIVO_DVGA_CONTROL_MODE_ENABLE); | ||
| 178 | tmp = RREG32(AVIVO_D2VGA_CONTROL); | ||
| 179 | WREG32(AVIVO_D2VGA_CONTROL, tmp & ~AVIVO_DVGA_CONTROL_MODE_ENABLE); | ||
| 180 | |||
| 181 | tmp = RREG32(AVIVO_D1CRTC_CONTROL); | ||
| 182 | WREG32(AVIVO_D1CRTC_CONTROL, tmp & ~AVIVO_CRTC_EN); | ||
| 183 | tmp = RREG32(AVIVO_D2CRTC_CONTROL); | ||
| 184 | WREG32(AVIVO_D2CRTC_CONTROL, tmp & ~AVIVO_CRTC_EN); | ||
| 185 | |||
| 186 | /* make sure all previous write got through */ | ||
| 187 | tmp = RREG32(AVIVO_D2CRTC_CONTROL); | ||
| 188 | |||
| 189 | mdelay(1); | ||
| 190 | } | ||
| 191 | |||
| 192 | int rs600_mc_init(struct radeon_device *rdev) | ||
| 193 | { | ||
| 194 | uint32_t tmp; | ||
| 195 | int r; | ||
| 196 | |||
| 197 | if (r100_debugfs_rbbm_init(rdev)) { | ||
| 198 | DRM_ERROR("Failed to register debugfs file for RBBM !\n"); | ||
| 199 | } | ||
| 200 | |||
| 201 | rs600_gpu_init(rdev); | ||
| 202 | rs600_gart_disable(rdev); | ||
| 203 | |||
| 204 | /* Setup GPU memory space */ | ||
| 205 | rdev->mc.vram_location = 0xFFFFFFFFUL; | ||
| 206 | rdev->mc.gtt_location = 0xFFFFFFFFUL; | ||
| 207 | r = radeon_mc_setup(rdev); | ||
| 208 | if (r) { | ||
| 209 | return r; | ||
| 210 | } | ||
| 211 | |||
| 212 | /* Program GPU memory space */ | ||
| 213 | /* Enable bus master */ | ||
| 214 | tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS; | ||
| 215 | WREG32(RADEON_BUS_CNTL, tmp); | ||
| 216 | /* FIXME: What does AGP means for such chipset ? */ | ||
| 217 | WREG32_MC(RS600_MC_AGP_LOCATION, 0x0FFFFFFF); | ||
| 218 | /* FIXME: are this AGP reg in indirect MC range ? */ | ||
| 219 | WREG32_MC(RS600_MC_AGP_BASE, 0); | ||
| 220 | WREG32_MC(RS600_MC_AGP_BASE_2, 0); | ||
| 221 | rs600_mc_disable_clients(rdev); | ||
| 222 | if (rs600_mc_wait_for_idle(rdev)) { | ||
| 223 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 224 | "programming pipes. Bad things might happen.\n"); | ||
| 225 | } | ||
| 226 | tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; | ||
| 227 | tmp = REG_SET(RS600_MC_FB_TOP, tmp >> 16); | ||
| 228 | tmp |= REG_SET(RS600_MC_FB_START, rdev->mc.vram_location >> 16); | ||
| 229 | WREG32_MC(RS600_MC_FB_LOCATION, tmp); | ||
| 230 | WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16); | ||
| 231 | return 0; | ||
| 232 | } | ||
| 233 | |||
| 234 | void rs600_mc_fini(struct radeon_device *rdev) | ||
| 235 | { | ||
| 236 | rs600_gart_disable(rdev); | ||
| 237 | radeon_gart_table_vram_free(rdev); | ||
| 238 | radeon_gart_fini(rdev); | ||
| 239 | } | ||
| 240 | |||
| 241 | |||
| 242 | /* | ||
| 243 | * Global GPU functions | ||
| 244 | */ | ||
| 245 | void rs600_disable_vga(struct radeon_device *rdev) | ||
| 246 | { | ||
| 247 | unsigned tmp; | ||
| 248 | |||
| 249 | WREG32(0x330, 0); | ||
| 250 | WREG32(0x338, 0); | ||
| 251 | tmp = RREG32(0x300); | ||
| 252 | tmp &= ~(3 << 16); | ||
| 253 | WREG32(0x300, tmp); | ||
| 254 | WREG32(0x308, (1 << 8)); | ||
| 255 | WREG32(0x310, rdev->mc.vram_location); | ||
| 256 | WREG32(0x594, 0); | ||
| 257 | } | ||
| 258 | |||
| 259 | int rs600_mc_wait_for_idle(struct radeon_device *rdev) | ||
| 260 | { | ||
| 261 | unsigned i; | ||
| 262 | uint32_t tmp; | ||
| 263 | |||
| 264 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 265 | /* read MC_STATUS */ | ||
| 266 | tmp = RREG32_MC(RS600_MC_STATUS); | ||
| 267 | if (tmp & RS600_MC_STATUS_IDLE) { | ||
| 268 | return 0; | ||
| 269 | } | ||
| 270 | DRM_UDELAY(1); | ||
| 271 | } | ||
| 272 | return -1; | ||
| 273 | } | ||
| 274 | |||
| 275 | void rs600_errata(struct radeon_device *rdev) | ||
| 276 | { | ||
| 277 | rdev->pll_errata = 0; | ||
| 278 | } | ||
| 279 | |||
| 280 | void rs600_gpu_init(struct radeon_device *rdev) | ||
| 281 | { | ||
| 282 | /* FIXME: HDP same place on rs600 ? */ | ||
| 283 | r100_hdp_reset(rdev); | ||
| 284 | rs600_disable_vga(rdev); | ||
| 285 | /* FIXME: is this correct ? */ | ||
| 286 | r420_pipes_init(rdev); | ||
| 287 | if (rs600_mc_wait_for_idle(rdev)) { | ||
| 288 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 289 | "programming pipes. Bad things might happen.\n"); | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 293 | |||
| 294 | /* | ||
| 295 | * VRAM info. | ||
| 296 | */ | ||
| 297 | void rs600_vram_info(struct radeon_device *rdev) | ||
| 298 | { | ||
| 299 | /* FIXME: to do or is these values sane ? */ | ||
| 300 | rdev->mc.vram_is_ddr = true; | ||
| 301 | rdev->mc.vram_width = 128; | ||
| 302 | } | ||
| 303 | |||
| 304 | |||
| 305 | /* | ||
| 306 | * Indirect registers accessor | ||
| 307 | */ | ||
| 308 | uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg) | ||
| 309 | { | ||
| 310 | uint32_t r; | ||
| 311 | |||
| 312 | WREG32(RS600_MC_INDEX, | ||
| 313 | ((reg & RS600_MC_ADDR_MASK) | RS600_MC_IND_CITF_ARB0)); | ||
| 314 | r = RREG32(RS600_MC_DATA); | ||
| 315 | return r; | ||
| 316 | } | ||
| 317 | |||
| 318 | void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | ||
| 319 | { | ||
| 320 | WREG32(RS600_MC_INDEX, | ||
| 321 | RS600_MC_IND_WR_EN | RS600_MC_IND_CITF_ARB0 | | ||
| 322 | ((reg) & RS600_MC_ADDR_MASK)); | ||
| 323 | WREG32(RS600_MC_DATA, v); | ||
| 324 | } | ||
diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c new file mode 100644 index 000000000000..79ba85042b5f --- /dev/null +++ b/drivers/gpu/drm/radeon/rs690.c | |||
| @@ -0,0 +1,181 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include "drmP.h" | ||
| 29 | #include "radeon_reg.h" | ||
| 30 | #include "radeon.h" | ||
| 31 | |||
| 32 | /* rs690,rs740 depends on : */ | ||
| 33 | void r100_hdp_reset(struct radeon_device *rdev); | ||
| 34 | int r300_mc_wait_for_idle(struct radeon_device *rdev); | ||
| 35 | void r420_pipes_init(struct radeon_device *rdev); | ||
| 36 | void rs400_gart_disable(struct radeon_device *rdev); | ||
| 37 | int rs400_gart_enable(struct radeon_device *rdev); | ||
| 38 | void rs400_gart_adjust_size(struct radeon_device *rdev); | ||
| 39 | void rs600_mc_disable_clients(struct radeon_device *rdev); | ||
| 40 | void rs600_disable_vga(struct radeon_device *rdev); | ||
| 41 | |||
| 42 | /* This files gather functions specifics to : | ||
| 43 | * rs690,rs740 | ||
| 44 | * | ||
| 45 | * Some of these functions might be used by newer ASICs. | ||
| 46 | */ | ||
| 47 | void rs690_gpu_init(struct radeon_device *rdev); | ||
| 48 | int rs690_mc_wait_for_idle(struct radeon_device *rdev); | ||
| 49 | |||
| 50 | |||
| 51 | /* | ||
| 52 | * MC functions. | ||
| 53 | */ | ||
| 54 | int rs690_mc_init(struct radeon_device *rdev) | ||
| 55 | { | ||
| 56 | uint32_t tmp; | ||
| 57 | int r; | ||
| 58 | |||
| 59 | if (r100_debugfs_rbbm_init(rdev)) { | ||
| 60 | DRM_ERROR("Failed to register debugfs file for RBBM !\n"); | ||
| 61 | } | ||
| 62 | |||
| 63 | rs690_gpu_init(rdev); | ||
| 64 | rs400_gart_disable(rdev); | ||
| 65 | |||
| 66 | /* Setup GPU memory space */ | ||
| 67 | rdev->mc.gtt_location = rdev->mc.vram_size; | ||
| 68 | rdev->mc.gtt_location += (rdev->mc.gtt_size - 1); | ||
| 69 | rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1); | ||
| 70 | rdev->mc.vram_location = 0xFFFFFFFFUL; | ||
| 71 | r = radeon_mc_setup(rdev); | ||
| 72 | if (r) { | ||
| 73 | return r; | ||
| 74 | } | ||
| 75 | |||
| 76 | /* Program GPU memory space */ | ||
| 77 | rs600_mc_disable_clients(rdev); | ||
| 78 | if (rs690_mc_wait_for_idle(rdev)) { | ||
| 79 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 80 | "programming pipes. Bad things might happen.\n"); | ||
| 81 | } | ||
| 82 | tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; | ||
| 83 | tmp = REG_SET(RS690_MC_FB_TOP, tmp >> 16); | ||
| 84 | tmp |= REG_SET(RS690_MC_FB_START, rdev->mc.vram_location >> 16); | ||
| 85 | WREG32_MC(RS690_MCCFG_FB_LOCATION, tmp); | ||
| 86 | /* FIXME: Does this reg exist on RS480,RS740 ? */ | ||
| 87 | WREG32(0x310, rdev->mc.vram_location); | ||
| 88 | WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16); | ||
| 89 | return 0; | ||
| 90 | } | ||
| 91 | |||
| 92 | void rs690_mc_fini(struct radeon_device *rdev) | ||
| 93 | { | ||
| 94 | rs400_gart_disable(rdev); | ||
| 95 | radeon_gart_table_ram_free(rdev); | ||
| 96 | radeon_gart_fini(rdev); | ||
| 97 | } | ||
| 98 | |||
| 99 | |||
| 100 | /* | ||
| 101 | * Global GPU functions | ||
| 102 | */ | ||
| 103 | int rs690_mc_wait_for_idle(struct radeon_device *rdev) | ||
| 104 | { | ||
| 105 | unsigned i; | ||
| 106 | uint32_t tmp; | ||
| 107 | |||
| 108 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 109 | /* read MC_STATUS */ | ||
| 110 | tmp = RREG32_MC(RS690_MC_STATUS); | ||
| 111 | if (tmp & RS690_MC_STATUS_IDLE) { | ||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | DRM_UDELAY(1); | ||
| 115 | } | ||
| 116 | return -1; | ||
| 117 | } | ||
| 118 | |||
| 119 | void rs690_errata(struct radeon_device *rdev) | ||
| 120 | { | ||
| 121 | rdev->pll_errata = 0; | ||
| 122 | } | ||
| 123 | |||
| 124 | void rs690_gpu_init(struct radeon_device *rdev) | ||
| 125 | { | ||
| 126 | /* FIXME: HDP same place on rs690 ? */ | ||
| 127 | r100_hdp_reset(rdev); | ||
| 128 | rs600_disable_vga(rdev); | ||
| 129 | /* FIXME: is this correct ? */ | ||
| 130 | r420_pipes_init(rdev); | ||
| 131 | if (rs690_mc_wait_for_idle(rdev)) { | ||
| 132 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 133 | "programming pipes. Bad things might happen.\n"); | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | |||
| 138 | /* | ||
| 139 | * VRAM info. | ||
| 140 | */ | ||
| 141 | void rs690_vram_info(struct radeon_device *rdev) | ||
| 142 | { | ||
| 143 | uint32_t tmp; | ||
| 144 | |||
| 145 | rs400_gart_adjust_size(rdev); | ||
| 146 | /* DDR for all card after R300 & IGP */ | ||
| 147 | rdev->mc.vram_is_ddr = true; | ||
| 148 | /* FIXME: is this correct for RS690/RS740 ? */ | ||
| 149 | tmp = RREG32(RADEON_MEM_CNTL); | ||
| 150 | if (tmp & R300_MEM_NUM_CHANNELS_MASK) { | ||
| 151 | rdev->mc.vram_width = 128; | ||
| 152 | } else { | ||
| 153 | rdev->mc.vram_width = 64; | ||
| 154 | } | ||
| 155 | rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); | ||
| 156 | |||
| 157 | rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); | ||
| 158 | rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); | ||
| 159 | } | ||
| 160 | |||
| 161 | |||
| 162 | /* | ||
| 163 | * Indirect registers accessor | ||
| 164 | */ | ||
| 165 | uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg) | ||
| 166 | { | ||
| 167 | uint32_t r; | ||
| 168 | |||
| 169 | WREG32(RS690_MC_INDEX, (reg & RS690_MC_INDEX_MASK)); | ||
| 170 | r = RREG32(RS690_MC_DATA); | ||
| 171 | WREG32(RS690_MC_INDEX, RS690_MC_INDEX_MASK); | ||
| 172 | return r; | ||
| 173 | } | ||
| 174 | |||
| 175 | void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | ||
| 176 | { | ||
| 177 | WREG32(RS690_MC_INDEX, | ||
| 178 | RS690_MC_INDEX_WR_EN | ((reg) & RS690_MC_INDEX_MASK)); | ||
| 179 | WREG32(RS690_MC_DATA, v); | ||
| 180 | WREG32(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK); | ||
| 181 | } | ||
diff --git a/drivers/gpu/drm/radeon/rs780.c b/drivers/gpu/drm/radeon/rs780.c new file mode 100644 index 000000000000..0affcff81825 --- /dev/null +++ b/drivers/gpu/drm/radeon/rs780.c | |||
| @@ -0,0 +1,102 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include "drmP.h" | ||
| 29 | #include "radeon_reg.h" | ||
| 30 | #include "radeon.h" | ||
| 31 | |||
| 32 | /* rs780 depends on : */ | ||
| 33 | void rs600_mc_disable_clients(struct radeon_device *rdev); | ||
| 34 | |||
| 35 | /* This files gather functions specifics to: | ||
| 36 | * rs780 | ||
| 37 | * | ||
| 38 | * Some of these functions might be used by newer ASICs. | ||
| 39 | */ | ||
| 40 | int rs780_mc_wait_for_idle(struct radeon_device *rdev); | ||
| 41 | void rs780_gpu_init(struct radeon_device *rdev); | ||
| 42 | |||
| 43 | |||
| 44 | /* | ||
| 45 | * MC | ||
| 46 | */ | ||
| 47 | int rs780_mc_init(struct radeon_device *rdev) | ||
| 48 | { | ||
| 49 | rs780_gpu_init(rdev); | ||
| 50 | /* FIXME: implement */ | ||
| 51 | |||
| 52 | rs600_mc_disable_clients(rdev); | ||
| 53 | if (rs780_mc_wait_for_idle(rdev)) { | ||
| 54 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 55 | "programming pipes. Bad things might happen.\n"); | ||
| 56 | } | ||
| 57 | return 0; | ||
| 58 | } | ||
| 59 | |||
| 60 | void rs780_mc_fini(struct radeon_device *rdev) | ||
| 61 | { | ||
| 62 | /* FIXME: implement */ | ||
| 63 | } | ||
| 64 | |||
| 65 | |||
| 66 | /* | ||
| 67 | * Global GPU functions | ||
| 68 | */ | ||
| 69 | void rs780_errata(struct radeon_device *rdev) | ||
| 70 | { | ||
| 71 | rdev->pll_errata = 0; | ||
| 72 | } | ||
| 73 | |||
| 74 | int rs780_mc_wait_for_idle(struct radeon_device *rdev) | ||
| 75 | { | ||
| 76 | /* FIXME: implement */ | ||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | |||
| 80 | void rs780_gpu_init(struct radeon_device *rdev) | ||
| 81 | { | ||
| 82 | /* FIXME: implement */ | ||
| 83 | } | ||
| 84 | |||
| 85 | |||
| 86 | /* | ||
| 87 | * VRAM info | ||
| 88 | */ | ||
| 89 | void rs780_vram_get_type(struct radeon_device *rdev) | ||
| 90 | { | ||
| 91 | /* FIXME: implement */ | ||
| 92 | } | ||
| 93 | |||
| 94 | void rs780_vram_info(struct radeon_device *rdev) | ||
| 95 | { | ||
| 96 | rs780_vram_get_type(rdev); | ||
| 97 | |||
| 98 | /* FIXME: implement */ | ||
| 99 | /* Could aper size report 0 ? */ | ||
| 100 | rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); | ||
| 101 | rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); | ||
| 102 | } | ||
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c new file mode 100644 index 000000000000..7eab95db58ac --- /dev/null +++ b/drivers/gpu/drm/radeon/rv515.c | |||
| @@ -0,0 +1,504 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include <linux/seq_file.h> | ||
| 29 | #include "drmP.h" | ||
| 30 | #include "radeon_reg.h" | ||
| 31 | #include "radeon.h" | ||
| 32 | |||
| 33 | /* rv515 depends on : */ | ||
| 34 | void r100_hdp_reset(struct radeon_device *rdev); | ||
| 35 | int r100_cp_reset(struct radeon_device *rdev); | ||
| 36 | int r100_rb2d_reset(struct radeon_device *rdev); | ||
| 37 | int r100_gui_wait_for_idle(struct radeon_device *rdev); | ||
| 38 | int r100_cp_init(struct radeon_device *rdev, unsigned ring_size); | ||
| 39 | int rv370_pcie_gart_enable(struct radeon_device *rdev); | ||
| 40 | void rv370_pcie_gart_disable(struct radeon_device *rdev); | ||
| 41 | void r420_pipes_init(struct radeon_device *rdev); | ||
| 42 | void rs600_mc_disable_clients(struct radeon_device *rdev); | ||
| 43 | void rs600_disable_vga(struct radeon_device *rdev); | ||
| 44 | |||
| 45 | /* This files gather functions specifics to: | ||
| 46 | * rv515 | ||
| 47 | * | ||
| 48 | * Some of these functions might be used by newer ASICs. | ||
| 49 | */ | ||
| 50 | int rv515_debugfs_pipes_info_init(struct radeon_device *rdev); | ||
| 51 | int rv515_debugfs_ga_info_init(struct radeon_device *rdev); | ||
| 52 | void rv515_gpu_init(struct radeon_device *rdev); | ||
| 53 | int rv515_mc_wait_for_idle(struct radeon_device *rdev); | ||
| 54 | |||
| 55 | |||
| 56 | /* | ||
| 57 | * MC | ||
| 58 | */ | ||
| 59 | int rv515_mc_init(struct radeon_device *rdev) | ||
| 60 | { | ||
| 61 | uint32_t tmp; | ||
| 62 | int r; | ||
| 63 | |||
| 64 | if (r100_debugfs_rbbm_init(rdev)) { | ||
| 65 | DRM_ERROR("Failed to register debugfs file for RBBM !\n"); | ||
| 66 | } | ||
| 67 | if (rv515_debugfs_pipes_info_init(rdev)) { | ||
| 68 | DRM_ERROR("Failed to register debugfs file for pipes !\n"); | ||
| 69 | } | ||
| 70 | if (rv515_debugfs_ga_info_init(rdev)) { | ||
| 71 | DRM_ERROR("Failed to register debugfs file for pipes !\n"); | ||
| 72 | } | ||
| 73 | |||
| 74 | rv515_gpu_init(rdev); | ||
| 75 | rv370_pcie_gart_disable(rdev); | ||
| 76 | |||
| 77 | /* Setup GPU memory space */ | ||
| 78 | rdev->mc.vram_location = 0xFFFFFFFFUL; | ||
| 79 | rdev->mc.gtt_location = 0xFFFFFFFFUL; | ||
| 80 | if (rdev->flags & RADEON_IS_AGP) { | ||
| 81 | r = radeon_agp_init(rdev); | ||
| 82 | if (r) { | ||
| 83 | printk(KERN_WARNING "[drm] Disabling AGP\n"); | ||
| 84 | rdev->flags &= ~RADEON_IS_AGP; | ||
| 85 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; | ||
| 86 | } else { | ||
| 87 | rdev->mc.gtt_location = rdev->mc.agp_base; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | r = radeon_mc_setup(rdev); | ||
| 91 | if (r) { | ||
| 92 | return r; | ||
| 93 | } | ||
| 94 | |||
| 95 | /* Program GPU memory space */ | ||
| 96 | rs600_mc_disable_clients(rdev); | ||
| 97 | if (rv515_mc_wait_for_idle(rdev)) { | ||
| 98 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 99 | "programming pipes. Bad things might happen.\n"); | ||
| 100 | } | ||
| 101 | /* Write VRAM size in case we are limiting it */ | ||
| 102 | WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); | ||
| 103 | tmp = REG_SET(RV515_MC_FB_START, rdev->mc.vram_location >> 16); | ||
| 104 | WREG32(0x134, tmp); | ||
| 105 | tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; | ||
| 106 | tmp = REG_SET(RV515_MC_FB_TOP, tmp >> 16); | ||
| 107 | tmp |= REG_SET(RV515_MC_FB_START, rdev->mc.vram_location >> 16); | ||
| 108 | WREG32_MC(RV515_MC_FB_LOCATION, tmp); | ||
| 109 | WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16); | ||
| 110 | WREG32(0x310, rdev->mc.vram_location); | ||
| 111 | if (rdev->flags & RADEON_IS_AGP) { | ||
| 112 | tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; | ||
| 113 | tmp = REG_SET(RV515_MC_AGP_TOP, tmp >> 16); | ||
| 114 | tmp |= REG_SET(RV515_MC_AGP_START, rdev->mc.gtt_location >> 16); | ||
| 115 | WREG32_MC(RV515_MC_AGP_LOCATION, tmp); | ||
| 116 | WREG32_MC(RV515_MC_AGP_BASE, rdev->mc.agp_base); | ||
| 117 | WREG32_MC(RV515_MC_AGP_BASE_2, 0); | ||
| 118 | } else { | ||
| 119 | WREG32_MC(RV515_MC_AGP_LOCATION, 0x0FFFFFFF); | ||
| 120 | WREG32_MC(RV515_MC_AGP_BASE, 0); | ||
| 121 | WREG32_MC(RV515_MC_AGP_BASE_2, 0); | ||
| 122 | } | ||
| 123 | return 0; | ||
| 124 | } | ||
| 125 | |||
| 126 | void rv515_mc_fini(struct radeon_device *rdev) | ||
| 127 | { | ||
| 128 | rv370_pcie_gart_disable(rdev); | ||
| 129 | radeon_gart_table_vram_free(rdev); | ||
| 130 | radeon_gart_fini(rdev); | ||
| 131 | } | ||
| 132 | |||
| 133 | |||
| 134 | /* | ||
| 135 | * Global GPU functions | ||
| 136 | */ | ||
| 137 | void rv515_ring_start(struct radeon_device *rdev) | ||
| 138 | { | ||
| 139 | unsigned gb_tile_config; | ||
| 140 | int r; | ||
| 141 | |||
| 142 | /* Sub pixel 1/12 so we can have 4K rendering according to doc */ | ||
| 143 | gb_tile_config = R300_ENABLE_TILING | R300_TILE_SIZE_16; | ||
| 144 | switch (rdev->num_gb_pipes) { | ||
| 145 | case 2: | ||
| 146 | gb_tile_config |= R300_PIPE_COUNT_R300; | ||
| 147 | break; | ||
| 148 | case 3: | ||
| 149 | gb_tile_config |= R300_PIPE_COUNT_R420_3P; | ||
| 150 | break; | ||
| 151 | case 4: | ||
| 152 | gb_tile_config |= R300_PIPE_COUNT_R420; | ||
| 153 | break; | ||
| 154 | case 1: | ||
| 155 | default: | ||
| 156 | gb_tile_config |= R300_PIPE_COUNT_RV350; | ||
| 157 | break; | ||
| 158 | } | ||
| 159 | |||
| 160 | r = radeon_ring_lock(rdev, 64); | ||
| 161 | if (r) { | ||
| 162 | return; | ||
| 163 | } | ||
| 164 | radeon_ring_write(rdev, PACKET0(RADEON_ISYNC_CNTL, 0)); | ||
| 165 | radeon_ring_write(rdev, | ||
| 166 | RADEON_ISYNC_ANY2D_IDLE3D | | ||
| 167 | RADEON_ISYNC_ANY3D_IDLE2D | | ||
| 168 | RADEON_ISYNC_WAIT_IDLEGUI | | ||
| 169 | RADEON_ISYNC_CPSCRATCH_IDLEGUI); | ||
| 170 | radeon_ring_write(rdev, PACKET0(R300_GB_TILE_CONFIG, 0)); | ||
| 171 | radeon_ring_write(rdev, gb_tile_config); | ||
| 172 | radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); | ||
| 173 | radeon_ring_write(rdev, | ||
| 174 | RADEON_WAIT_2D_IDLECLEAN | | ||
| 175 | RADEON_WAIT_3D_IDLECLEAN); | ||
| 176 | radeon_ring_write(rdev, PACKET0(0x170C, 0)); | ||
| 177 | radeon_ring_write(rdev, 1 << 31); | ||
| 178 | radeon_ring_write(rdev, PACKET0(R300_GB_SELECT, 0)); | ||
| 179 | radeon_ring_write(rdev, 0); | ||
| 180 | radeon_ring_write(rdev, PACKET0(R300_GB_ENABLE, 0)); | ||
| 181 | radeon_ring_write(rdev, 0); | ||
| 182 | radeon_ring_write(rdev, PACKET0(0x42C8, 0)); | ||
| 183 | radeon_ring_write(rdev, (1 << rdev->num_gb_pipes) - 1); | ||
| 184 | radeon_ring_write(rdev, PACKET0(R500_VAP_INDEX_OFFSET, 0)); | ||
| 185 | radeon_ring_write(rdev, 0); | ||
| 186 | radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); | ||
| 187 | radeon_ring_write(rdev, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); | ||
| 188 | radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); | ||
| 189 | radeon_ring_write(rdev, R300_ZC_FLUSH | R300_ZC_FREE); | ||
| 190 | radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0)); | ||
| 191 | radeon_ring_write(rdev, | ||
| 192 | RADEON_WAIT_2D_IDLECLEAN | | ||
| 193 | RADEON_WAIT_3D_IDLECLEAN); | ||
| 194 | radeon_ring_write(rdev, PACKET0(R300_GB_AA_CONFIG, 0)); | ||
| 195 | radeon_ring_write(rdev, 0); | ||
| 196 | radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); | ||
| 197 | radeon_ring_write(rdev, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); | ||
| 198 | radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0)); | ||
| 199 | radeon_ring_write(rdev, R300_ZC_FLUSH | R300_ZC_FREE); | ||
| 200 | radeon_ring_write(rdev, PACKET0(R300_GB_MSPOS0, 0)); | ||
| 201 | radeon_ring_write(rdev, | ||
| 202 | ((6 << R300_MS_X0_SHIFT) | | ||
| 203 | (6 << R300_MS_Y0_SHIFT) | | ||
| 204 | (6 << R300_MS_X1_SHIFT) | | ||
| 205 | (6 << R300_MS_Y1_SHIFT) | | ||
| 206 | (6 << R300_MS_X2_SHIFT) | | ||
| 207 | (6 << R300_MS_Y2_SHIFT) | | ||
| 208 | (6 << R300_MSBD0_Y_SHIFT) | | ||
| 209 | (6 << R300_MSBD0_X_SHIFT))); | ||
| 210 | radeon_ring_write(rdev, PACKET0(R300_GB_MSPOS1, 0)); | ||
| 211 | radeon_ring_write(rdev, | ||
| 212 | ((6 << R300_MS_X3_SHIFT) | | ||
| 213 | (6 << R300_MS_Y3_SHIFT) | | ||
| 214 | (6 << R300_MS_X4_SHIFT) | | ||
| 215 | (6 << R300_MS_Y4_SHIFT) | | ||
| 216 | (6 << R300_MS_X5_SHIFT) | | ||
| 217 | (6 << R300_MS_Y5_SHIFT) | | ||
| 218 | (6 << R300_MSBD1_SHIFT))); | ||
| 219 | radeon_ring_write(rdev, PACKET0(R300_GA_ENHANCE, 0)); | ||
| 220 | radeon_ring_write(rdev, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL); | ||
| 221 | radeon_ring_write(rdev, PACKET0(R300_GA_POLY_MODE, 0)); | ||
| 222 | radeon_ring_write(rdev, | ||
| 223 | R300_FRONT_PTYPE_TRIANGE | R300_BACK_PTYPE_TRIANGE); | ||
| 224 | radeon_ring_write(rdev, PACKET0(R300_GA_ROUND_MODE, 0)); | ||
| 225 | radeon_ring_write(rdev, | ||
| 226 | R300_GEOMETRY_ROUND_NEAREST | | ||
| 227 | R300_COLOR_ROUND_NEAREST); | ||
| 228 | radeon_ring_unlock_commit(rdev); | ||
| 229 | } | ||
| 230 | |||
| 231 | void rv515_errata(struct radeon_device *rdev) | ||
| 232 | { | ||
| 233 | rdev->pll_errata = 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | int rv515_mc_wait_for_idle(struct radeon_device *rdev) | ||
| 237 | { | ||
| 238 | unsigned i; | ||
| 239 | uint32_t tmp; | ||
| 240 | |||
| 241 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 242 | /* read MC_STATUS */ | ||
| 243 | tmp = RREG32_MC(RV515_MC_STATUS); | ||
| 244 | if (tmp & RV515_MC_STATUS_IDLE) { | ||
| 245 | return 0; | ||
| 246 | } | ||
| 247 | DRM_UDELAY(1); | ||
| 248 | } | ||
| 249 | return -1; | ||
| 250 | } | ||
| 251 | |||
| 252 | void rv515_gpu_init(struct radeon_device *rdev) | ||
| 253 | { | ||
| 254 | unsigned pipe_select_current, gb_pipe_select, tmp; | ||
| 255 | |||
| 256 | r100_hdp_reset(rdev); | ||
| 257 | r100_rb2d_reset(rdev); | ||
| 258 | |||
| 259 | if (r100_gui_wait_for_idle(rdev)) { | ||
| 260 | printk(KERN_WARNING "Failed to wait GUI idle while " | ||
| 261 | "reseting GPU. Bad things might happen.\n"); | ||
| 262 | } | ||
| 263 | |||
| 264 | rs600_disable_vga(rdev); | ||
| 265 | |||
| 266 | r420_pipes_init(rdev); | ||
| 267 | gb_pipe_select = RREG32(0x402C); | ||
| 268 | tmp = RREG32(0x170C); | ||
| 269 | pipe_select_current = (tmp >> 2) & 3; | ||
| 270 | tmp = (1 << pipe_select_current) | | ||
| 271 | (((gb_pipe_select >> 8) & 0xF) << 4); | ||
| 272 | WREG32_PLL(0x000D, tmp); | ||
| 273 | if (r100_gui_wait_for_idle(rdev)) { | ||
| 274 | printk(KERN_WARNING "Failed to wait GUI idle while " | ||
| 275 | "reseting GPU. Bad things might happen.\n"); | ||
| 276 | } | ||
| 277 | if (rv515_mc_wait_for_idle(rdev)) { | ||
| 278 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 279 | "programming pipes. Bad things might happen.\n"); | ||
| 280 | } | ||
| 281 | } | ||
| 282 | |||
| 283 | int rv515_ga_reset(struct radeon_device *rdev) | ||
| 284 | { | ||
| 285 | uint32_t tmp; | ||
| 286 | bool reinit_cp; | ||
| 287 | int i; | ||
| 288 | |||
| 289 | reinit_cp = rdev->cp.ready; | ||
| 290 | rdev->cp.ready = false; | ||
| 291 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 292 | WREG32(RADEON_CP_CSQ_MODE, 0); | ||
| 293 | WREG32(RADEON_CP_CSQ_CNTL, 0); | ||
| 294 | WREG32(RADEON_RBBM_SOFT_RESET, 0x32005); | ||
| 295 | (void)RREG32(RADEON_RBBM_SOFT_RESET); | ||
| 296 | udelay(200); | ||
| 297 | WREG32(RADEON_RBBM_SOFT_RESET, 0); | ||
| 298 | /* Wait to prevent race in RBBM_STATUS */ | ||
| 299 | mdelay(1); | ||
| 300 | tmp = RREG32(RADEON_RBBM_STATUS); | ||
| 301 | if (tmp & ((1 << 20) | (1 << 26))) { | ||
| 302 | DRM_ERROR("VAP & CP still busy (RBBM_STATUS=0x%08X)\n", tmp); | ||
| 303 | /* GA still busy soft reset it */ | ||
| 304 | WREG32(0x429C, 0x200); | ||
| 305 | WREG32(R300_VAP_PVS_STATE_FLUSH_REG, 0); | ||
| 306 | WREG32(0x43E0, 0); | ||
| 307 | WREG32(0x43E4, 0); | ||
| 308 | WREG32(0x24AC, 0); | ||
| 309 | } | ||
| 310 | /* Wait to prevent race in RBBM_STATUS */ | ||
| 311 | mdelay(1); | ||
| 312 | tmp = RREG32(RADEON_RBBM_STATUS); | ||
| 313 | if (!(tmp & ((1 << 20) | (1 << 26)))) { | ||
| 314 | break; | ||
| 315 | } | ||
| 316 | } | ||
| 317 | for (i = 0; i < rdev->usec_timeout; i++) { | ||
| 318 | tmp = RREG32(RADEON_RBBM_STATUS); | ||
| 319 | if (!(tmp & ((1 << 20) | (1 << 26)))) { | ||
| 320 | DRM_INFO("GA reset succeed (RBBM_STATUS=0x%08X)\n", | ||
| 321 | tmp); | ||
| 322 | DRM_INFO("GA_IDLE=0x%08X\n", RREG32(0x425C)); | ||
| 323 | DRM_INFO("RB3D_RESET_STATUS=0x%08X\n", RREG32(0x46f0)); | ||
| 324 | DRM_INFO("ISYNC_CNTL=0x%08X\n", RREG32(0x1724)); | ||
| 325 | if (reinit_cp) { | ||
| 326 | return r100_cp_init(rdev, rdev->cp.ring_size); | ||
| 327 | } | ||
| 328 | return 0; | ||
| 329 | } | ||
| 330 | DRM_UDELAY(1); | ||
| 331 | } | ||
| 332 | tmp = RREG32(RADEON_RBBM_STATUS); | ||
| 333 | DRM_ERROR("Failed to reset GA ! (RBBM_STATUS=0x%08X)\n", tmp); | ||
| 334 | return -1; | ||
| 335 | } | ||
| 336 | |||
| 337 | int rv515_gpu_reset(struct radeon_device *rdev) | ||
| 338 | { | ||
| 339 | uint32_t status; | ||
| 340 | |||
| 341 | /* reset order likely matter */ | ||
| 342 | status = RREG32(RADEON_RBBM_STATUS); | ||
| 343 | /* reset HDP */ | ||
| 344 | r100_hdp_reset(rdev); | ||
| 345 | /* reset rb2d */ | ||
| 346 | if (status & ((1 << 17) | (1 << 18) | (1 << 27))) { | ||
| 347 | r100_rb2d_reset(rdev); | ||
| 348 | } | ||
| 349 | /* reset GA */ | ||
| 350 | if (status & ((1 << 20) | (1 << 26))) { | ||
| 351 | rv515_ga_reset(rdev); | ||
| 352 | } | ||
| 353 | /* reset CP */ | ||
| 354 | status = RREG32(RADEON_RBBM_STATUS); | ||
| 355 | if (status & (1 << 16)) { | ||
| 356 | r100_cp_reset(rdev); | ||
| 357 | } | ||
| 358 | /* Check if GPU is idle */ | ||
| 359 | status = RREG32(RADEON_RBBM_STATUS); | ||
| 360 | if (status & (1 << 31)) { | ||
| 361 | DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status); | ||
| 362 | return -1; | ||
| 363 | } | ||
| 364 | DRM_INFO("GPU reset succeed (RBBM_STATUS=0x%08X)\n", status); | ||
| 365 | return 0; | ||
| 366 | } | ||
| 367 | |||
| 368 | |||
| 369 | /* | ||
| 370 | * VRAM info | ||
| 371 | */ | ||
| 372 | static void rv515_vram_get_type(struct radeon_device *rdev) | ||
| 373 | { | ||
| 374 | uint32_t tmp; | ||
| 375 | |||
| 376 | rdev->mc.vram_width = 128; | ||
| 377 | rdev->mc.vram_is_ddr = true; | ||
| 378 | tmp = RREG32_MC(RV515_MC_CNTL); | ||
| 379 | tmp &= RV515_MEM_NUM_CHANNELS_MASK; | ||
| 380 | switch (tmp) { | ||
| 381 | case 0: | ||
| 382 | rdev->mc.vram_width = 64; | ||
| 383 | break; | ||
| 384 | case 1: | ||
| 385 | rdev->mc.vram_width = 128; | ||
| 386 | break; | ||
| 387 | default: | ||
| 388 | rdev->mc.vram_width = 128; | ||
| 389 | break; | ||
| 390 | } | ||
| 391 | } | ||
| 392 | |||
| 393 | void rv515_vram_info(struct radeon_device *rdev) | ||
| 394 | { | ||
| 395 | rv515_vram_get_type(rdev); | ||
| 396 | rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE); | ||
| 397 | |||
| 398 | rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); | ||
| 399 | rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); | ||
| 400 | } | ||
| 401 | |||
| 402 | |||
| 403 | /* | ||
| 404 | * Indirect registers accessor | ||
| 405 | */ | ||
| 406 | uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg) | ||
| 407 | { | ||
| 408 | uint32_t r; | ||
| 409 | |||
| 410 | WREG32(R520_MC_IND_INDEX, 0x7f0000 | (reg & 0xffff)); | ||
| 411 | r = RREG32(R520_MC_IND_DATA); | ||
| 412 | WREG32(R520_MC_IND_INDEX, 0); | ||
| 413 | return r; | ||
| 414 | } | ||
| 415 | |||
| 416 | void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | ||
| 417 | { | ||
| 418 | WREG32(R520_MC_IND_INDEX, 0xff0000 | ((reg) & 0xffff)); | ||
| 419 | WREG32(R520_MC_IND_DATA, (v)); | ||
| 420 | WREG32(R520_MC_IND_INDEX, 0); | ||
| 421 | } | ||
| 422 | |||
| 423 | uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg) | ||
| 424 | { | ||
| 425 | uint32_t r; | ||
| 426 | |||
| 427 | WREG32(RADEON_PCIE_INDEX, ((reg) & 0x7ff)); | ||
| 428 | (void)RREG32(RADEON_PCIE_INDEX); | ||
| 429 | r = RREG32(RADEON_PCIE_DATA); | ||
| 430 | return r; | ||
| 431 | } | ||
| 432 | |||
| 433 | void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | ||
| 434 | { | ||
| 435 | WREG32(RADEON_PCIE_INDEX, ((reg) & 0x7ff)); | ||
| 436 | (void)RREG32(RADEON_PCIE_INDEX); | ||
| 437 | WREG32(RADEON_PCIE_DATA, (v)); | ||
| 438 | (void)RREG32(RADEON_PCIE_DATA); | ||
| 439 | } | ||
| 440 | |||
| 441 | |||
| 442 | /* | ||
| 443 | * Debugfs info | ||
| 444 | */ | ||
| 445 | #if defined(CONFIG_DEBUG_FS) | ||
| 446 | static int rv515_debugfs_pipes_info(struct seq_file *m, void *data) | ||
| 447 | { | ||
| 448 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
| 449 | struct drm_device *dev = node->minor->dev; | ||
| 450 | struct radeon_device *rdev = dev->dev_private; | ||
| 451 | uint32_t tmp; | ||
| 452 | |||
| 453 | tmp = RREG32(R400_GB_PIPE_SELECT); | ||
| 454 | seq_printf(m, "GB_PIPE_SELECT 0x%08x\n", tmp); | ||
| 455 | tmp = RREG32(R500_SU_REG_DEST); | ||
| 456 | seq_printf(m, "SU_REG_DEST 0x%08x\n", tmp); | ||
| 457 | tmp = RREG32(R300_GB_TILE_CONFIG); | ||
| 458 | seq_printf(m, "GB_TILE_CONFIG 0x%08x\n", tmp); | ||
| 459 | tmp = RREG32(R300_DST_PIPE_CONFIG); | ||
| 460 | seq_printf(m, "DST_PIPE_CONFIG 0x%08x\n", tmp); | ||
| 461 | return 0; | ||
| 462 | } | ||
| 463 | |||
| 464 | static int rv515_debugfs_ga_info(struct seq_file *m, void *data) | ||
| 465 | { | ||
| 466 | struct drm_info_node *node = (struct drm_info_node *) m->private; | ||
| 467 | struct drm_device *dev = node->minor->dev; | ||
| 468 | struct radeon_device *rdev = dev->dev_private; | ||
| 469 | uint32_t tmp; | ||
| 470 | |||
| 471 | tmp = RREG32(0x2140); | ||
| 472 | seq_printf(m, "VAP_CNTL_STATUS 0x%08x\n", tmp); | ||
| 473 | radeon_gpu_reset(rdev); | ||
| 474 | tmp = RREG32(0x425C); | ||
| 475 | seq_printf(m, "GA_IDLE 0x%08x\n", tmp); | ||
| 476 | return 0; | ||
| 477 | } | ||
| 478 | |||
| 479 | static struct drm_info_list rv515_pipes_info_list[] = { | ||
| 480 | {"rv515_pipes_info", rv515_debugfs_pipes_info, 0, NULL}, | ||
| 481 | }; | ||
| 482 | |||
| 483 | static struct drm_info_list rv515_ga_info_list[] = { | ||
| 484 | {"rv515_ga_info", rv515_debugfs_ga_info, 0, NULL}, | ||
| 485 | }; | ||
| 486 | #endif | ||
| 487 | |||
| 488 | int rv515_debugfs_pipes_info_init(struct radeon_device *rdev) | ||
| 489 | { | ||
| 490 | #if defined(CONFIG_DEBUG_FS) | ||
| 491 | return radeon_debugfs_add_files(rdev, rv515_pipes_info_list, 1); | ||
| 492 | #else | ||
| 493 | return 0; | ||
| 494 | #endif | ||
| 495 | } | ||
| 496 | |||
| 497 | int rv515_debugfs_ga_info_init(struct radeon_device *rdev) | ||
| 498 | { | ||
| 499 | #if defined(CONFIG_DEBUG_FS) | ||
| 500 | return radeon_debugfs_add_files(rdev, rv515_ga_info_list, 1); | ||
| 501 | #else | ||
| 502 | return 0; | ||
| 503 | #endif | ||
| 504 | } | ||
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c new file mode 100644 index 000000000000..da50cc51ede3 --- /dev/null +++ b/drivers/gpu/drm/radeon/rv770.c | |||
| @@ -0,0 +1,124 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2008 Advanced Micro Devices, Inc. | ||
| 3 | * Copyright 2008 Red Hat Inc. | ||
| 4 | * Copyright 2009 Jerome Glisse. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice shall be included in | ||
| 14 | * all copies or substantial portions of the Software. | ||
| 15 | * | ||
| 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 19 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 22 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 23 | * | ||
| 24 | * Authors: Dave Airlie | ||
| 25 | * Alex Deucher | ||
| 26 | * Jerome Glisse | ||
| 27 | */ | ||
| 28 | #include "drmP.h" | ||
| 29 | #include "radeon_reg.h" | ||
| 30 | #include "radeon.h" | ||
| 31 | |||
| 32 | /* rv770,rv730,rv710 depends on : */ | ||
| 33 | void rs600_mc_disable_clients(struct radeon_device *rdev); | ||
| 34 | |||
| 35 | /* This files gather functions specifics to: | ||
| 36 | * rv770,rv730,rv710 | ||
| 37 | * | ||
| 38 | * Some of these functions might be used by newer ASICs. | ||
| 39 | */ | ||
| 40 | int rv770_mc_wait_for_idle(struct radeon_device *rdev); | ||
| 41 | void rv770_gpu_init(struct radeon_device *rdev); | ||
| 42 | |||
| 43 | |||
| 44 | /* | ||
| 45 | * MC | ||
| 46 | */ | ||
| 47 | int rv770_mc_init(struct radeon_device *rdev) | ||
| 48 | { | ||
| 49 | uint32_t tmp; | ||
| 50 | |||
| 51 | rv770_gpu_init(rdev); | ||
| 52 | |||
| 53 | /* setup the gart before changing location so we can ask to | ||
| 54 | * discard unmapped mc request | ||
| 55 | */ | ||
| 56 | /* FIXME: disable out of gart access */ | ||
| 57 | tmp = rdev->mc.gtt_location / 4096; | ||
| 58 | tmp = REG_SET(R700_LOGICAL_PAGE_NUMBER, tmp); | ||
| 59 | WREG32(R700_MC_VM_SYSTEM_APERTURE_LOW_ADDR, tmp); | ||
| 60 | tmp = (rdev->mc.gtt_location + rdev->mc.gtt_size) / 4096; | ||
| 61 | tmp = REG_SET(R700_LOGICAL_PAGE_NUMBER, tmp); | ||
| 62 | WREG32(R700_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, tmp); | ||
| 63 | |||
| 64 | rs600_mc_disable_clients(rdev); | ||
| 65 | if (rv770_mc_wait_for_idle(rdev)) { | ||
| 66 | printk(KERN_WARNING "Failed to wait MC idle while " | ||
| 67 | "programming pipes. Bad things might happen.\n"); | ||
| 68 | } | ||
| 69 | |||
| 70 | tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; | ||
| 71 | tmp = REG_SET(R700_MC_FB_TOP, tmp >> 24); | ||
| 72 | tmp |= REG_SET(R700_MC_FB_BASE, rdev->mc.vram_location >> 24); | ||
| 73 | WREG32(R700_MC_VM_FB_LOCATION, tmp); | ||
| 74 | tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; | ||
| 75 | tmp = REG_SET(R700_MC_AGP_TOP, tmp >> 22); | ||
| 76 | WREG32(R700_MC_VM_AGP_TOP, tmp); | ||
| 77 | tmp = REG_SET(R700_MC_AGP_BOT, rdev->mc.gtt_location >> 22); | ||
| 78 | WREG32(R700_MC_VM_AGP_BOT, tmp); | ||
| 79 | return 0; | ||
| 80 | } | ||
| 81 | |||
| 82 | void rv770_mc_fini(struct radeon_device *rdev) | ||
| 83 | { | ||
| 84 | /* FIXME: implement */ | ||
| 85 | } | ||
| 86 | |||
| 87 | |||
| 88 | /* | ||
| 89 | * Global GPU functions | ||
| 90 | */ | ||
| 91 | void rv770_errata(struct radeon_device *rdev) | ||
| 92 | { | ||
| 93 | rdev->pll_errata = 0; | ||
| 94 | } | ||
| 95 | |||
| 96 | int rv770_mc_wait_for_idle(struct radeon_device *rdev) | ||
| 97 | { | ||
| 98 | /* FIXME: implement */ | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | void rv770_gpu_init(struct radeon_device *rdev) | ||
| 103 | { | ||
| 104 | /* FIXME: implement */ | ||
| 105 | } | ||
| 106 | |||
| 107 | |||
| 108 | /* | ||
| 109 | * VRAM info | ||
| 110 | */ | ||
| 111 | void rv770_vram_get_type(struct radeon_device *rdev) | ||
| 112 | { | ||
| 113 | /* FIXME: implement */ | ||
| 114 | } | ||
| 115 | |||
| 116 | void rv770_vram_info(struct radeon_device *rdev) | ||
| 117 | { | ||
| 118 | rv770_vram_get_type(rdev); | ||
| 119 | |||
| 120 | /* FIXME: implement */ | ||
| 121 | /* Could aper size report 0 ? */ | ||
| 122 | rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); | ||
| 123 | rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); | ||
| 124 | } | ||
diff --git a/drivers/gpu/drm/ttm/Makefile b/drivers/gpu/drm/ttm/Makefile new file mode 100644 index 000000000000..b0a9de7a57c2 --- /dev/null +++ b/drivers/gpu/drm/ttm/Makefile | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | # | ||
| 2 | # Makefile for the drm device driver. This driver provides support for the | ||
| 3 | |||
| 4 | ccflags-y := -Iinclude/drm | ||
| 5 | ttm-y := ttm_agp_backend.o ttm_memory.o ttm_tt.o ttm_bo.o \ | ||
| 6 | ttm_bo_util.o ttm_bo_vm.o ttm_module.o ttm_global.o | ||
| 7 | |||
| 8 | obj-$(CONFIG_DRM_TTM) += ttm.o | ||
diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c new file mode 100644 index 000000000000..e8f6d2229d8c --- /dev/null +++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c | |||
| @@ -0,0 +1,150 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | **************************************************************************/ | ||
| 27 | /* | ||
| 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | ||
| 29 | * Keith Packard. | ||
| 30 | */ | ||
| 31 | |||
| 32 | #include "ttm/ttm_module.h" | ||
| 33 | #include "ttm/ttm_bo_driver.h" | ||
| 34 | #ifdef TTM_HAS_AGP | ||
| 35 | #include "ttm/ttm_placement.h" | ||
| 36 | #include <linux/agp_backend.h> | ||
| 37 | #include <linux/module.h> | ||
| 38 | #include <linux/io.h> | ||
| 39 | #include <asm/agp.h> | ||
| 40 | |||
| 41 | struct ttm_agp_backend { | ||
| 42 | struct ttm_backend backend; | ||
| 43 | struct agp_memory *mem; | ||
| 44 | struct agp_bridge_data *bridge; | ||
| 45 | }; | ||
| 46 | |||
| 47 | static int ttm_agp_populate(struct ttm_backend *backend, | ||
| 48 | unsigned long num_pages, struct page **pages, | ||
| 49 | struct page *dummy_read_page) | ||
| 50 | { | ||
| 51 | struct ttm_agp_backend *agp_be = | ||
| 52 | container_of(backend, struct ttm_agp_backend, backend); | ||
| 53 | struct page **cur_page, **last_page = pages + num_pages; | ||
| 54 | struct agp_memory *mem; | ||
| 55 | |||
| 56 | mem = agp_allocate_memory(agp_be->bridge, num_pages, AGP_USER_MEMORY); | ||
| 57 | if (unlikely(mem == NULL)) | ||
| 58 | return -ENOMEM; | ||
| 59 | |||
| 60 | mem->page_count = 0; | ||
| 61 | for (cur_page = pages; cur_page < last_page; ++cur_page) { | ||
| 62 | struct page *page = *cur_page; | ||
| 63 | if (!page) | ||
| 64 | page = dummy_read_page; | ||
| 65 | |||
| 66 | mem->memory[mem->page_count++] = | ||
| 67 | phys_to_gart(page_to_phys(page)); | ||
| 68 | } | ||
| 69 | agp_be->mem = mem; | ||
| 70 | return 0; | ||
| 71 | } | ||
| 72 | |||
| 73 | static int ttm_agp_bind(struct ttm_backend *backend, struct ttm_mem_reg *bo_mem) | ||
| 74 | { | ||
| 75 | struct ttm_agp_backend *agp_be = | ||
| 76 | container_of(backend, struct ttm_agp_backend, backend); | ||
| 77 | struct agp_memory *mem = agp_be->mem; | ||
| 78 | int cached = (bo_mem->placement & TTM_PL_FLAG_CACHED); | ||
| 79 | int ret; | ||
| 80 | |||
| 81 | mem->is_flushed = 1; | ||
| 82 | mem->type = (cached) ? AGP_USER_CACHED_MEMORY : AGP_USER_MEMORY; | ||
| 83 | |||
| 84 | ret = agp_bind_memory(mem, bo_mem->mm_node->start); | ||
| 85 | if (ret) | ||
| 86 | printk(KERN_ERR TTM_PFX "AGP Bind memory failed.\n"); | ||
| 87 | |||
| 88 | return ret; | ||
| 89 | } | ||
| 90 | |||
| 91 | static int ttm_agp_unbind(struct ttm_backend *backend) | ||
| 92 | { | ||
| 93 | struct ttm_agp_backend *agp_be = | ||
| 94 | container_of(backend, struct ttm_agp_backend, backend); | ||
| 95 | |||
| 96 | if (agp_be->mem->is_bound) | ||
| 97 | return agp_unbind_memory(agp_be->mem); | ||
| 98 | else | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | static void ttm_agp_clear(struct ttm_backend *backend) | ||
| 103 | { | ||
| 104 | struct ttm_agp_backend *agp_be = | ||
| 105 | container_of(backend, struct ttm_agp_backend, backend); | ||
| 106 | struct agp_memory *mem = agp_be->mem; | ||
| 107 | |||
| 108 | if (mem) { | ||
| 109 | ttm_agp_unbind(backend); | ||
| 110 | agp_free_memory(mem); | ||
| 111 | } | ||
| 112 | agp_be->mem = NULL; | ||
| 113 | } | ||
| 114 | |||
| 115 | static void ttm_agp_destroy(struct ttm_backend *backend) | ||
| 116 | { | ||
| 117 | struct ttm_agp_backend *agp_be = | ||
| 118 | container_of(backend, struct ttm_agp_backend, backend); | ||
| 119 | |||
| 120 | if (agp_be->mem) | ||
| 121 | ttm_agp_clear(backend); | ||
| 122 | kfree(agp_be); | ||
| 123 | } | ||
| 124 | |||
| 125 | static struct ttm_backend_func ttm_agp_func = { | ||
| 126 | .populate = ttm_agp_populate, | ||
| 127 | .clear = ttm_agp_clear, | ||
| 128 | .bind = ttm_agp_bind, | ||
| 129 | .unbind = ttm_agp_unbind, | ||
| 130 | .destroy = ttm_agp_destroy, | ||
| 131 | }; | ||
| 132 | |||
| 133 | struct ttm_backend *ttm_agp_backend_init(struct ttm_bo_device *bdev, | ||
| 134 | struct agp_bridge_data *bridge) | ||
| 135 | { | ||
| 136 | struct ttm_agp_backend *agp_be; | ||
| 137 | |||
| 138 | agp_be = kmalloc(sizeof(*agp_be), GFP_KERNEL); | ||
| 139 | if (!agp_be) | ||
| 140 | return NULL; | ||
| 141 | |||
| 142 | agp_be->mem = NULL; | ||
| 143 | agp_be->bridge = bridge; | ||
| 144 | agp_be->backend.func = &ttm_agp_func; | ||
| 145 | agp_be->backend.bdev = bdev; | ||
| 146 | return &agp_be->backend; | ||
| 147 | } | ||
| 148 | EXPORT_SYMBOL(ttm_agp_backend_init); | ||
| 149 | |||
| 150 | #endif | ||
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c new file mode 100644 index 000000000000..1587aeca7bea --- /dev/null +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
| @@ -0,0 +1,1698 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | **************************************************************************/ | ||
| 27 | /* | ||
| 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include "ttm/ttm_module.h" | ||
| 32 | #include "ttm/ttm_bo_driver.h" | ||
| 33 | #include "ttm/ttm_placement.h" | ||
| 34 | #include <linux/jiffies.h> | ||
| 35 | #include <linux/slab.h> | ||
| 36 | #include <linux/sched.h> | ||
| 37 | #include <linux/mm.h> | ||
| 38 | #include <linux/file.h> | ||
| 39 | #include <linux/module.h> | ||
| 40 | |||
| 41 | #define TTM_ASSERT_LOCKED(param) | ||
| 42 | #define TTM_DEBUG(fmt, arg...) | ||
| 43 | #define TTM_BO_HASH_ORDER 13 | ||
| 44 | |||
| 45 | static int ttm_bo_setup_vm(struct ttm_buffer_object *bo); | ||
| 46 | static void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo); | ||
| 47 | static int ttm_bo_swapout(struct ttm_mem_shrink *shrink); | ||
| 48 | |||
| 49 | static inline uint32_t ttm_bo_type_flags(unsigned type) | ||
| 50 | { | ||
| 51 | return 1 << (type); | ||
| 52 | } | ||
| 53 | |||
| 54 | static void ttm_bo_release_list(struct kref *list_kref) | ||
| 55 | { | ||
| 56 | struct ttm_buffer_object *bo = | ||
| 57 | container_of(list_kref, struct ttm_buffer_object, list_kref); | ||
| 58 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 59 | |||
| 60 | BUG_ON(atomic_read(&bo->list_kref.refcount)); | ||
| 61 | BUG_ON(atomic_read(&bo->kref.refcount)); | ||
| 62 | BUG_ON(atomic_read(&bo->cpu_writers)); | ||
| 63 | BUG_ON(bo->sync_obj != NULL); | ||
| 64 | BUG_ON(bo->mem.mm_node != NULL); | ||
| 65 | BUG_ON(!list_empty(&bo->lru)); | ||
| 66 | BUG_ON(!list_empty(&bo->ddestroy)); | ||
| 67 | |||
| 68 | if (bo->ttm) | ||
| 69 | ttm_tt_destroy(bo->ttm); | ||
| 70 | if (bo->destroy) | ||
| 71 | bo->destroy(bo); | ||
| 72 | else { | ||
| 73 | ttm_mem_global_free(bdev->mem_glob, bo->acc_size, false); | ||
| 74 | kfree(bo); | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo, bool interruptible) | ||
| 79 | { | ||
| 80 | |||
| 81 | if (interruptible) { | ||
| 82 | int ret = 0; | ||
| 83 | |||
| 84 | ret = wait_event_interruptible(bo->event_queue, | ||
| 85 | atomic_read(&bo->reserved) == 0); | ||
| 86 | if (unlikely(ret != 0)) | ||
| 87 | return -ERESTART; | ||
| 88 | } else { | ||
| 89 | wait_event(bo->event_queue, atomic_read(&bo->reserved) == 0); | ||
| 90 | } | ||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | static void ttm_bo_add_to_lru(struct ttm_buffer_object *bo) | ||
| 95 | { | ||
| 96 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 97 | struct ttm_mem_type_manager *man; | ||
| 98 | |||
| 99 | BUG_ON(!atomic_read(&bo->reserved)); | ||
| 100 | |||
| 101 | if (!(bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) { | ||
| 102 | |||
| 103 | BUG_ON(!list_empty(&bo->lru)); | ||
| 104 | |||
| 105 | man = &bdev->man[bo->mem.mem_type]; | ||
| 106 | list_add_tail(&bo->lru, &man->lru); | ||
| 107 | kref_get(&bo->list_kref); | ||
| 108 | |||
| 109 | if (bo->ttm != NULL) { | ||
| 110 | list_add_tail(&bo->swap, &bdev->swap_lru); | ||
| 111 | kref_get(&bo->list_kref); | ||
| 112 | } | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | /** | ||
| 117 | * Call with the lru_lock held. | ||
| 118 | */ | ||
| 119 | |||
| 120 | static int ttm_bo_del_from_lru(struct ttm_buffer_object *bo) | ||
| 121 | { | ||
| 122 | int put_count = 0; | ||
| 123 | |||
| 124 | if (!list_empty(&bo->swap)) { | ||
| 125 | list_del_init(&bo->swap); | ||
| 126 | ++put_count; | ||
| 127 | } | ||
| 128 | if (!list_empty(&bo->lru)) { | ||
| 129 | list_del_init(&bo->lru); | ||
| 130 | ++put_count; | ||
| 131 | } | ||
| 132 | |||
| 133 | /* | ||
| 134 | * TODO: Add a driver hook to delete from | ||
| 135 | * driver-specific LRU's here. | ||
| 136 | */ | ||
| 137 | |||
| 138 | return put_count; | ||
| 139 | } | ||
| 140 | |||
| 141 | int ttm_bo_reserve_locked(struct ttm_buffer_object *bo, | ||
| 142 | bool interruptible, | ||
| 143 | bool no_wait, bool use_sequence, uint32_t sequence) | ||
| 144 | { | ||
| 145 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 146 | int ret; | ||
| 147 | |||
| 148 | while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) { | ||
| 149 | if (use_sequence && bo->seq_valid && | ||
| 150 | (sequence - bo->val_seq < (1 << 31))) { | ||
| 151 | return -EAGAIN; | ||
| 152 | } | ||
| 153 | |||
| 154 | if (no_wait) | ||
| 155 | return -EBUSY; | ||
| 156 | |||
| 157 | spin_unlock(&bdev->lru_lock); | ||
| 158 | ret = ttm_bo_wait_unreserved(bo, interruptible); | ||
| 159 | spin_lock(&bdev->lru_lock); | ||
| 160 | |||
| 161 | if (unlikely(ret)) | ||
| 162 | return ret; | ||
| 163 | } | ||
| 164 | |||
| 165 | if (use_sequence) { | ||
| 166 | bo->val_seq = sequence; | ||
| 167 | bo->seq_valid = true; | ||
| 168 | } else { | ||
| 169 | bo->seq_valid = false; | ||
| 170 | } | ||
| 171 | |||
| 172 | return 0; | ||
| 173 | } | ||
| 174 | EXPORT_SYMBOL(ttm_bo_reserve); | ||
| 175 | |||
| 176 | static void ttm_bo_ref_bug(struct kref *list_kref) | ||
| 177 | { | ||
| 178 | BUG(); | ||
| 179 | } | ||
| 180 | |||
| 181 | int ttm_bo_reserve(struct ttm_buffer_object *bo, | ||
| 182 | bool interruptible, | ||
| 183 | bool no_wait, bool use_sequence, uint32_t sequence) | ||
| 184 | { | ||
| 185 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 186 | int put_count = 0; | ||
| 187 | int ret; | ||
| 188 | |||
| 189 | spin_lock(&bdev->lru_lock); | ||
| 190 | ret = ttm_bo_reserve_locked(bo, interruptible, no_wait, use_sequence, | ||
| 191 | sequence); | ||
| 192 | if (likely(ret == 0)) | ||
| 193 | put_count = ttm_bo_del_from_lru(bo); | ||
| 194 | spin_unlock(&bdev->lru_lock); | ||
| 195 | |||
| 196 | while (put_count--) | ||
| 197 | kref_put(&bo->list_kref, ttm_bo_ref_bug); | ||
| 198 | |||
| 199 | return ret; | ||
| 200 | } | ||
| 201 | |||
| 202 | void ttm_bo_unreserve(struct ttm_buffer_object *bo) | ||
| 203 | { | ||
| 204 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 205 | |||
| 206 | spin_lock(&bdev->lru_lock); | ||
| 207 | ttm_bo_add_to_lru(bo); | ||
| 208 | atomic_set(&bo->reserved, 0); | ||
| 209 | wake_up_all(&bo->event_queue); | ||
| 210 | spin_unlock(&bdev->lru_lock); | ||
| 211 | } | ||
| 212 | EXPORT_SYMBOL(ttm_bo_unreserve); | ||
| 213 | |||
| 214 | /* | ||
| 215 | * Call bo->mutex locked. | ||
| 216 | */ | ||
| 217 | |||
| 218 | static int ttm_bo_add_ttm(struct ttm_buffer_object *bo, bool zero_alloc) | ||
| 219 | { | ||
| 220 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 221 | int ret = 0; | ||
| 222 | uint32_t page_flags = 0; | ||
| 223 | |||
| 224 | TTM_ASSERT_LOCKED(&bo->mutex); | ||
| 225 | bo->ttm = NULL; | ||
| 226 | |||
| 227 | switch (bo->type) { | ||
| 228 | case ttm_bo_type_device: | ||
| 229 | if (zero_alloc) | ||
| 230 | page_flags |= TTM_PAGE_FLAG_ZERO_ALLOC; | ||
| 231 | case ttm_bo_type_kernel: | ||
| 232 | bo->ttm = ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT, | ||
| 233 | page_flags, bdev->dummy_read_page); | ||
| 234 | if (unlikely(bo->ttm == NULL)) | ||
| 235 | ret = -ENOMEM; | ||
| 236 | break; | ||
| 237 | case ttm_bo_type_user: | ||
| 238 | bo->ttm = ttm_tt_create(bdev, bo->num_pages << PAGE_SHIFT, | ||
| 239 | page_flags | TTM_PAGE_FLAG_USER, | ||
| 240 | bdev->dummy_read_page); | ||
| 241 | if (unlikely(bo->ttm == NULL)) | ||
| 242 | ret = -ENOMEM; | ||
| 243 | break; | ||
| 244 | |||
| 245 | ret = ttm_tt_set_user(bo->ttm, current, | ||
| 246 | bo->buffer_start, bo->num_pages); | ||
| 247 | if (unlikely(ret != 0)) | ||
| 248 | ttm_tt_destroy(bo->ttm); | ||
| 249 | break; | ||
| 250 | default: | ||
| 251 | printk(KERN_ERR TTM_PFX "Illegal buffer object type\n"); | ||
| 252 | ret = -EINVAL; | ||
| 253 | break; | ||
| 254 | } | ||
| 255 | |||
| 256 | return ret; | ||
| 257 | } | ||
| 258 | |||
| 259 | static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, | ||
| 260 | struct ttm_mem_reg *mem, | ||
| 261 | bool evict, bool interruptible, bool no_wait) | ||
| 262 | { | ||
| 263 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 264 | bool old_is_pci = ttm_mem_reg_is_pci(bdev, &bo->mem); | ||
| 265 | bool new_is_pci = ttm_mem_reg_is_pci(bdev, mem); | ||
| 266 | struct ttm_mem_type_manager *old_man = &bdev->man[bo->mem.mem_type]; | ||
| 267 | struct ttm_mem_type_manager *new_man = &bdev->man[mem->mem_type]; | ||
| 268 | int ret = 0; | ||
| 269 | |||
| 270 | if (old_is_pci || new_is_pci || | ||
| 271 | ((mem->placement & bo->mem.placement & TTM_PL_MASK_CACHING) == 0)) | ||
| 272 | ttm_bo_unmap_virtual(bo); | ||
| 273 | |||
| 274 | /* | ||
| 275 | * Create and bind a ttm if required. | ||
| 276 | */ | ||
| 277 | |||
| 278 | if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED) && (bo->ttm == NULL)) { | ||
| 279 | ret = ttm_bo_add_ttm(bo, false); | ||
| 280 | if (ret) | ||
| 281 | goto out_err; | ||
| 282 | |||
| 283 | ret = ttm_tt_set_placement_caching(bo->ttm, mem->placement); | ||
| 284 | if (ret) | ||
| 285 | return ret; | ||
| 286 | |||
| 287 | if (mem->mem_type != TTM_PL_SYSTEM) { | ||
| 288 | ret = ttm_tt_bind(bo->ttm, mem); | ||
| 289 | if (ret) | ||
| 290 | goto out_err; | ||
| 291 | } | ||
| 292 | |||
| 293 | if (bo->mem.mem_type == TTM_PL_SYSTEM) { | ||
| 294 | |||
| 295 | struct ttm_mem_reg *old_mem = &bo->mem; | ||
| 296 | uint32_t save_flags = old_mem->placement; | ||
| 297 | |||
| 298 | *old_mem = *mem; | ||
| 299 | mem->mm_node = NULL; | ||
| 300 | ttm_flag_masked(&save_flags, mem->placement, | ||
| 301 | TTM_PL_MASK_MEMTYPE); | ||
| 302 | goto moved; | ||
| 303 | } | ||
| 304 | |||
| 305 | } | ||
| 306 | |||
| 307 | if (!(old_man->flags & TTM_MEMTYPE_FLAG_FIXED) && | ||
| 308 | !(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) | ||
| 309 | ret = ttm_bo_move_ttm(bo, evict, no_wait, mem); | ||
| 310 | else if (bdev->driver->move) | ||
| 311 | ret = bdev->driver->move(bo, evict, interruptible, | ||
| 312 | no_wait, mem); | ||
| 313 | else | ||
| 314 | ret = ttm_bo_move_memcpy(bo, evict, no_wait, mem); | ||
| 315 | |||
| 316 | if (ret) | ||
| 317 | goto out_err; | ||
| 318 | |||
| 319 | moved: | ||
| 320 | if (bo->evicted) { | ||
| 321 | ret = bdev->driver->invalidate_caches(bdev, bo->mem.placement); | ||
| 322 | if (ret) | ||
| 323 | printk(KERN_ERR TTM_PFX "Can not flush read caches\n"); | ||
| 324 | bo->evicted = false; | ||
| 325 | } | ||
| 326 | |||
| 327 | if (bo->mem.mm_node) { | ||
| 328 | spin_lock(&bo->lock); | ||
| 329 | bo->offset = (bo->mem.mm_node->start << PAGE_SHIFT) + | ||
| 330 | bdev->man[bo->mem.mem_type].gpu_offset; | ||
| 331 | bo->cur_placement = bo->mem.placement; | ||
| 332 | spin_unlock(&bo->lock); | ||
| 333 | } | ||
| 334 | |||
| 335 | return 0; | ||
| 336 | |||
| 337 | out_err: | ||
| 338 | new_man = &bdev->man[bo->mem.mem_type]; | ||
| 339 | if ((new_man->flags & TTM_MEMTYPE_FLAG_FIXED) && bo->ttm) { | ||
| 340 | ttm_tt_unbind(bo->ttm); | ||
| 341 | ttm_tt_destroy(bo->ttm); | ||
| 342 | bo->ttm = NULL; | ||
| 343 | } | ||
| 344 | |||
| 345 | return ret; | ||
| 346 | } | ||
| 347 | |||
| 348 | /** | ||
| 349 | * If bo idle, remove from delayed- and lru lists, and unref. | ||
| 350 | * If not idle, and already on delayed list, do nothing. | ||
| 351 | * If not idle, and not on delayed list, put on delayed list, | ||
| 352 | * up the list_kref and schedule a delayed list check. | ||
| 353 | */ | ||
| 354 | |||
| 355 | static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all) | ||
| 356 | { | ||
| 357 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 358 | struct ttm_bo_driver *driver = bdev->driver; | ||
| 359 | int ret; | ||
| 360 | |||
| 361 | spin_lock(&bo->lock); | ||
| 362 | (void) ttm_bo_wait(bo, false, false, !remove_all); | ||
| 363 | |||
| 364 | if (!bo->sync_obj) { | ||
| 365 | int put_count; | ||
| 366 | |||
| 367 | spin_unlock(&bo->lock); | ||
| 368 | |||
| 369 | spin_lock(&bdev->lru_lock); | ||
| 370 | ret = ttm_bo_reserve_locked(bo, false, false, false, 0); | ||
| 371 | BUG_ON(ret); | ||
| 372 | if (bo->ttm) | ||
| 373 | ttm_tt_unbind(bo->ttm); | ||
| 374 | |||
| 375 | if (!list_empty(&bo->ddestroy)) { | ||
| 376 | list_del_init(&bo->ddestroy); | ||
| 377 | kref_put(&bo->list_kref, ttm_bo_ref_bug); | ||
| 378 | } | ||
| 379 | if (bo->mem.mm_node) { | ||
| 380 | drm_mm_put_block(bo->mem.mm_node); | ||
| 381 | bo->mem.mm_node = NULL; | ||
| 382 | } | ||
| 383 | put_count = ttm_bo_del_from_lru(bo); | ||
| 384 | spin_unlock(&bdev->lru_lock); | ||
| 385 | |||
| 386 | atomic_set(&bo->reserved, 0); | ||
| 387 | |||
| 388 | while (put_count--) | ||
| 389 | kref_put(&bo->list_kref, ttm_bo_release_list); | ||
| 390 | |||
| 391 | return 0; | ||
| 392 | } | ||
| 393 | |||
| 394 | spin_lock(&bdev->lru_lock); | ||
| 395 | if (list_empty(&bo->ddestroy)) { | ||
| 396 | void *sync_obj = bo->sync_obj; | ||
| 397 | void *sync_obj_arg = bo->sync_obj_arg; | ||
| 398 | |||
| 399 | kref_get(&bo->list_kref); | ||
| 400 | list_add_tail(&bo->ddestroy, &bdev->ddestroy); | ||
| 401 | spin_unlock(&bdev->lru_lock); | ||
| 402 | spin_unlock(&bo->lock); | ||
| 403 | |||
| 404 | if (sync_obj) | ||
| 405 | driver->sync_obj_flush(sync_obj, sync_obj_arg); | ||
| 406 | schedule_delayed_work(&bdev->wq, | ||
| 407 | ((HZ / 100) < 1) ? 1 : HZ / 100); | ||
| 408 | ret = 0; | ||
| 409 | |||
| 410 | } else { | ||
| 411 | spin_unlock(&bdev->lru_lock); | ||
| 412 | spin_unlock(&bo->lock); | ||
| 413 | ret = -EBUSY; | ||
| 414 | } | ||
| 415 | |||
| 416 | return ret; | ||
| 417 | } | ||
| 418 | |||
| 419 | /** | ||
| 420 | * Traverse the delayed list, and call ttm_bo_cleanup_refs on all | ||
| 421 | * encountered buffers. | ||
| 422 | */ | ||
| 423 | |||
| 424 | static int ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all) | ||
| 425 | { | ||
| 426 | struct ttm_buffer_object *entry, *nentry; | ||
| 427 | struct list_head *list, *next; | ||
| 428 | int ret; | ||
| 429 | |||
| 430 | spin_lock(&bdev->lru_lock); | ||
| 431 | list_for_each_safe(list, next, &bdev->ddestroy) { | ||
| 432 | entry = list_entry(list, struct ttm_buffer_object, ddestroy); | ||
| 433 | nentry = NULL; | ||
| 434 | |||
| 435 | /* | ||
| 436 | * Protect the next list entry from destruction while we | ||
| 437 | * unlock the lru_lock. | ||
| 438 | */ | ||
| 439 | |||
| 440 | if (next != &bdev->ddestroy) { | ||
| 441 | nentry = list_entry(next, struct ttm_buffer_object, | ||
| 442 | ddestroy); | ||
| 443 | kref_get(&nentry->list_kref); | ||
| 444 | } | ||
| 445 | kref_get(&entry->list_kref); | ||
| 446 | |||
| 447 | spin_unlock(&bdev->lru_lock); | ||
| 448 | ret = ttm_bo_cleanup_refs(entry, remove_all); | ||
| 449 | kref_put(&entry->list_kref, ttm_bo_release_list); | ||
| 450 | |||
| 451 | spin_lock(&bdev->lru_lock); | ||
| 452 | if (nentry) { | ||
| 453 | bool next_onlist = !list_empty(next); | ||
| 454 | spin_unlock(&bdev->lru_lock); | ||
| 455 | kref_put(&nentry->list_kref, ttm_bo_release_list); | ||
| 456 | spin_lock(&bdev->lru_lock); | ||
| 457 | /* | ||
| 458 | * Someone might have raced us and removed the | ||
| 459 | * next entry from the list. We don't bother restarting | ||
| 460 | * list traversal. | ||
| 461 | */ | ||
| 462 | |||
| 463 | if (!next_onlist) | ||
| 464 | break; | ||
| 465 | } | ||
| 466 | if (ret) | ||
| 467 | break; | ||
| 468 | } | ||
| 469 | ret = !list_empty(&bdev->ddestroy); | ||
| 470 | spin_unlock(&bdev->lru_lock); | ||
| 471 | |||
| 472 | return ret; | ||
| 473 | } | ||
| 474 | |||
| 475 | static void ttm_bo_delayed_workqueue(struct work_struct *work) | ||
| 476 | { | ||
| 477 | struct ttm_bo_device *bdev = | ||
| 478 | container_of(work, struct ttm_bo_device, wq.work); | ||
| 479 | |||
| 480 | if (ttm_bo_delayed_delete(bdev, false)) { | ||
| 481 | schedule_delayed_work(&bdev->wq, | ||
| 482 | ((HZ / 100) < 1) ? 1 : HZ / 100); | ||
| 483 | } | ||
| 484 | } | ||
| 485 | |||
| 486 | static void ttm_bo_release(struct kref *kref) | ||
| 487 | { | ||
| 488 | struct ttm_buffer_object *bo = | ||
| 489 | container_of(kref, struct ttm_buffer_object, kref); | ||
| 490 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 491 | |||
| 492 | if (likely(bo->vm_node != NULL)) { | ||
| 493 | rb_erase(&bo->vm_rb, &bdev->addr_space_rb); | ||
| 494 | drm_mm_put_block(bo->vm_node); | ||
| 495 | bo->vm_node = NULL; | ||
| 496 | } | ||
| 497 | write_unlock(&bdev->vm_lock); | ||
| 498 | ttm_bo_cleanup_refs(bo, false); | ||
| 499 | kref_put(&bo->list_kref, ttm_bo_release_list); | ||
| 500 | write_lock(&bdev->vm_lock); | ||
| 501 | } | ||
| 502 | |||
| 503 | void ttm_bo_unref(struct ttm_buffer_object **p_bo) | ||
| 504 | { | ||
| 505 | struct ttm_buffer_object *bo = *p_bo; | ||
| 506 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 507 | |||
| 508 | *p_bo = NULL; | ||
| 509 | write_lock(&bdev->vm_lock); | ||
| 510 | kref_put(&bo->kref, ttm_bo_release); | ||
| 511 | write_unlock(&bdev->vm_lock); | ||
| 512 | } | ||
| 513 | EXPORT_SYMBOL(ttm_bo_unref); | ||
| 514 | |||
| 515 | static int ttm_bo_evict(struct ttm_buffer_object *bo, unsigned mem_type, | ||
| 516 | bool interruptible, bool no_wait) | ||
| 517 | { | ||
| 518 | int ret = 0; | ||
| 519 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 520 | struct ttm_mem_reg evict_mem; | ||
| 521 | uint32_t proposed_placement; | ||
| 522 | |||
| 523 | if (bo->mem.mem_type != mem_type) | ||
| 524 | goto out; | ||
| 525 | |||
| 526 | spin_lock(&bo->lock); | ||
| 527 | ret = ttm_bo_wait(bo, false, interruptible, no_wait); | ||
| 528 | spin_unlock(&bo->lock); | ||
| 529 | |||
| 530 | if (ret && ret != -ERESTART) { | ||
| 531 | printk(KERN_ERR TTM_PFX "Failed to expire sync object before " | ||
| 532 | "buffer eviction.\n"); | ||
| 533 | goto out; | ||
| 534 | } | ||
| 535 | |||
| 536 | BUG_ON(!atomic_read(&bo->reserved)); | ||
| 537 | |||
| 538 | evict_mem = bo->mem; | ||
| 539 | evict_mem.mm_node = NULL; | ||
| 540 | |||
| 541 | proposed_placement = bdev->driver->evict_flags(bo); | ||
| 542 | |||
| 543 | ret = ttm_bo_mem_space(bo, proposed_placement, | ||
| 544 | &evict_mem, interruptible, no_wait); | ||
| 545 | if (unlikely(ret != 0 && ret != -ERESTART)) | ||
| 546 | ret = ttm_bo_mem_space(bo, TTM_PL_FLAG_SYSTEM, | ||
| 547 | &evict_mem, interruptible, no_wait); | ||
| 548 | |||
| 549 | if (ret) { | ||
| 550 | if (ret != -ERESTART) | ||
| 551 | printk(KERN_ERR TTM_PFX | ||
| 552 | "Failed to find memory space for " | ||
| 553 | "buffer 0x%p eviction.\n", bo); | ||
| 554 | goto out; | ||
| 555 | } | ||
| 556 | |||
| 557 | ret = ttm_bo_handle_move_mem(bo, &evict_mem, true, interruptible, | ||
| 558 | no_wait); | ||
| 559 | if (ret) { | ||
| 560 | if (ret != -ERESTART) | ||
| 561 | printk(KERN_ERR TTM_PFX "Buffer eviction failed\n"); | ||
| 562 | goto out; | ||
| 563 | } | ||
| 564 | |||
| 565 | spin_lock(&bdev->lru_lock); | ||
| 566 | if (evict_mem.mm_node) { | ||
| 567 | drm_mm_put_block(evict_mem.mm_node); | ||
| 568 | evict_mem.mm_node = NULL; | ||
| 569 | } | ||
| 570 | spin_unlock(&bdev->lru_lock); | ||
| 571 | bo->evicted = true; | ||
| 572 | out: | ||
| 573 | return ret; | ||
| 574 | } | ||
| 575 | |||
| 576 | /** | ||
| 577 | * Repeatedly evict memory from the LRU for @mem_type until we create enough | ||
| 578 | * space, or we've evicted everything and there isn't enough space. | ||
| 579 | */ | ||
| 580 | static int ttm_bo_mem_force_space(struct ttm_bo_device *bdev, | ||
| 581 | struct ttm_mem_reg *mem, | ||
| 582 | uint32_t mem_type, | ||
| 583 | bool interruptible, bool no_wait) | ||
| 584 | { | ||
| 585 | struct drm_mm_node *node; | ||
| 586 | struct ttm_buffer_object *entry; | ||
| 587 | struct ttm_mem_type_manager *man = &bdev->man[mem_type]; | ||
| 588 | struct list_head *lru; | ||
| 589 | unsigned long num_pages = mem->num_pages; | ||
| 590 | int put_count = 0; | ||
| 591 | int ret; | ||
| 592 | |||
| 593 | retry_pre_get: | ||
| 594 | ret = drm_mm_pre_get(&man->manager); | ||
| 595 | if (unlikely(ret != 0)) | ||
| 596 | return ret; | ||
| 597 | |||
| 598 | spin_lock(&bdev->lru_lock); | ||
| 599 | do { | ||
| 600 | node = drm_mm_search_free(&man->manager, num_pages, | ||
| 601 | mem->page_alignment, 1); | ||
| 602 | if (node) | ||
| 603 | break; | ||
| 604 | |||
| 605 | lru = &man->lru; | ||
| 606 | if (list_empty(lru)) | ||
| 607 | break; | ||
| 608 | |||
| 609 | entry = list_first_entry(lru, struct ttm_buffer_object, lru); | ||
| 610 | kref_get(&entry->list_kref); | ||
| 611 | |||
| 612 | ret = | ||
| 613 | ttm_bo_reserve_locked(entry, interruptible, no_wait, | ||
| 614 | false, 0); | ||
| 615 | |||
| 616 | if (likely(ret == 0)) | ||
| 617 | put_count = ttm_bo_del_from_lru(entry); | ||
| 618 | |||
| 619 | spin_unlock(&bdev->lru_lock); | ||
| 620 | |||
| 621 | if (unlikely(ret != 0)) | ||
| 622 | return ret; | ||
| 623 | |||
| 624 | while (put_count--) | ||
| 625 | kref_put(&entry->list_kref, ttm_bo_ref_bug); | ||
| 626 | |||
| 627 | ret = ttm_bo_evict(entry, mem_type, interruptible, no_wait); | ||
| 628 | |||
| 629 | ttm_bo_unreserve(entry); | ||
| 630 | |||
| 631 | kref_put(&entry->list_kref, ttm_bo_release_list); | ||
| 632 | if (ret) | ||
| 633 | return ret; | ||
| 634 | |||
| 635 | spin_lock(&bdev->lru_lock); | ||
| 636 | } while (1); | ||
| 637 | |||
| 638 | if (!node) { | ||
| 639 | spin_unlock(&bdev->lru_lock); | ||
| 640 | return -ENOMEM; | ||
| 641 | } | ||
| 642 | |||
| 643 | node = drm_mm_get_block_atomic(node, num_pages, mem->page_alignment); | ||
| 644 | if (unlikely(!node)) { | ||
| 645 | spin_unlock(&bdev->lru_lock); | ||
| 646 | goto retry_pre_get; | ||
| 647 | } | ||
| 648 | |||
| 649 | spin_unlock(&bdev->lru_lock); | ||
| 650 | mem->mm_node = node; | ||
| 651 | mem->mem_type = mem_type; | ||
| 652 | return 0; | ||
| 653 | } | ||
| 654 | |||
| 655 | static bool ttm_bo_mt_compatible(struct ttm_mem_type_manager *man, | ||
| 656 | bool disallow_fixed, | ||
| 657 | uint32_t mem_type, | ||
| 658 | uint32_t mask, uint32_t *res_mask) | ||
| 659 | { | ||
| 660 | uint32_t cur_flags = ttm_bo_type_flags(mem_type); | ||
| 661 | |||
| 662 | if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && disallow_fixed) | ||
| 663 | return false; | ||
| 664 | |||
| 665 | if ((cur_flags & mask & TTM_PL_MASK_MEM) == 0) | ||
| 666 | return false; | ||
| 667 | |||
| 668 | if ((mask & man->available_caching) == 0) | ||
| 669 | return false; | ||
| 670 | if (mask & man->default_caching) | ||
| 671 | cur_flags |= man->default_caching; | ||
| 672 | else if (mask & TTM_PL_FLAG_CACHED) | ||
| 673 | cur_flags |= TTM_PL_FLAG_CACHED; | ||
| 674 | else if (mask & TTM_PL_FLAG_WC) | ||
| 675 | cur_flags |= TTM_PL_FLAG_WC; | ||
| 676 | else | ||
| 677 | cur_flags |= TTM_PL_FLAG_UNCACHED; | ||
| 678 | |||
| 679 | *res_mask = cur_flags; | ||
| 680 | return true; | ||
| 681 | } | ||
| 682 | |||
| 683 | /** | ||
| 684 | * Creates space for memory region @mem according to its type. | ||
| 685 | * | ||
| 686 | * This function first searches for free space in compatible memory types in | ||
| 687 | * the priority order defined by the driver. If free space isn't found, then | ||
| 688 | * ttm_bo_mem_force_space is attempted in priority order to evict and find | ||
| 689 | * space. | ||
| 690 | */ | ||
| 691 | int ttm_bo_mem_space(struct ttm_buffer_object *bo, | ||
| 692 | uint32_t proposed_placement, | ||
| 693 | struct ttm_mem_reg *mem, | ||
| 694 | bool interruptible, bool no_wait) | ||
| 695 | { | ||
| 696 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 697 | struct ttm_mem_type_manager *man; | ||
| 698 | |||
| 699 | uint32_t num_prios = bdev->driver->num_mem_type_prio; | ||
| 700 | const uint32_t *prios = bdev->driver->mem_type_prio; | ||
| 701 | uint32_t i; | ||
| 702 | uint32_t mem_type = TTM_PL_SYSTEM; | ||
| 703 | uint32_t cur_flags = 0; | ||
| 704 | bool type_found = false; | ||
| 705 | bool type_ok = false; | ||
| 706 | bool has_eagain = false; | ||
| 707 | struct drm_mm_node *node = NULL; | ||
| 708 | int ret; | ||
| 709 | |||
| 710 | mem->mm_node = NULL; | ||
| 711 | for (i = 0; i < num_prios; ++i) { | ||
| 712 | mem_type = prios[i]; | ||
| 713 | man = &bdev->man[mem_type]; | ||
| 714 | |||
| 715 | type_ok = ttm_bo_mt_compatible(man, | ||
| 716 | bo->type == ttm_bo_type_user, | ||
| 717 | mem_type, proposed_placement, | ||
| 718 | &cur_flags); | ||
| 719 | |||
| 720 | if (!type_ok) | ||
| 721 | continue; | ||
| 722 | |||
| 723 | if (mem_type == TTM_PL_SYSTEM) | ||
| 724 | break; | ||
| 725 | |||
| 726 | if (man->has_type && man->use_type) { | ||
| 727 | type_found = true; | ||
| 728 | do { | ||
| 729 | ret = drm_mm_pre_get(&man->manager); | ||
| 730 | if (unlikely(ret)) | ||
| 731 | return ret; | ||
| 732 | |||
| 733 | spin_lock(&bdev->lru_lock); | ||
| 734 | node = drm_mm_search_free(&man->manager, | ||
| 735 | mem->num_pages, | ||
| 736 | mem->page_alignment, | ||
| 737 | 1); | ||
| 738 | if (unlikely(!node)) { | ||
| 739 | spin_unlock(&bdev->lru_lock); | ||
| 740 | break; | ||
| 741 | } | ||
| 742 | node = drm_mm_get_block_atomic(node, | ||
| 743 | mem->num_pages, | ||
| 744 | mem-> | ||
| 745 | page_alignment); | ||
| 746 | spin_unlock(&bdev->lru_lock); | ||
| 747 | } while (!node); | ||
| 748 | } | ||
| 749 | if (node) | ||
| 750 | break; | ||
| 751 | } | ||
| 752 | |||
| 753 | if ((type_ok && (mem_type == TTM_PL_SYSTEM)) || node) { | ||
| 754 | mem->mm_node = node; | ||
| 755 | mem->mem_type = mem_type; | ||
| 756 | mem->placement = cur_flags; | ||
| 757 | return 0; | ||
| 758 | } | ||
| 759 | |||
| 760 | if (!type_found) | ||
| 761 | return -EINVAL; | ||
| 762 | |||
| 763 | num_prios = bdev->driver->num_mem_busy_prio; | ||
| 764 | prios = bdev->driver->mem_busy_prio; | ||
| 765 | |||
| 766 | for (i = 0; i < num_prios; ++i) { | ||
| 767 | mem_type = prios[i]; | ||
| 768 | man = &bdev->man[mem_type]; | ||
| 769 | |||
| 770 | if (!man->has_type) | ||
| 771 | continue; | ||
| 772 | |||
| 773 | if (!ttm_bo_mt_compatible(man, | ||
| 774 | bo->type == ttm_bo_type_user, | ||
| 775 | mem_type, | ||
| 776 | proposed_placement, &cur_flags)) | ||
| 777 | continue; | ||
| 778 | |||
| 779 | ret = ttm_bo_mem_force_space(bdev, mem, mem_type, | ||
| 780 | interruptible, no_wait); | ||
| 781 | |||
| 782 | if (ret == 0 && mem->mm_node) { | ||
| 783 | mem->placement = cur_flags; | ||
| 784 | return 0; | ||
| 785 | } | ||
| 786 | |||
| 787 | if (ret == -ERESTART) | ||
| 788 | has_eagain = true; | ||
| 789 | } | ||
| 790 | |||
| 791 | ret = (has_eagain) ? -ERESTART : -ENOMEM; | ||
| 792 | return ret; | ||
| 793 | } | ||
| 794 | EXPORT_SYMBOL(ttm_bo_mem_space); | ||
| 795 | |||
| 796 | int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool no_wait) | ||
| 797 | { | ||
| 798 | int ret = 0; | ||
| 799 | |||
| 800 | if ((atomic_read(&bo->cpu_writers) > 0) && no_wait) | ||
| 801 | return -EBUSY; | ||
| 802 | |||
| 803 | ret = wait_event_interruptible(bo->event_queue, | ||
| 804 | atomic_read(&bo->cpu_writers) == 0); | ||
| 805 | |||
| 806 | if (ret == -ERESTARTSYS) | ||
| 807 | ret = -ERESTART; | ||
| 808 | |||
| 809 | return ret; | ||
| 810 | } | ||
| 811 | |||
| 812 | int ttm_bo_move_buffer(struct ttm_buffer_object *bo, | ||
| 813 | uint32_t proposed_placement, | ||
| 814 | bool interruptible, bool no_wait) | ||
| 815 | { | ||
| 816 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 817 | int ret = 0; | ||
| 818 | struct ttm_mem_reg mem; | ||
| 819 | |||
| 820 | BUG_ON(!atomic_read(&bo->reserved)); | ||
| 821 | |||
| 822 | /* | ||
| 823 | * FIXME: It's possible to pipeline buffer moves. | ||
| 824 | * Have the driver move function wait for idle when necessary, | ||
| 825 | * instead of doing it here. | ||
| 826 | */ | ||
| 827 | |||
| 828 | spin_lock(&bo->lock); | ||
| 829 | ret = ttm_bo_wait(bo, false, interruptible, no_wait); | ||
| 830 | spin_unlock(&bo->lock); | ||
| 831 | |||
| 832 | if (ret) | ||
| 833 | return ret; | ||
| 834 | |||
| 835 | mem.num_pages = bo->num_pages; | ||
| 836 | mem.size = mem.num_pages << PAGE_SHIFT; | ||
| 837 | mem.page_alignment = bo->mem.page_alignment; | ||
| 838 | |||
| 839 | /* | ||
| 840 | * Determine where to move the buffer. | ||
| 841 | */ | ||
| 842 | |||
| 843 | ret = ttm_bo_mem_space(bo, proposed_placement, &mem, | ||
| 844 | interruptible, no_wait); | ||
| 845 | if (ret) | ||
| 846 | goto out_unlock; | ||
| 847 | |||
| 848 | ret = ttm_bo_handle_move_mem(bo, &mem, false, interruptible, no_wait); | ||
| 849 | |||
| 850 | out_unlock: | ||
| 851 | if (ret && mem.mm_node) { | ||
| 852 | spin_lock(&bdev->lru_lock); | ||
| 853 | drm_mm_put_block(mem.mm_node); | ||
| 854 | spin_unlock(&bdev->lru_lock); | ||
| 855 | } | ||
| 856 | return ret; | ||
| 857 | } | ||
| 858 | |||
| 859 | static int ttm_bo_mem_compat(uint32_t proposed_placement, | ||
| 860 | struct ttm_mem_reg *mem) | ||
| 861 | { | ||
| 862 | if ((proposed_placement & mem->placement & TTM_PL_MASK_MEM) == 0) | ||
| 863 | return 0; | ||
| 864 | if ((proposed_placement & mem->placement & TTM_PL_MASK_CACHING) == 0) | ||
| 865 | return 0; | ||
| 866 | |||
| 867 | return 1; | ||
| 868 | } | ||
| 869 | |||
| 870 | int ttm_buffer_object_validate(struct ttm_buffer_object *bo, | ||
| 871 | uint32_t proposed_placement, | ||
| 872 | bool interruptible, bool no_wait) | ||
| 873 | { | ||
| 874 | int ret; | ||
| 875 | |||
| 876 | BUG_ON(!atomic_read(&bo->reserved)); | ||
| 877 | bo->proposed_placement = proposed_placement; | ||
| 878 | |||
| 879 | TTM_DEBUG("Proposed placement 0x%08lx, Old flags 0x%08lx\n", | ||
| 880 | (unsigned long)proposed_placement, | ||
| 881 | (unsigned long)bo->mem.placement); | ||
| 882 | |||
| 883 | /* | ||
| 884 | * Check whether we need to move buffer. | ||
| 885 | */ | ||
| 886 | |||
| 887 | if (!ttm_bo_mem_compat(bo->proposed_placement, &bo->mem)) { | ||
| 888 | ret = ttm_bo_move_buffer(bo, bo->proposed_placement, | ||
| 889 | interruptible, no_wait); | ||
| 890 | if (ret) { | ||
| 891 | if (ret != -ERESTART) | ||
| 892 | printk(KERN_ERR TTM_PFX | ||
| 893 | "Failed moving buffer. " | ||
| 894 | "Proposed placement 0x%08x\n", | ||
| 895 | bo->proposed_placement); | ||
| 896 | if (ret == -ENOMEM) | ||
| 897 | printk(KERN_ERR TTM_PFX | ||
| 898 | "Out of aperture space or " | ||
| 899 | "DRM memory quota.\n"); | ||
| 900 | return ret; | ||
| 901 | } | ||
| 902 | } | ||
| 903 | |||
| 904 | /* | ||
| 905 | * We might need to add a TTM. | ||
| 906 | */ | ||
| 907 | |||
| 908 | if (bo->mem.mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { | ||
| 909 | ret = ttm_bo_add_ttm(bo, true); | ||
| 910 | if (ret) | ||
| 911 | return ret; | ||
| 912 | } | ||
| 913 | /* | ||
| 914 | * Validation has succeeded, move the access and other | ||
| 915 | * non-mapping-related flag bits from the proposed flags to | ||
| 916 | * the active flags | ||
| 917 | */ | ||
| 918 | |||
| 919 | ttm_flag_masked(&bo->mem.placement, bo->proposed_placement, | ||
| 920 | ~TTM_PL_MASK_MEMTYPE); | ||
| 921 | |||
| 922 | return 0; | ||
| 923 | } | ||
| 924 | EXPORT_SYMBOL(ttm_buffer_object_validate); | ||
| 925 | |||
| 926 | int | ||
| 927 | ttm_bo_check_placement(struct ttm_buffer_object *bo, | ||
| 928 | uint32_t set_flags, uint32_t clr_flags) | ||
| 929 | { | ||
| 930 | uint32_t new_mask = set_flags | clr_flags; | ||
| 931 | |||
| 932 | if ((bo->type == ttm_bo_type_user) && | ||
| 933 | (clr_flags & TTM_PL_FLAG_CACHED)) { | ||
| 934 | printk(KERN_ERR TTM_PFX | ||
| 935 | "User buffers require cache-coherent memory.\n"); | ||
| 936 | return -EINVAL; | ||
| 937 | } | ||
| 938 | |||
| 939 | if (!capable(CAP_SYS_ADMIN)) { | ||
| 940 | if (new_mask & TTM_PL_FLAG_NO_EVICT) { | ||
| 941 | printk(KERN_ERR TTM_PFX "Need to be root to modify" | ||
| 942 | " NO_EVICT status.\n"); | ||
| 943 | return -EINVAL; | ||
| 944 | } | ||
| 945 | |||
| 946 | if ((clr_flags & bo->mem.placement & TTM_PL_MASK_MEMTYPE) && | ||
| 947 | (bo->mem.placement & TTM_PL_FLAG_NO_EVICT)) { | ||
| 948 | printk(KERN_ERR TTM_PFX | ||
| 949 | "Incompatible memory specification" | ||
| 950 | " for NO_EVICT buffer.\n"); | ||
| 951 | return -EINVAL; | ||
| 952 | } | ||
| 953 | } | ||
| 954 | return 0; | ||
| 955 | } | ||
| 956 | |||
| 957 | int ttm_buffer_object_init(struct ttm_bo_device *bdev, | ||
| 958 | struct ttm_buffer_object *bo, | ||
| 959 | unsigned long size, | ||
| 960 | enum ttm_bo_type type, | ||
| 961 | uint32_t flags, | ||
| 962 | uint32_t page_alignment, | ||
| 963 | unsigned long buffer_start, | ||
| 964 | bool interruptible, | ||
| 965 | struct file *persistant_swap_storage, | ||
| 966 | size_t acc_size, | ||
| 967 | void (*destroy) (struct ttm_buffer_object *)) | ||
| 968 | { | ||
| 969 | int ret = 0; | ||
| 970 | unsigned long num_pages; | ||
| 971 | |||
| 972 | size += buffer_start & ~PAGE_MASK; | ||
| 973 | num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
| 974 | if (num_pages == 0) { | ||
| 975 | printk(KERN_ERR TTM_PFX "Illegal buffer object size.\n"); | ||
| 976 | return -EINVAL; | ||
| 977 | } | ||
| 978 | bo->destroy = destroy; | ||
| 979 | |||
| 980 | spin_lock_init(&bo->lock); | ||
| 981 | kref_init(&bo->kref); | ||
| 982 | kref_init(&bo->list_kref); | ||
| 983 | atomic_set(&bo->cpu_writers, 0); | ||
| 984 | atomic_set(&bo->reserved, 1); | ||
| 985 | init_waitqueue_head(&bo->event_queue); | ||
| 986 | INIT_LIST_HEAD(&bo->lru); | ||
| 987 | INIT_LIST_HEAD(&bo->ddestroy); | ||
| 988 | INIT_LIST_HEAD(&bo->swap); | ||
| 989 | bo->bdev = bdev; | ||
| 990 | bo->type = type; | ||
| 991 | bo->num_pages = num_pages; | ||
| 992 | bo->mem.mem_type = TTM_PL_SYSTEM; | ||
| 993 | bo->mem.num_pages = bo->num_pages; | ||
| 994 | bo->mem.mm_node = NULL; | ||
| 995 | bo->mem.page_alignment = page_alignment; | ||
| 996 | bo->buffer_start = buffer_start & PAGE_MASK; | ||
| 997 | bo->priv_flags = 0; | ||
| 998 | bo->mem.placement = (TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED); | ||
| 999 | bo->seq_valid = false; | ||
| 1000 | bo->persistant_swap_storage = persistant_swap_storage; | ||
| 1001 | bo->acc_size = acc_size; | ||
| 1002 | |||
| 1003 | ret = ttm_bo_check_placement(bo, flags, 0ULL); | ||
| 1004 | if (unlikely(ret != 0)) | ||
| 1005 | goto out_err; | ||
| 1006 | |||
| 1007 | /* | ||
| 1008 | * If no caching attributes are set, accept any form of caching. | ||
| 1009 | */ | ||
| 1010 | |||
| 1011 | if ((flags & TTM_PL_MASK_CACHING) == 0) | ||
| 1012 | flags |= TTM_PL_MASK_CACHING; | ||
| 1013 | |||
| 1014 | /* | ||
| 1015 | * For ttm_bo_type_device buffers, allocate | ||
| 1016 | * address space from the device. | ||
| 1017 | */ | ||
| 1018 | |||
| 1019 | if (bo->type == ttm_bo_type_device) { | ||
| 1020 | ret = ttm_bo_setup_vm(bo); | ||
| 1021 | if (ret) | ||
| 1022 | goto out_err; | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | ret = ttm_buffer_object_validate(bo, flags, interruptible, false); | ||
| 1026 | if (ret) | ||
| 1027 | goto out_err; | ||
| 1028 | |||
| 1029 | ttm_bo_unreserve(bo); | ||
| 1030 | return 0; | ||
| 1031 | |||
| 1032 | out_err: | ||
| 1033 | ttm_bo_unreserve(bo); | ||
| 1034 | ttm_bo_unref(&bo); | ||
| 1035 | |||
| 1036 | return ret; | ||
| 1037 | } | ||
| 1038 | EXPORT_SYMBOL(ttm_buffer_object_init); | ||
| 1039 | |||
| 1040 | static inline size_t ttm_bo_size(struct ttm_bo_device *bdev, | ||
| 1041 | unsigned long num_pages) | ||
| 1042 | { | ||
| 1043 | size_t page_array_size = (num_pages * sizeof(void *) + PAGE_SIZE - 1) & | ||
| 1044 | PAGE_MASK; | ||
| 1045 | |||
| 1046 | return bdev->ttm_bo_size + 2 * page_array_size; | ||
| 1047 | } | ||
| 1048 | |||
| 1049 | int ttm_buffer_object_create(struct ttm_bo_device *bdev, | ||
| 1050 | unsigned long size, | ||
| 1051 | enum ttm_bo_type type, | ||
| 1052 | uint32_t flags, | ||
| 1053 | uint32_t page_alignment, | ||
| 1054 | unsigned long buffer_start, | ||
| 1055 | bool interruptible, | ||
| 1056 | struct file *persistant_swap_storage, | ||
| 1057 | struct ttm_buffer_object **p_bo) | ||
| 1058 | { | ||
| 1059 | struct ttm_buffer_object *bo; | ||
| 1060 | int ret; | ||
| 1061 | struct ttm_mem_global *mem_glob = bdev->mem_glob; | ||
| 1062 | |||
| 1063 | size_t acc_size = | ||
| 1064 | ttm_bo_size(bdev, (size + PAGE_SIZE - 1) >> PAGE_SHIFT); | ||
| 1065 | ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false, false); | ||
| 1066 | if (unlikely(ret != 0)) | ||
| 1067 | return ret; | ||
| 1068 | |||
| 1069 | bo = kzalloc(sizeof(*bo), GFP_KERNEL); | ||
| 1070 | |||
| 1071 | if (unlikely(bo == NULL)) { | ||
| 1072 | ttm_mem_global_free(mem_glob, acc_size, false); | ||
| 1073 | return -ENOMEM; | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | ret = ttm_buffer_object_init(bdev, bo, size, type, flags, | ||
| 1077 | page_alignment, buffer_start, | ||
| 1078 | interruptible, | ||
| 1079 | persistant_swap_storage, acc_size, NULL); | ||
| 1080 | if (likely(ret == 0)) | ||
| 1081 | *p_bo = bo; | ||
| 1082 | |||
| 1083 | return ret; | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | static int ttm_bo_leave_list(struct ttm_buffer_object *bo, | ||
| 1087 | uint32_t mem_type, bool allow_errors) | ||
| 1088 | { | ||
| 1089 | int ret; | ||
| 1090 | |||
| 1091 | spin_lock(&bo->lock); | ||
| 1092 | ret = ttm_bo_wait(bo, false, false, false); | ||
| 1093 | spin_unlock(&bo->lock); | ||
| 1094 | |||
| 1095 | if (ret && allow_errors) | ||
| 1096 | goto out; | ||
| 1097 | |||
| 1098 | if (bo->mem.mem_type == mem_type) | ||
| 1099 | ret = ttm_bo_evict(bo, mem_type, false, false); | ||
| 1100 | |||
| 1101 | if (ret) { | ||
| 1102 | if (allow_errors) { | ||
| 1103 | goto out; | ||
| 1104 | } else { | ||
| 1105 | ret = 0; | ||
| 1106 | printk(KERN_ERR TTM_PFX "Cleanup eviction failed\n"); | ||
| 1107 | } | ||
| 1108 | } | ||
| 1109 | |||
| 1110 | out: | ||
| 1111 | return ret; | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | static int ttm_bo_force_list_clean(struct ttm_bo_device *bdev, | ||
| 1115 | struct list_head *head, | ||
| 1116 | unsigned mem_type, bool allow_errors) | ||
| 1117 | { | ||
| 1118 | struct ttm_buffer_object *entry; | ||
| 1119 | int ret; | ||
| 1120 | int put_count; | ||
| 1121 | |||
| 1122 | /* | ||
| 1123 | * Can't use standard list traversal since we're unlocking. | ||
| 1124 | */ | ||
| 1125 | |||
| 1126 | spin_lock(&bdev->lru_lock); | ||
| 1127 | |||
| 1128 | while (!list_empty(head)) { | ||
| 1129 | entry = list_first_entry(head, struct ttm_buffer_object, lru); | ||
| 1130 | kref_get(&entry->list_kref); | ||
| 1131 | ret = ttm_bo_reserve_locked(entry, false, false, false, 0); | ||
| 1132 | put_count = ttm_bo_del_from_lru(entry); | ||
| 1133 | spin_unlock(&bdev->lru_lock); | ||
| 1134 | while (put_count--) | ||
| 1135 | kref_put(&entry->list_kref, ttm_bo_ref_bug); | ||
| 1136 | BUG_ON(ret); | ||
| 1137 | ret = ttm_bo_leave_list(entry, mem_type, allow_errors); | ||
| 1138 | ttm_bo_unreserve(entry); | ||
| 1139 | kref_put(&entry->list_kref, ttm_bo_release_list); | ||
| 1140 | spin_lock(&bdev->lru_lock); | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | spin_unlock(&bdev->lru_lock); | ||
| 1144 | |||
| 1145 | return 0; | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type) | ||
| 1149 | { | ||
| 1150 | struct ttm_mem_type_manager *man = &bdev->man[mem_type]; | ||
| 1151 | int ret = -EINVAL; | ||
| 1152 | |||
| 1153 | if (mem_type >= TTM_NUM_MEM_TYPES) { | ||
| 1154 | printk(KERN_ERR TTM_PFX "Illegal memory type %d\n", mem_type); | ||
| 1155 | return ret; | ||
| 1156 | } | ||
| 1157 | |||
| 1158 | if (!man->has_type) { | ||
| 1159 | printk(KERN_ERR TTM_PFX "Trying to take down uninitialized " | ||
| 1160 | "memory manager type %u\n", mem_type); | ||
| 1161 | return ret; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | man->use_type = false; | ||
| 1165 | man->has_type = false; | ||
| 1166 | |||
| 1167 | ret = 0; | ||
| 1168 | if (mem_type > 0) { | ||
| 1169 | ttm_bo_force_list_clean(bdev, &man->lru, mem_type, false); | ||
| 1170 | |||
| 1171 | spin_lock(&bdev->lru_lock); | ||
| 1172 | if (drm_mm_clean(&man->manager)) | ||
| 1173 | drm_mm_takedown(&man->manager); | ||
| 1174 | else | ||
| 1175 | ret = -EBUSY; | ||
| 1176 | |||
| 1177 | spin_unlock(&bdev->lru_lock); | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | return ret; | ||
| 1181 | } | ||
| 1182 | EXPORT_SYMBOL(ttm_bo_clean_mm); | ||
| 1183 | |||
| 1184 | int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type) | ||
| 1185 | { | ||
| 1186 | struct ttm_mem_type_manager *man = &bdev->man[mem_type]; | ||
| 1187 | |||
| 1188 | if (mem_type == 0 || mem_type >= TTM_NUM_MEM_TYPES) { | ||
| 1189 | printk(KERN_ERR TTM_PFX | ||
| 1190 | "Illegal memory manager memory type %u.\n", | ||
| 1191 | mem_type); | ||
| 1192 | return -EINVAL; | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | if (!man->has_type) { | ||
| 1196 | printk(KERN_ERR TTM_PFX | ||
| 1197 | "Memory type %u has not been initialized.\n", | ||
| 1198 | mem_type); | ||
| 1199 | return 0; | ||
| 1200 | } | ||
| 1201 | |||
| 1202 | return ttm_bo_force_list_clean(bdev, &man->lru, mem_type, true); | ||
| 1203 | } | ||
| 1204 | EXPORT_SYMBOL(ttm_bo_evict_mm); | ||
| 1205 | |||
| 1206 | int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, | ||
| 1207 | unsigned long p_offset, unsigned long p_size) | ||
| 1208 | { | ||
| 1209 | int ret = -EINVAL; | ||
| 1210 | struct ttm_mem_type_manager *man; | ||
| 1211 | |||
| 1212 | if (type >= TTM_NUM_MEM_TYPES) { | ||
| 1213 | printk(KERN_ERR TTM_PFX "Illegal memory type %d\n", type); | ||
| 1214 | return ret; | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | man = &bdev->man[type]; | ||
| 1218 | if (man->has_type) { | ||
| 1219 | printk(KERN_ERR TTM_PFX | ||
| 1220 | "Memory manager already initialized for type %d\n", | ||
| 1221 | type); | ||
| 1222 | return ret; | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | ret = bdev->driver->init_mem_type(bdev, type, man); | ||
| 1226 | if (ret) | ||
| 1227 | return ret; | ||
| 1228 | |||
| 1229 | ret = 0; | ||
| 1230 | if (type != TTM_PL_SYSTEM) { | ||
| 1231 | if (!p_size) { | ||
| 1232 | printk(KERN_ERR TTM_PFX | ||
| 1233 | "Zero size memory manager type %d\n", | ||
| 1234 | type); | ||
| 1235 | return ret; | ||
| 1236 | } | ||
| 1237 | ret = drm_mm_init(&man->manager, p_offset, p_size); | ||
| 1238 | if (ret) | ||
| 1239 | return ret; | ||
| 1240 | } | ||
| 1241 | man->has_type = true; | ||
| 1242 | man->use_type = true; | ||
| 1243 | man->size = p_size; | ||
| 1244 | |||
| 1245 | INIT_LIST_HEAD(&man->lru); | ||
| 1246 | |||
| 1247 | return 0; | ||
| 1248 | } | ||
| 1249 | EXPORT_SYMBOL(ttm_bo_init_mm); | ||
| 1250 | |||
| 1251 | int ttm_bo_device_release(struct ttm_bo_device *bdev) | ||
| 1252 | { | ||
| 1253 | int ret = 0; | ||
| 1254 | unsigned i = TTM_NUM_MEM_TYPES; | ||
| 1255 | struct ttm_mem_type_manager *man; | ||
| 1256 | |||
| 1257 | while (i--) { | ||
| 1258 | man = &bdev->man[i]; | ||
| 1259 | if (man->has_type) { | ||
| 1260 | man->use_type = false; | ||
| 1261 | if ((i != TTM_PL_SYSTEM) && ttm_bo_clean_mm(bdev, i)) { | ||
| 1262 | ret = -EBUSY; | ||
| 1263 | printk(KERN_ERR TTM_PFX | ||
| 1264 | "DRM memory manager type %d " | ||
| 1265 | "is not clean.\n", i); | ||
| 1266 | } | ||
| 1267 | man->has_type = false; | ||
| 1268 | } | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | if (!cancel_delayed_work(&bdev->wq)) | ||
| 1272 | flush_scheduled_work(); | ||
| 1273 | |||
| 1274 | while (ttm_bo_delayed_delete(bdev, true)) | ||
| 1275 | ; | ||
| 1276 | |||
| 1277 | spin_lock(&bdev->lru_lock); | ||
| 1278 | if (list_empty(&bdev->ddestroy)) | ||
| 1279 | TTM_DEBUG("Delayed destroy list was clean\n"); | ||
| 1280 | |||
| 1281 | if (list_empty(&bdev->man[0].lru)) | ||
| 1282 | TTM_DEBUG("Swap list was clean\n"); | ||
| 1283 | spin_unlock(&bdev->lru_lock); | ||
| 1284 | |||
| 1285 | ttm_mem_unregister_shrink(bdev->mem_glob, &bdev->shrink); | ||
| 1286 | BUG_ON(!drm_mm_clean(&bdev->addr_space_mm)); | ||
| 1287 | write_lock(&bdev->vm_lock); | ||
| 1288 | drm_mm_takedown(&bdev->addr_space_mm); | ||
| 1289 | write_unlock(&bdev->vm_lock); | ||
| 1290 | |||
| 1291 | __free_page(bdev->dummy_read_page); | ||
| 1292 | return ret; | ||
| 1293 | } | ||
| 1294 | EXPORT_SYMBOL(ttm_bo_device_release); | ||
| 1295 | |||
| 1296 | /* | ||
| 1297 | * This function is intended to be called on drm driver load. | ||
| 1298 | * If you decide to call it from firstopen, you must protect the call | ||
| 1299 | * from a potentially racing ttm_bo_driver_finish in lastclose. | ||
| 1300 | * (This may happen on X server restart). | ||
| 1301 | */ | ||
| 1302 | |||
| 1303 | int ttm_bo_device_init(struct ttm_bo_device *bdev, | ||
| 1304 | struct ttm_mem_global *mem_glob, | ||
| 1305 | struct ttm_bo_driver *driver, uint64_t file_page_offset) | ||
| 1306 | { | ||
| 1307 | int ret = -EINVAL; | ||
| 1308 | |||
| 1309 | bdev->dummy_read_page = NULL; | ||
| 1310 | rwlock_init(&bdev->vm_lock); | ||
| 1311 | spin_lock_init(&bdev->lru_lock); | ||
| 1312 | |||
| 1313 | bdev->driver = driver; | ||
| 1314 | bdev->mem_glob = mem_glob; | ||
| 1315 | |||
| 1316 | memset(bdev->man, 0, sizeof(bdev->man)); | ||
| 1317 | |||
| 1318 | bdev->dummy_read_page = alloc_page(__GFP_ZERO | GFP_DMA32); | ||
| 1319 | if (unlikely(bdev->dummy_read_page == NULL)) { | ||
| 1320 | ret = -ENOMEM; | ||
| 1321 | goto out_err0; | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | /* | ||
| 1325 | * Initialize the system memory buffer type. | ||
| 1326 | * Other types need to be driver / IOCTL initialized. | ||
| 1327 | */ | ||
| 1328 | ret = ttm_bo_init_mm(bdev, TTM_PL_SYSTEM, 0, 0); | ||
| 1329 | if (unlikely(ret != 0)) | ||
| 1330 | goto out_err1; | ||
| 1331 | |||
| 1332 | bdev->addr_space_rb = RB_ROOT; | ||
| 1333 | ret = drm_mm_init(&bdev->addr_space_mm, file_page_offset, 0x10000000); | ||
| 1334 | if (unlikely(ret != 0)) | ||
| 1335 | goto out_err2; | ||
| 1336 | |||
| 1337 | INIT_DELAYED_WORK(&bdev->wq, ttm_bo_delayed_workqueue); | ||
| 1338 | bdev->nice_mode = true; | ||
| 1339 | INIT_LIST_HEAD(&bdev->ddestroy); | ||
| 1340 | INIT_LIST_HEAD(&bdev->swap_lru); | ||
| 1341 | bdev->dev_mapping = NULL; | ||
| 1342 | ttm_mem_init_shrink(&bdev->shrink, ttm_bo_swapout); | ||
| 1343 | ret = ttm_mem_register_shrink(mem_glob, &bdev->shrink); | ||
| 1344 | if (unlikely(ret != 0)) { | ||
| 1345 | printk(KERN_ERR TTM_PFX | ||
| 1346 | "Could not register buffer object swapout.\n"); | ||
| 1347 | goto out_err2; | ||
| 1348 | } | ||
| 1349 | |||
| 1350 | bdev->ttm_bo_extra_size = | ||
| 1351 | ttm_round_pot(sizeof(struct ttm_tt)) + | ||
| 1352 | ttm_round_pot(sizeof(struct ttm_backend)); | ||
| 1353 | |||
| 1354 | bdev->ttm_bo_size = bdev->ttm_bo_extra_size + | ||
| 1355 | ttm_round_pot(sizeof(struct ttm_buffer_object)); | ||
| 1356 | |||
| 1357 | return 0; | ||
| 1358 | out_err2: | ||
| 1359 | ttm_bo_clean_mm(bdev, 0); | ||
| 1360 | out_err1: | ||
| 1361 | __free_page(bdev->dummy_read_page); | ||
| 1362 | out_err0: | ||
| 1363 | return ret; | ||
| 1364 | } | ||
| 1365 | EXPORT_SYMBOL(ttm_bo_device_init); | ||
| 1366 | |||
| 1367 | /* | ||
| 1368 | * buffer object vm functions. | ||
| 1369 | */ | ||
| 1370 | |||
| 1371 | bool ttm_mem_reg_is_pci(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem) | ||
| 1372 | { | ||
| 1373 | struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; | ||
| 1374 | |||
| 1375 | if (!(man->flags & TTM_MEMTYPE_FLAG_FIXED)) { | ||
| 1376 | if (mem->mem_type == TTM_PL_SYSTEM) | ||
| 1377 | return false; | ||
| 1378 | |||
| 1379 | if (man->flags & TTM_MEMTYPE_FLAG_CMA) | ||
| 1380 | return false; | ||
| 1381 | |||
| 1382 | if (mem->placement & TTM_PL_FLAG_CACHED) | ||
| 1383 | return false; | ||
| 1384 | } | ||
| 1385 | return true; | ||
| 1386 | } | ||
| 1387 | |||
| 1388 | int ttm_bo_pci_offset(struct ttm_bo_device *bdev, | ||
| 1389 | struct ttm_mem_reg *mem, | ||
| 1390 | unsigned long *bus_base, | ||
| 1391 | unsigned long *bus_offset, unsigned long *bus_size) | ||
| 1392 | { | ||
| 1393 | struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; | ||
| 1394 | |||
| 1395 | *bus_size = 0; | ||
| 1396 | if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE)) | ||
| 1397 | return -EINVAL; | ||
| 1398 | |||
| 1399 | if (ttm_mem_reg_is_pci(bdev, mem)) { | ||
| 1400 | *bus_offset = mem->mm_node->start << PAGE_SHIFT; | ||
| 1401 | *bus_size = mem->num_pages << PAGE_SHIFT; | ||
| 1402 | *bus_base = man->io_offset; | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | return 0; | ||
| 1406 | } | ||
| 1407 | |||
| 1408 | void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo) | ||
| 1409 | { | ||
| 1410 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 1411 | loff_t offset = (loff_t) bo->addr_space_offset; | ||
| 1412 | loff_t holelen = ((loff_t) bo->mem.num_pages) << PAGE_SHIFT; | ||
| 1413 | |||
| 1414 | if (!bdev->dev_mapping) | ||
| 1415 | return; | ||
| 1416 | |||
| 1417 | unmap_mapping_range(bdev->dev_mapping, offset, holelen, 1); | ||
| 1418 | } | ||
| 1419 | |||
| 1420 | static void ttm_bo_vm_insert_rb(struct ttm_buffer_object *bo) | ||
| 1421 | { | ||
| 1422 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 1423 | struct rb_node **cur = &bdev->addr_space_rb.rb_node; | ||
| 1424 | struct rb_node *parent = NULL; | ||
| 1425 | struct ttm_buffer_object *cur_bo; | ||
| 1426 | unsigned long offset = bo->vm_node->start; | ||
| 1427 | unsigned long cur_offset; | ||
| 1428 | |||
| 1429 | while (*cur) { | ||
| 1430 | parent = *cur; | ||
| 1431 | cur_bo = rb_entry(parent, struct ttm_buffer_object, vm_rb); | ||
| 1432 | cur_offset = cur_bo->vm_node->start; | ||
| 1433 | if (offset < cur_offset) | ||
| 1434 | cur = &parent->rb_left; | ||
| 1435 | else if (offset > cur_offset) | ||
| 1436 | cur = &parent->rb_right; | ||
| 1437 | else | ||
| 1438 | BUG(); | ||
| 1439 | } | ||
| 1440 | |||
| 1441 | rb_link_node(&bo->vm_rb, parent, cur); | ||
| 1442 | rb_insert_color(&bo->vm_rb, &bdev->addr_space_rb); | ||
| 1443 | } | ||
| 1444 | |||
| 1445 | /** | ||
| 1446 | * ttm_bo_setup_vm: | ||
| 1447 | * | ||
| 1448 | * @bo: the buffer to allocate address space for | ||
| 1449 | * | ||
| 1450 | * Allocate address space in the drm device so that applications | ||
| 1451 | * can mmap the buffer and access the contents. This only | ||
| 1452 | * applies to ttm_bo_type_device objects as others are not | ||
| 1453 | * placed in the drm device address space. | ||
| 1454 | */ | ||
| 1455 | |||
| 1456 | static int ttm_bo_setup_vm(struct ttm_buffer_object *bo) | ||
| 1457 | { | ||
| 1458 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 1459 | int ret; | ||
| 1460 | |||
| 1461 | retry_pre_get: | ||
| 1462 | ret = drm_mm_pre_get(&bdev->addr_space_mm); | ||
| 1463 | if (unlikely(ret != 0)) | ||
| 1464 | return ret; | ||
| 1465 | |||
| 1466 | write_lock(&bdev->vm_lock); | ||
| 1467 | bo->vm_node = drm_mm_search_free(&bdev->addr_space_mm, | ||
| 1468 | bo->mem.num_pages, 0, 0); | ||
| 1469 | |||
| 1470 | if (unlikely(bo->vm_node == NULL)) { | ||
| 1471 | ret = -ENOMEM; | ||
| 1472 | goto out_unlock; | ||
| 1473 | } | ||
| 1474 | |||
| 1475 | bo->vm_node = drm_mm_get_block_atomic(bo->vm_node, | ||
| 1476 | bo->mem.num_pages, 0); | ||
| 1477 | |||
| 1478 | if (unlikely(bo->vm_node == NULL)) { | ||
| 1479 | write_unlock(&bdev->vm_lock); | ||
| 1480 | goto retry_pre_get; | ||
| 1481 | } | ||
| 1482 | |||
| 1483 | ttm_bo_vm_insert_rb(bo); | ||
| 1484 | write_unlock(&bdev->vm_lock); | ||
| 1485 | bo->addr_space_offset = ((uint64_t) bo->vm_node->start) << PAGE_SHIFT; | ||
| 1486 | |||
| 1487 | return 0; | ||
| 1488 | out_unlock: | ||
| 1489 | write_unlock(&bdev->vm_lock); | ||
| 1490 | return ret; | ||
| 1491 | } | ||
| 1492 | |||
| 1493 | int ttm_bo_wait(struct ttm_buffer_object *bo, | ||
| 1494 | bool lazy, bool interruptible, bool no_wait) | ||
| 1495 | { | ||
| 1496 | struct ttm_bo_driver *driver = bo->bdev->driver; | ||
| 1497 | void *sync_obj; | ||
| 1498 | void *sync_obj_arg; | ||
| 1499 | int ret = 0; | ||
| 1500 | |||
| 1501 | if (likely(bo->sync_obj == NULL)) | ||
| 1502 | return 0; | ||
| 1503 | |||
| 1504 | while (bo->sync_obj) { | ||
| 1505 | |||
| 1506 | if (driver->sync_obj_signaled(bo->sync_obj, bo->sync_obj_arg)) { | ||
| 1507 | void *tmp_obj = bo->sync_obj; | ||
| 1508 | bo->sync_obj = NULL; | ||
| 1509 | clear_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags); | ||
| 1510 | spin_unlock(&bo->lock); | ||
| 1511 | driver->sync_obj_unref(&tmp_obj); | ||
| 1512 | spin_lock(&bo->lock); | ||
| 1513 | continue; | ||
| 1514 | } | ||
| 1515 | |||
| 1516 | if (no_wait) | ||
| 1517 | return -EBUSY; | ||
| 1518 | |||
| 1519 | sync_obj = driver->sync_obj_ref(bo->sync_obj); | ||
| 1520 | sync_obj_arg = bo->sync_obj_arg; | ||
| 1521 | spin_unlock(&bo->lock); | ||
| 1522 | ret = driver->sync_obj_wait(sync_obj, sync_obj_arg, | ||
| 1523 | lazy, interruptible); | ||
| 1524 | if (unlikely(ret != 0)) { | ||
| 1525 | driver->sync_obj_unref(&sync_obj); | ||
| 1526 | spin_lock(&bo->lock); | ||
| 1527 | return ret; | ||
| 1528 | } | ||
| 1529 | spin_lock(&bo->lock); | ||
| 1530 | if (likely(bo->sync_obj == sync_obj && | ||
| 1531 | bo->sync_obj_arg == sync_obj_arg)) { | ||
| 1532 | void *tmp_obj = bo->sync_obj; | ||
| 1533 | bo->sync_obj = NULL; | ||
| 1534 | clear_bit(TTM_BO_PRIV_FLAG_MOVING, | ||
| 1535 | &bo->priv_flags); | ||
| 1536 | spin_unlock(&bo->lock); | ||
| 1537 | driver->sync_obj_unref(&sync_obj); | ||
| 1538 | driver->sync_obj_unref(&tmp_obj); | ||
| 1539 | spin_lock(&bo->lock); | ||
| 1540 | } | ||
| 1541 | } | ||
| 1542 | return 0; | ||
| 1543 | } | ||
| 1544 | EXPORT_SYMBOL(ttm_bo_wait); | ||
| 1545 | |||
| 1546 | void ttm_bo_unblock_reservation(struct ttm_buffer_object *bo) | ||
| 1547 | { | ||
| 1548 | atomic_set(&bo->reserved, 0); | ||
| 1549 | wake_up_all(&bo->event_queue); | ||
| 1550 | } | ||
| 1551 | |||
| 1552 | int ttm_bo_block_reservation(struct ttm_buffer_object *bo, bool interruptible, | ||
| 1553 | bool no_wait) | ||
| 1554 | { | ||
| 1555 | int ret; | ||
| 1556 | |||
| 1557 | while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) { | ||
| 1558 | if (no_wait) | ||
| 1559 | return -EBUSY; | ||
| 1560 | else if (interruptible) { | ||
| 1561 | ret = wait_event_interruptible | ||
| 1562 | (bo->event_queue, atomic_read(&bo->reserved) == 0); | ||
| 1563 | if (unlikely(ret != 0)) | ||
| 1564 | return -ERESTART; | ||
| 1565 | } else { | ||
| 1566 | wait_event(bo->event_queue, | ||
| 1567 | atomic_read(&bo->reserved) == 0); | ||
| 1568 | } | ||
| 1569 | } | ||
| 1570 | return 0; | ||
| 1571 | } | ||
| 1572 | |||
| 1573 | int ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait) | ||
| 1574 | { | ||
| 1575 | int ret = 0; | ||
| 1576 | |||
| 1577 | /* | ||
| 1578 | * Using ttm_bo_reserve instead of ttm_bo_block_reservation | ||
| 1579 | * makes sure the lru lists are updated. | ||
| 1580 | */ | ||
| 1581 | |||
| 1582 | ret = ttm_bo_reserve(bo, true, no_wait, false, 0); | ||
| 1583 | if (unlikely(ret != 0)) | ||
| 1584 | return ret; | ||
| 1585 | spin_lock(&bo->lock); | ||
| 1586 | ret = ttm_bo_wait(bo, false, true, no_wait); | ||
| 1587 | spin_unlock(&bo->lock); | ||
| 1588 | if (likely(ret == 0)) | ||
| 1589 | atomic_inc(&bo->cpu_writers); | ||
| 1590 | ttm_bo_unreserve(bo); | ||
| 1591 | return ret; | ||
| 1592 | } | ||
| 1593 | |||
| 1594 | void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo) | ||
| 1595 | { | ||
| 1596 | if (atomic_dec_and_test(&bo->cpu_writers)) | ||
| 1597 | wake_up_all(&bo->event_queue); | ||
| 1598 | } | ||
| 1599 | |||
| 1600 | /** | ||
| 1601 | * A buffer object shrink method that tries to swap out the first | ||
| 1602 | * buffer object on the bo_global::swap_lru list. | ||
| 1603 | */ | ||
| 1604 | |||
| 1605 | static int ttm_bo_swapout(struct ttm_mem_shrink *shrink) | ||
| 1606 | { | ||
| 1607 | struct ttm_bo_device *bdev = | ||
| 1608 | container_of(shrink, struct ttm_bo_device, shrink); | ||
| 1609 | struct ttm_buffer_object *bo; | ||
| 1610 | int ret = -EBUSY; | ||
| 1611 | int put_count; | ||
| 1612 | uint32_t swap_placement = (TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM); | ||
| 1613 | |||
| 1614 | spin_lock(&bdev->lru_lock); | ||
| 1615 | while (ret == -EBUSY) { | ||
| 1616 | if (unlikely(list_empty(&bdev->swap_lru))) { | ||
| 1617 | spin_unlock(&bdev->lru_lock); | ||
| 1618 | return -EBUSY; | ||
| 1619 | } | ||
| 1620 | |||
| 1621 | bo = list_first_entry(&bdev->swap_lru, | ||
| 1622 | struct ttm_buffer_object, swap); | ||
| 1623 | kref_get(&bo->list_kref); | ||
| 1624 | |||
| 1625 | /** | ||
| 1626 | * Reserve buffer. Since we unlock while sleeping, we need | ||
| 1627 | * to re-check that nobody removed us from the swap-list while | ||
| 1628 | * we slept. | ||
| 1629 | */ | ||
| 1630 | |||
| 1631 | ret = ttm_bo_reserve_locked(bo, false, true, false, 0); | ||
| 1632 | if (unlikely(ret == -EBUSY)) { | ||
| 1633 | spin_unlock(&bdev->lru_lock); | ||
| 1634 | ttm_bo_wait_unreserved(bo, false); | ||
| 1635 | kref_put(&bo->list_kref, ttm_bo_release_list); | ||
| 1636 | spin_lock(&bdev->lru_lock); | ||
| 1637 | } | ||
| 1638 | } | ||
| 1639 | |||
| 1640 | BUG_ON(ret != 0); | ||
| 1641 | put_count = ttm_bo_del_from_lru(bo); | ||
| 1642 | spin_unlock(&bdev->lru_lock); | ||
| 1643 | |||
| 1644 | while (put_count--) | ||
| 1645 | kref_put(&bo->list_kref, ttm_bo_ref_bug); | ||
| 1646 | |||
| 1647 | /** | ||
| 1648 | * Wait for GPU, then move to system cached. | ||
| 1649 | */ | ||
| 1650 | |||
| 1651 | spin_lock(&bo->lock); | ||
| 1652 | ret = ttm_bo_wait(bo, false, false, false); | ||
| 1653 | spin_unlock(&bo->lock); | ||
| 1654 | |||
| 1655 | if (unlikely(ret != 0)) | ||
| 1656 | goto out; | ||
| 1657 | |||
| 1658 | if ((bo->mem.placement & swap_placement) != swap_placement) { | ||
| 1659 | struct ttm_mem_reg evict_mem; | ||
| 1660 | |||
| 1661 | evict_mem = bo->mem; | ||
| 1662 | evict_mem.mm_node = NULL; | ||
| 1663 | evict_mem.placement = TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED; | ||
| 1664 | evict_mem.mem_type = TTM_PL_SYSTEM; | ||
| 1665 | |||
| 1666 | ret = ttm_bo_handle_move_mem(bo, &evict_mem, true, | ||
| 1667 | false, false); | ||
| 1668 | if (unlikely(ret != 0)) | ||
| 1669 | goto out; | ||
| 1670 | } | ||
| 1671 | |||
| 1672 | ttm_bo_unmap_virtual(bo); | ||
| 1673 | |||
| 1674 | /** | ||
| 1675 | * Swap out. Buffer will be swapped in again as soon as | ||
| 1676 | * anyone tries to access a ttm page. | ||
| 1677 | */ | ||
| 1678 | |||
| 1679 | ret = ttm_tt_swapout(bo->ttm, bo->persistant_swap_storage); | ||
| 1680 | out: | ||
| 1681 | |||
| 1682 | /** | ||
| 1683 | * | ||
| 1684 | * Unreserve without putting on LRU to avoid swapping out an | ||
| 1685 | * already swapped buffer. | ||
| 1686 | */ | ||
| 1687 | |||
| 1688 | atomic_set(&bo->reserved, 0); | ||
| 1689 | wake_up_all(&bo->event_queue); | ||
| 1690 | kref_put(&bo->list_kref, ttm_bo_release_list); | ||
| 1691 | return ret; | ||
| 1692 | } | ||
| 1693 | |||
| 1694 | void ttm_bo_swapout_all(struct ttm_bo_device *bdev) | ||
| 1695 | { | ||
| 1696 | while (ttm_bo_swapout(&bdev->shrink) == 0) | ||
| 1697 | ; | ||
| 1698 | } | ||
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c new file mode 100644 index 000000000000..517c84559633 --- /dev/null +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c | |||
| @@ -0,0 +1,561 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | **************************************************************************/ | ||
| 27 | /* | ||
| 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include "ttm/ttm_bo_driver.h" | ||
| 32 | #include "ttm/ttm_placement.h" | ||
| 33 | #include <linux/io.h> | ||
| 34 | #include <linux/highmem.h> | ||
| 35 | #include <linux/wait.h> | ||
| 36 | #include <linux/vmalloc.h> | ||
| 37 | #include <linux/version.h> | ||
| 38 | #include <linux/module.h> | ||
| 39 | |||
| 40 | void ttm_bo_free_old_node(struct ttm_buffer_object *bo) | ||
| 41 | { | ||
| 42 | struct ttm_mem_reg *old_mem = &bo->mem; | ||
| 43 | |||
| 44 | if (old_mem->mm_node) { | ||
| 45 | spin_lock(&bo->bdev->lru_lock); | ||
| 46 | drm_mm_put_block(old_mem->mm_node); | ||
| 47 | spin_unlock(&bo->bdev->lru_lock); | ||
| 48 | } | ||
| 49 | old_mem->mm_node = NULL; | ||
| 50 | } | ||
| 51 | |||
| 52 | int ttm_bo_move_ttm(struct ttm_buffer_object *bo, | ||
| 53 | bool evict, bool no_wait, struct ttm_mem_reg *new_mem) | ||
| 54 | { | ||
| 55 | struct ttm_tt *ttm = bo->ttm; | ||
| 56 | struct ttm_mem_reg *old_mem = &bo->mem; | ||
| 57 | uint32_t save_flags = old_mem->placement; | ||
| 58 | int ret; | ||
| 59 | |||
| 60 | if (old_mem->mem_type != TTM_PL_SYSTEM) { | ||
| 61 | ttm_tt_unbind(ttm); | ||
| 62 | ttm_bo_free_old_node(bo); | ||
| 63 | ttm_flag_masked(&old_mem->placement, TTM_PL_FLAG_SYSTEM, | ||
| 64 | TTM_PL_MASK_MEM); | ||
| 65 | old_mem->mem_type = TTM_PL_SYSTEM; | ||
| 66 | save_flags = old_mem->placement; | ||
| 67 | } | ||
| 68 | |||
| 69 | ret = ttm_tt_set_placement_caching(ttm, new_mem->placement); | ||
| 70 | if (unlikely(ret != 0)) | ||
| 71 | return ret; | ||
| 72 | |||
| 73 | if (new_mem->mem_type != TTM_PL_SYSTEM) { | ||
| 74 | ret = ttm_tt_bind(ttm, new_mem); | ||
| 75 | if (unlikely(ret != 0)) | ||
| 76 | return ret; | ||
| 77 | } | ||
| 78 | |||
| 79 | *old_mem = *new_mem; | ||
| 80 | new_mem->mm_node = NULL; | ||
| 81 | ttm_flag_masked(&save_flags, new_mem->placement, TTM_PL_MASK_MEMTYPE); | ||
| 82 | return 0; | ||
| 83 | } | ||
| 84 | EXPORT_SYMBOL(ttm_bo_move_ttm); | ||
| 85 | |||
| 86 | int ttm_mem_reg_ioremap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem, | ||
| 87 | void **virtual) | ||
| 88 | { | ||
| 89 | struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; | ||
| 90 | unsigned long bus_offset; | ||
| 91 | unsigned long bus_size; | ||
| 92 | unsigned long bus_base; | ||
| 93 | int ret; | ||
| 94 | void *addr; | ||
| 95 | |||
| 96 | *virtual = NULL; | ||
| 97 | ret = ttm_bo_pci_offset(bdev, mem, &bus_base, &bus_offset, &bus_size); | ||
| 98 | if (ret || bus_size == 0) | ||
| 99 | return ret; | ||
| 100 | |||
| 101 | if (!(man->flags & TTM_MEMTYPE_FLAG_NEEDS_IOREMAP)) | ||
| 102 | addr = (void *)(((u8 *) man->io_addr) + bus_offset); | ||
| 103 | else { | ||
| 104 | if (mem->placement & TTM_PL_FLAG_WC) | ||
| 105 | addr = ioremap_wc(bus_base + bus_offset, bus_size); | ||
| 106 | else | ||
| 107 | addr = ioremap_nocache(bus_base + bus_offset, bus_size); | ||
| 108 | if (!addr) | ||
| 109 | return -ENOMEM; | ||
| 110 | } | ||
| 111 | *virtual = addr; | ||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | |||
| 115 | void ttm_mem_reg_iounmap(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem, | ||
| 116 | void *virtual) | ||
| 117 | { | ||
| 118 | struct ttm_mem_type_manager *man; | ||
| 119 | |||
| 120 | man = &bdev->man[mem->mem_type]; | ||
| 121 | |||
| 122 | if (virtual && (man->flags & TTM_MEMTYPE_FLAG_NEEDS_IOREMAP)) | ||
| 123 | iounmap(virtual); | ||
| 124 | } | ||
| 125 | |||
| 126 | static int ttm_copy_io_page(void *dst, void *src, unsigned long page) | ||
| 127 | { | ||
| 128 | uint32_t *dstP = | ||
| 129 | (uint32_t *) ((unsigned long)dst + (page << PAGE_SHIFT)); | ||
| 130 | uint32_t *srcP = | ||
| 131 | (uint32_t *) ((unsigned long)src + (page << PAGE_SHIFT)); | ||
| 132 | |||
| 133 | int i; | ||
| 134 | for (i = 0; i < PAGE_SIZE / sizeof(uint32_t); ++i) | ||
| 135 | iowrite32(ioread32(srcP++), dstP++); | ||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src, | ||
| 140 | unsigned long page) | ||
| 141 | { | ||
| 142 | struct page *d = ttm_tt_get_page(ttm, page); | ||
| 143 | void *dst; | ||
| 144 | |||
| 145 | if (!d) | ||
| 146 | return -ENOMEM; | ||
| 147 | |||
| 148 | src = (void *)((unsigned long)src + (page << PAGE_SHIFT)); | ||
| 149 | dst = kmap(d); | ||
| 150 | if (!dst) | ||
| 151 | return -ENOMEM; | ||
| 152 | |||
| 153 | memcpy_fromio(dst, src, PAGE_SIZE); | ||
| 154 | kunmap(d); | ||
| 155 | return 0; | ||
| 156 | } | ||
| 157 | |||
| 158 | static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst, | ||
| 159 | unsigned long page) | ||
| 160 | { | ||
| 161 | struct page *s = ttm_tt_get_page(ttm, page); | ||
| 162 | void *src; | ||
| 163 | |||
| 164 | if (!s) | ||
| 165 | return -ENOMEM; | ||
| 166 | |||
| 167 | dst = (void *)((unsigned long)dst + (page << PAGE_SHIFT)); | ||
| 168 | src = kmap(s); | ||
| 169 | if (!src) | ||
| 170 | return -ENOMEM; | ||
| 171 | |||
| 172 | memcpy_toio(dst, src, PAGE_SIZE); | ||
| 173 | kunmap(s); | ||
| 174 | return 0; | ||
| 175 | } | ||
| 176 | |||
| 177 | int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, | ||
| 178 | bool evict, bool no_wait, struct ttm_mem_reg *new_mem) | ||
| 179 | { | ||
| 180 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 181 | struct ttm_mem_type_manager *man = &bdev->man[new_mem->mem_type]; | ||
| 182 | struct ttm_tt *ttm = bo->ttm; | ||
| 183 | struct ttm_mem_reg *old_mem = &bo->mem; | ||
| 184 | struct ttm_mem_reg old_copy = *old_mem; | ||
| 185 | void *old_iomap; | ||
| 186 | void *new_iomap; | ||
| 187 | int ret; | ||
| 188 | uint32_t save_flags = old_mem->placement; | ||
| 189 | unsigned long i; | ||
| 190 | unsigned long page; | ||
| 191 | unsigned long add = 0; | ||
| 192 | int dir; | ||
| 193 | |||
| 194 | ret = ttm_mem_reg_ioremap(bdev, old_mem, &old_iomap); | ||
| 195 | if (ret) | ||
| 196 | return ret; | ||
| 197 | ret = ttm_mem_reg_ioremap(bdev, new_mem, &new_iomap); | ||
| 198 | if (ret) | ||
| 199 | goto out; | ||
| 200 | |||
| 201 | if (old_iomap == NULL && new_iomap == NULL) | ||
| 202 | goto out2; | ||
| 203 | if (old_iomap == NULL && ttm == NULL) | ||
| 204 | goto out2; | ||
| 205 | |||
| 206 | add = 0; | ||
| 207 | dir = 1; | ||
| 208 | |||
| 209 | if ((old_mem->mem_type == new_mem->mem_type) && | ||
| 210 | (new_mem->mm_node->start < | ||
| 211 | old_mem->mm_node->start + old_mem->mm_node->size)) { | ||
| 212 | dir = -1; | ||
| 213 | add = new_mem->num_pages - 1; | ||
| 214 | } | ||
| 215 | |||
| 216 | for (i = 0; i < new_mem->num_pages; ++i) { | ||
| 217 | page = i * dir + add; | ||
| 218 | if (old_iomap == NULL) | ||
| 219 | ret = ttm_copy_ttm_io_page(ttm, new_iomap, page); | ||
| 220 | else if (new_iomap == NULL) | ||
| 221 | ret = ttm_copy_io_ttm_page(ttm, old_iomap, page); | ||
| 222 | else | ||
| 223 | ret = ttm_copy_io_page(new_iomap, old_iomap, page); | ||
| 224 | if (ret) | ||
| 225 | goto out1; | ||
| 226 | } | ||
| 227 | mb(); | ||
| 228 | out2: | ||
| 229 | ttm_bo_free_old_node(bo); | ||
| 230 | |||
| 231 | *old_mem = *new_mem; | ||
| 232 | new_mem->mm_node = NULL; | ||
| 233 | ttm_flag_masked(&save_flags, new_mem->placement, TTM_PL_MASK_MEMTYPE); | ||
| 234 | |||
| 235 | if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && (ttm != NULL)) { | ||
| 236 | ttm_tt_unbind(ttm); | ||
| 237 | ttm_tt_destroy(ttm); | ||
| 238 | bo->ttm = NULL; | ||
| 239 | } | ||
| 240 | |||
| 241 | out1: | ||
| 242 | ttm_mem_reg_iounmap(bdev, new_mem, new_iomap); | ||
| 243 | out: | ||
| 244 | ttm_mem_reg_iounmap(bdev, &old_copy, old_iomap); | ||
| 245 | return ret; | ||
| 246 | } | ||
| 247 | EXPORT_SYMBOL(ttm_bo_move_memcpy); | ||
| 248 | |||
| 249 | static void ttm_transfered_destroy(struct ttm_buffer_object *bo) | ||
| 250 | { | ||
| 251 | kfree(bo); | ||
| 252 | } | ||
| 253 | |||
| 254 | /** | ||
| 255 | * ttm_buffer_object_transfer | ||
| 256 | * | ||
| 257 | * @bo: A pointer to a struct ttm_buffer_object. | ||
| 258 | * @new_obj: A pointer to a pointer to a newly created ttm_buffer_object, | ||
| 259 | * holding the data of @bo with the old placement. | ||
| 260 | * | ||
| 261 | * This is a utility function that may be called after an accelerated move | ||
| 262 | * has been scheduled. A new buffer object is created as a placeholder for | ||
| 263 | * the old data while it's being copied. When that buffer object is idle, | ||
| 264 | * it can be destroyed, releasing the space of the old placement. | ||
| 265 | * Returns: | ||
| 266 | * !0: Failure. | ||
| 267 | */ | ||
| 268 | |||
| 269 | static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, | ||
| 270 | struct ttm_buffer_object **new_obj) | ||
| 271 | { | ||
| 272 | struct ttm_buffer_object *fbo; | ||
| 273 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 274 | struct ttm_bo_driver *driver = bdev->driver; | ||
| 275 | |||
| 276 | fbo = kzalloc(sizeof(*fbo), GFP_KERNEL); | ||
| 277 | if (!fbo) | ||
| 278 | return -ENOMEM; | ||
| 279 | |||
| 280 | *fbo = *bo; | ||
| 281 | |||
| 282 | /** | ||
| 283 | * Fix up members that we shouldn't copy directly: | ||
| 284 | * TODO: Explicit member copy would probably be better here. | ||
| 285 | */ | ||
| 286 | |||
| 287 | spin_lock_init(&fbo->lock); | ||
| 288 | init_waitqueue_head(&fbo->event_queue); | ||
| 289 | INIT_LIST_HEAD(&fbo->ddestroy); | ||
| 290 | INIT_LIST_HEAD(&fbo->lru); | ||
| 291 | INIT_LIST_HEAD(&fbo->swap); | ||
| 292 | fbo->vm_node = NULL; | ||
| 293 | |||
| 294 | fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj); | ||
| 295 | if (fbo->mem.mm_node) | ||
| 296 | fbo->mem.mm_node->private = (void *)fbo; | ||
| 297 | kref_init(&fbo->list_kref); | ||
| 298 | kref_init(&fbo->kref); | ||
| 299 | fbo->destroy = &ttm_transfered_destroy; | ||
| 300 | |||
| 301 | *new_obj = fbo; | ||
| 302 | return 0; | ||
| 303 | } | ||
| 304 | |||
| 305 | pgprot_t ttm_io_prot(uint32_t caching_flags, pgprot_t tmp) | ||
| 306 | { | ||
| 307 | #if defined(__i386__) || defined(__x86_64__) | ||
| 308 | if (caching_flags & TTM_PL_FLAG_WC) | ||
| 309 | tmp = pgprot_writecombine(tmp); | ||
| 310 | else if (boot_cpu_data.x86 > 3) | ||
| 311 | tmp = pgprot_noncached(tmp); | ||
| 312 | |||
| 313 | #elif defined(__powerpc__) | ||
| 314 | if (!(caching_flags & TTM_PL_FLAG_CACHED)) { | ||
| 315 | pgprot_val(tmp) |= _PAGE_NO_CACHE; | ||
| 316 | if (caching_flags & TTM_PL_FLAG_UNCACHED) | ||
| 317 | pgprot_val(tmp) |= _PAGE_GUARDED; | ||
| 318 | } | ||
| 319 | #endif | ||
| 320 | #if defined(__ia64__) | ||
| 321 | if (caching_flags & TTM_PL_FLAG_WC) | ||
| 322 | tmp = pgprot_writecombine(tmp); | ||
| 323 | else | ||
| 324 | tmp = pgprot_noncached(tmp); | ||
| 325 | #endif | ||
| 326 | #if defined(__sparc__) | ||
| 327 | if (!(caching_flags & TTM_PL_FLAG_CACHED)) | ||
| 328 | tmp = pgprot_noncached(tmp); | ||
| 329 | #endif | ||
| 330 | return tmp; | ||
| 331 | } | ||
| 332 | |||
| 333 | static int ttm_bo_ioremap(struct ttm_buffer_object *bo, | ||
| 334 | unsigned long bus_base, | ||
| 335 | unsigned long bus_offset, | ||
| 336 | unsigned long bus_size, | ||
| 337 | struct ttm_bo_kmap_obj *map) | ||
| 338 | { | ||
| 339 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 340 | struct ttm_mem_reg *mem = &bo->mem; | ||
| 341 | struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; | ||
| 342 | |||
| 343 | if (!(man->flags & TTM_MEMTYPE_FLAG_NEEDS_IOREMAP)) { | ||
| 344 | map->bo_kmap_type = ttm_bo_map_premapped; | ||
| 345 | map->virtual = (void *)(((u8 *) man->io_addr) + bus_offset); | ||
| 346 | } else { | ||
| 347 | map->bo_kmap_type = ttm_bo_map_iomap; | ||
| 348 | if (mem->placement & TTM_PL_FLAG_WC) | ||
| 349 | map->virtual = ioremap_wc(bus_base + bus_offset, | ||
| 350 | bus_size); | ||
| 351 | else | ||
| 352 | map->virtual = ioremap_nocache(bus_base + bus_offset, | ||
| 353 | bus_size); | ||
| 354 | } | ||
| 355 | return (!map->virtual) ? -ENOMEM : 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, | ||
| 359 | unsigned long start_page, | ||
| 360 | unsigned long num_pages, | ||
| 361 | struct ttm_bo_kmap_obj *map) | ||
| 362 | { | ||
| 363 | struct ttm_mem_reg *mem = &bo->mem; pgprot_t prot; | ||
| 364 | struct ttm_tt *ttm = bo->ttm; | ||
| 365 | struct page *d; | ||
| 366 | int i; | ||
| 367 | |||
| 368 | BUG_ON(!ttm); | ||
| 369 | if (num_pages == 1 && (mem->placement & TTM_PL_FLAG_CACHED)) { | ||
| 370 | /* | ||
| 371 | * We're mapping a single page, and the desired | ||
| 372 | * page protection is consistent with the bo. | ||
| 373 | */ | ||
| 374 | |||
| 375 | map->bo_kmap_type = ttm_bo_map_kmap; | ||
| 376 | map->page = ttm_tt_get_page(ttm, start_page); | ||
| 377 | map->virtual = kmap(map->page); | ||
| 378 | } else { | ||
| 379 | /* | ||
| 380 | * Populate the part we're mapping; | ||
| 381 | */ | ||
| 382 | for (i = start_page; i < start_page + num_pages; ++i) { | ||
| 383 | d = ttm_tt_get_page(ttm, i); | ||
| 384 | if (!d) | ||
| 385 | return -ENOMEM; | ||
| 386 | } | ||
| 387 | |||
| 388 | /* | ||
| 389 | * We need to use vmap to get the desired page protection | ||
| 390 | * or to make the buffer object look contigous. | ||
| 391 | */ | ||
| 392 | prot = (mem->placement & TTM_PL_FLAG_CACHED) ? | ||
| 393 | PAGE_KERNEL : | ||
| 394 | ttm_io_prot(mem->placement, PAGE_KERNEL); | ||
| 395 | map->bo_kmap_type = ttm_bo_map_vmap; | ||
| 396 | map->virtual = vmap(ttm->pages + start_page, num_pages, | ||
| 397 | 0, prot); | ||
| 398 | } | ||
| 399 | return (!map->virtual) ? -ENOMEM : 0; | ||
| 400 | } | ||
| 401 | |||
| 402 | int ttm_bo_kmap(struct ttm_buffer_object *bo, | ||
| 403 | unsigned long start_page, unsigned long num_pages, | ||
| 404 | struct ttm_bo_kmap_obj *map) | ||
| 405 | { | ||
| 406 | int ret; | ||
| 407 | unsigned long bus_base; | ||
| 408 | unsigned long bus_offset; | ||
| 409 | unsigned long bus_size; | ||
| 410 | |||
| 411 | BUG_ON(!list_empty(&bo->swap)); | ||
| 412 | map->virtual = NULL; | ||
| 413 | if (num_pages > bo->num_pages) | ||
| 414 | return -EINVAL; | ||
| 415 | if (start_page > bo->num_pages) | ||
| 416 | return -EINVAL; | ||
| 417 | #if 0 | ||
| 418 | if (num_pages > 1 && !DRM_SUSER(DRM_CURPROC)) | ||
| 419 | return -EPERM; | ||
| 420 | #endif | ||
| 421 | ret = ttm_bo_pci_offset(bo->bdev, &bo->mem, &bus_base, | ||
| 422 | &bus_offset, &bus_size); | ||
| 423 | if (ret) | ||
| 424 | return ret; | ||
| 425 | if (bus_size == 0) { | ||
| 426 | return ttm_bo_kmap_ttm(bo, start_page, num_pages, map); | ||
| 427 | } else { | ||
| 428 | bus_offset += start_page << PAGE_SHIFT; | ||
| 429 | bus_size = num_pages << PAGE_SHIFT; | ||
| 430 | return ttm_bo_ioremap(bo, bus_base, bus_offset, bus_size, map); | ||
| 431 | } | ||
| 432 | } | ||
| 433 | EXPORT_SYMBOL(ttm_bo_kmap); | ||
| 434 | |||
| 435 | void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map) | ||
| 436 | { | ||
| 437 | if (!map->virtual) | ||
| 438 | return; | ||
| 439 | switch (map->bo_kmap_type) { | ||
| 440 | case ttm_bo_map_iomap: | ||
| 441 | iounmap(map->virtual); | ||
| 442 | break; | ||
| 443 | case ttm_bo_map_vmap: | ||
| 444 | vunmap(map->virtual); | ||
| 445 | break; | ||
| 446 | case ttm_bo_map_kmap: | ||
| 447 | kunmap(map->page); | ||
| 448 | break; | ||
| 449 | case ttm_bo_map_premapped: | ||
| 450 | break; | ||
| 451 | default: | ||
| 452 | BUG(); | ||
| 453 | } | ||
| 454 | map->virtual = NULL; | ||
| 455 | map->page = NULL; | ||
| 456 | } | ||
| 457 | EXPORT_SYMBOL(ttm_bo_kunmap); | ||
| 458 | |||
| 459 | int ttm_bo_pfn_prot(struct ttm_buffer_object *bo, | ||
| 460 | unsigned long dst_offset, | ||
| 461 | unsigned long *pfn, pgprot_t *prot) | ||
| 462 | { | ||
| 463 | struct ttm_mem_reg *mem = &bo->mem; | ||
| 464 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 465 | unsigned long bus_offset; | ||
| 466 | unsigned long bus_size; | ||
| 467 | unsigned long bus_base; | ||
| 468 | int ret; | ||
| 469 | ret = ttm_bo_pci_offset(bdev, mem, &bus_base, &bus_offset, | ||
| 470 | &bus_size); | ||
| 471 | if (ret) | ||
| 472 | return -EINVAL; | ||
| 473 | if (bus_size != 0) | ||
| 474 | *pfn = (bus_base + bus_offset + dst_offset) >> PAGE_SHIFT; | ||
| 475 | else | ||
| 476 | if (!bo->ttm) | ||
| 477 | return -EINVAL; | ||
| 478 | else | ||
| 479 | *pfn = page_to_pfn(ttm_tt_get_page(bo->ttm, | ||
| 480 | dst_offset >> | ||
| 481 | PAGE_SHIFT)); | ||
| 482 | *prot = (mem->placement & TTM_PL_FLAG_CACHED) ? | ||
| 483 | PAGE_KERNEL : ttm_io_prot(mem->placement, PAGE_KERNEL); | ||
| 484 | |||
| 485 | return 0; | ||
| 486 | } | ||
| 487 | |||
| 488 | int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, | ||
| 489 | void *sync_obj, | ||
| 490 | void *sync_obj_arg, | ||
| 491 | bool evict, bool no_wait, | ||
| 492 | struct ttm_mem_reg *new_mem) | ||
| 493 | { | ||
| 494 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 495 | struct ttm_bo_driver *driver = bdev->driver; | ||
| 496 | struct ttm_mem_type_manager *man = &bdev->man[new_mem->mem_type]; | ||
| 497 | struct ttm_mem_reg *old_mem = &bo->mem; | ||
| 498 | int ret; | ||
| 499 | uint32_t save_flags = old_mem->placement; | ||
| 500 | struct ttm_buffer_object *ghost_obj; | ||
| 501 | void *tmp_obj = NULL; | ||
| 502 | |||
| 503 | spin_lock(&bo->lock); | ||
| 504 | if (bo->sync_obj) { | ||
| 505 | tmp_obj = bo->sync_obj; | ||
| 506 | bo->sync_obj = NULL; | ||
| 507 | } | ||
| 508 | bo->sync_obj = driver->sync_obj_ref(sync_obj); | ||
| 509 | bo->sync_obj_arg = sync_obj_arg; | ||
| 510 | if (evict) { | ||
| 511 | ret = ttm_bo_wait(bo, false, false, false); | ||
| 512 | spin_unlock(&bo->lock); | ||
| 513 | driver->sync_obj_unref(&bo->sync_obj); | ||
| 514 | |||
| 515 | if (ret) | ||
| 516 | return ret; | ||
| 517 | |||
| 518 | ttm_bo_free_old_node(bo); | ||
| 519 | if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) && | ||
| 520 | (bo->ttm != NULL)) { | ||
| 521 | ttm_tt_unbind(bo->ttm); | ||
| 522 | ttm_tt_destroy(bo->ttm); | ||
| 523 | bo->ttm = NULL; | ||
| 524 | } | ||
| 525 | } else { | ||
| 526 | /** | ||
| 527 | * This should help pipeline ordinary buffer moves. | ||
| 528 | * | ||
| 529 | * Hang old buffer memory on a new buffer object, | ||
| 530 | * and leave it to be released when the GPU | ||
| 531 | * operation has completed. | ||
| 532 | */ | ||
| 533 | |||
| 534 | set_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags); | ||
| 535 | spin_unlock(&bo->lock); | ||
| 536 | |||
| 537 | ret = ttm_buffer_object_transfer(bo, &ghost_obj); | ||
| 538 | if (ret) | ||
| 539 | return ret; | ||
| 540 | |||
| 541 | /** | ||
| 542 | * If we're not moving to fixed memory, the TTM object | ||
| 543 | * needs to stay alive. Otherwhise hang it on the ghost | ||
| 544 | * bo to be unbound and destroyed. | ||
| 545 | */ | ||
| 546 | |||
| 547 | if (!(man->flags & TTM_MEMTYPE_FLAG_FIXED)) | ||
| 548 | ghost_obj->ttm = NULL; | ||
| 549 | else | ||
| 550 | bo->ttm = NULL; | ||
| 551 | |||
| 552 | ttm_bo_unreserve(ghost_obj); | ||
| 553 | ttm_bo_unref(&ghost_obj); | ||
| 554 | } | ||
| 555 | |||
| 556 | *old_mem = *new_mem; | ||
| 557 | new_mem->mm_node = NULL; | ||
| 558 | ttm_flag_masked(&save_flags, new_mem->placement, TTM_PL_MASK_MEMTYPE); | ||
| 559 | return 0; | ||
| 560 | } | ||
| 561 | EXPORT_SYMBOL(ttm_bo_move_accel_cleanup); | ||
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c new file mode 100644 index 000000000000..27b146c54fbc --- /dev/null +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c | |||
| @@ -0,0 +1,454 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | **************************************************************************/ | ||
| 27 | /* | ||
| 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include <ttm/ttm_module.h> | ||
| 32 | #include <ttm/ttm_bo_driver.h> | ||
| 33 | #include <ttm/ttm_placement.h> | ||
| 34 | #include <linux/mm.h> | ||
| 35 | #include <linux/version.h> | ||
| 36 | #include <linux/rbtree.h> | ||
| 37 | #include <linux/module.h> | ||
| 38 | #include <linux/uaccess.h> | ||
| 39 | |||
| 40 | #define TTM_BO_VM_NUM_PREFAULT 16 | ||
| 41 | |||
| 42 | static struct ttm_buffer_object *ttm_bo_vm_lookup_rb(struct ttm_bo_device *bdev, | ||
| 43 | unsigned long page_start, | ||
| 44 | unsigned long num_pages) | ||
| 45 | { | ||
| 46 | struct rb_node *cur = bdev->addr_space_rb.rb_node; | ||
| 47 | unsigned long cur_offset; | ||
| 48 | struct ttm_buffer_object *bo; | ||
| 49 | struct ttm_buffer_object *best_bo = NULL; | ||
| 50 | |||
| 51 | while (likely(cur != NULL)) { | ||
| 52 | bo = rb_entry(cur, struct ttm_buffer_object, vm_rb); | ||
| 53 | cur_offset = bo->vm_node->start; | ||
| 54 | if (page_start >= cur_offset) { | ||
| 55 | cur = cur->rb_right; | ||
| 56 | best_bo = bo; | ||
| 57 | if (page_start == cur_offset) | ||
| 58 | break; | ||
| 59 | } else | ||
| 60 | cur = cur->rb_left; | ||
| 61 | } | ||
| 62 | |||
| 63 | if (unlikely(best_bo == NULL)) | ||
| 64 | return NULL; | ||
| 65 | |||
| 66 | if (unlikely((best_bo->vm_node->start + best_bo->num_pages) < | ||
| 67 | (page_start + num_pages))) | ||
| 68 | return NULL; | ||
| 69 | |||
| 70 | return best_bo; | ||
| 71 | } | ||
| 72 | |||
| 73 | static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | ||
| 74 | { | ||
| 75 | struct ttm_buffer_object *bo = (struct ttm_buffer_object *) | ||
| 76 | vma->vm_private_data; | ||
| 77 | struct ttm_bo_device *bdev = bo->bdev; | ||
| 78 | unsigned long bus_base; | ||
| 79 | unsigned long bus_offset; | ||
| 80 | unsigned long bus_size; | ||
| 81 | unsigned long page_offset; | ||
| 82 | unsigned long page_last; | ||
| 83 | unsigned long pfn; | ||
| 84 | struct ttm_tt *ttm = NULL; | ||
| 85 | struct page *page; | ||
| 86 | int ret; | ||
| 87 | int i; | ||
| 88 | bool is_iomem; | ||
| 89 | unsigned long address = (unsigned long)vmf->virtual_address; | ||
| 90 | int retval = VM_FAULT_NOPAGE; | ||
| 91 | |||
| 92 | /* | ||
| 93 | * Work around locking order reversal in fault / nopfn | ||
| 94 | * between mmap_sem and bo_reserve: Perform a trylock operation | ||
| 95 | * for reserve, and if it fails, retry the fault after scheduling. | ||
| 96 | */ | ||
| 97 | |||
| 98 | ret = ttm_bo_reserve(bo, true, true, false, 0); | ||
| 99 | if (unlikely(ret != 0)) { | ||
| 100 | if (ret == -EBUSY) | ||
| 101 | set_need_resched(); | ||
| 102 | return VM_FAULT_NOPAGE; | ||
| 103 | } | ||
| 104 | |||
| 105 | /* | ||
| 106 | * Wait for buffer data in transit, due to a pipelined | ||
| 107 | * move. | ||
| 108 | */ | ||
| 109 | |||
| 110 | spin_lock(&bo->lock); | ||
| 111 | if (test_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags)) { | ||
| 112 | ret = ttm_bo_wait(bo, false, true, false); | ||
| 113 | spin_unlock(&bo->lock); | ||
| 114 | if (unlikely(ret != 0)) { | ||
| 115 | retval = (ret != -ERESTART) ? | ||
| 116 | VM_FAULT_SIGBUS : VM_FAULT_NOPAGE; | ||
| 117 | goto out_unlock; | ||
| 118 | } | ||
| 119 | } else | ||
| 120 | spin_unlock(&bo->lock); | ||
| 121 | |||
| 122 | |||
| 123 | ret = ttm_bo_pci_offset(bdev, &bo->mem, &bus_base, &bus_offset, | ||
| 124 | &bus_size); | ||
| 125 | if (unlikely(ret != 0)) { | ||
| 126 | retval = VM_FAULT_SIGBUS; | ||
| 127 | goto out_unlock; | ||
| 128 | } | ||
| 129 | |||
| 130 | is_iomem = (bus_size != 0); | ||
| 131 | |||
| 132 | page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) + | ||
| 133 | bo->vm_node->start - vma->vm_pgoff; | ||
| 134 | page_last = ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) + | ||
| 135 | bo->vm_node->start - vma->vm_pgoff; | ||
| 136 | |||
| 137 | if (unlikely(page_offset >= bo->num_pages)) { | ||
| 138 | retval = VM_FAULT_SIGBUS; | ||
| 139 | goto out_unlock; | ||
| 140 | } | ||
| 141 | |||
| 142 | /* | ||
| 143 | * Strictly, we're not allowed to modify vma->vm_page_prot here, | ||
| 144 | * since the mmap_sem is only held in read mode. However, we | ||
| 145 | * modify only the caching bits of vma->vm_page_prot and | ||
| 146 | * consider those bits protected by | ||
| 147 | * the bo->mutex, as we should be the only writers. | ||
| 148 | * There shouldn't really be any readers of these bits except | ||
| 149 | * within vm_insert_mixed()? fork? | ||
| 150 | * | ||
| 151 | * TODO: Add a list of vmas to the bo, and change the | ||
| 152 | * vma->vm_page_prot when the object changes caching policy, with | ||
| 153 | * the correct locks held. | ||
| 154 | */ | ||
| 155 | |||
| 156 | if (is_iomem) { | ||
| 157 | vma->vm_page_prot = ttm_io_prot(bo->mem.placement, | ||
| 158 | vma->vm_page_prot); | ||
| 159 | } else { | ||
| 160 | ttm = bo->ttm; | ||
| 161 | vma->vm_page_prot = (bo->mem.placement & TTM_PL_FLAG_CACHED) ? | ||
| 162 | vm_get_page_prot(vma->vm_flags) : | ||
| 163 | ttm_io_prot(bo->mem.placement, vma->vm_page_prot); | ||
| 164 | } | ||
| 165 | |||
| 166 | /* | ||
| 167 | * Speculatively prefault a number of pages. Only error on | ||
| 168 | * first page. | ||
| 169 | */ | ||
| 170 | |||
| 171 | for (i = 0; i < TTM_BO_VM_NUM_PREFAULT; ++i) { | ||
| 172 | |||
| 173 | if (is_iomem) | ||
| 174 | pfn = ((bus_base + bus_offset) >> PAGE_SHIFT) + | ||
| 175 | page_offset; | ||
| 176 | else { | ||
| 177 | page = ttm_tt_get_page(ttm, page_offset); | ||
| 178 | if (unlikely(!page && i == 0)) { | ||
| 179 | retval = VM_FAULT_OOM; | ||
| 180 | goto out_unlock; | ||
| 181 | } else if (unlikely(!page)) { | ||
| 182 | break; | ||
| 183 | } | ||
| 184 | pfn = page_to_pfn(page); | ||
| 185 | } | ||
| 186 | |||
| 187 | ret = vm_insert_mixed(vma, address, pfn); | ||
| 188 | /* | ||
| 189 | * Somebody beat us to this PTE or prefaulting to | ||
| 190 | * an already populated PTE, or prefaulting error. | ||
| 191 | */ | ||
| 192 | |||
| 193 | if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0))) | ||
| 194 | break; | ||
| 195 | else if (unlikely(ret != 0)) { | ||
| 196 | retval = | ||
| 197 | (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS; | ||
| 198 | goto out_unlock; | ||
| 199 | |||
| 200 | } | ||
| 201 | |||
| 202 | address += PAGE_SIZE; | ||
| 203 | if (unlikely(++page_offset >= page_last)) | ||
| 204 | break; | ||
| 205 | } | ||
| 206 | |||
| 207 | out_unlock: | ||
| 208 | ttm_bo_unreserve(bo); | ||
| 209 | return retval; | ||
| 210 | } | ||
| 211 | |||
| 212 | static void ttm_bo_vm_open(struct vm_area_struct *vma) | ||
| 213 | { | ||
| 214 | struct ttm_buffer_object *bo = | ||
| 215 | (struct ttm_buffer_object *)vma->vm_private_data; | ||
| 216 | |||
| 217 | (void)ttm_bo_reference(bo); | ||
| 218 | } | ||
| 219 | |||
| 220 | static void ttm_bo_vm_close(struct vm_area_struct *vma) | ||
| 221 | { | ||
| 222 | struct ttm_buffer_object *bo = | ||
| 223 | (struct ttm_buffer_object *)vma->vm_private_data; | ||
| 224 | |||
| 225 | ttm_bo_unref(&bo); | ||
| 226 | vma->vm_private_data = NULL; | ||
| 227 | } | ||
| 228 | |||
| 229 | static struct vm_operations_struct ttm_bo_vm_ops = { | ||
| 230 | .fault = ttm_bo_vm_fault, | ||
| 231 | .open = ttm_bo_vm_open, | ||
| 232 | .close = ttm_bo_vm_close | ||
| 233 | }; | ||
| 234 | |||
| 235 | int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma, | ||
| 236 | struct ttm_bo_device *bdev) | ||
| 237 | { | ||
| 238 | struct ttm_bo_driver *driver; | ||
| 239 | struct ttm_buffer_object *bo; | ||
| 240 | int ret; | ||
| 241 | |||
| 242 | read_lock(&bdev->vm_lock); | ||
| 243 | bo = ttm_bo_vm_lookup_rb(bdev, vma->vm_pgoff, | ||
| 244 | (vma->vm_end - vma->vm_start) >> PAGE_SHIFT); | ||
| 245 | if (likely(bo != NULL)) | ||
| 246 | ttm_bo_reference(bo); | ||
| 247 | read_unlock(&bdev->vm_lock); | ||
| 248 | |||
| 249 | if (unlikely(bo == NULL)) { | ||
| 250 | printk(KERN_ERR TTM_PFX | ||
| 251 | "Could not find buffer object to map.\n"); | ||
| 252 | return -EINVAL; | ||
| 253 | } | ||
| 254 | |||
| 255 | driver = bo->bdev->driver; | ||
| 256 | if (unlikely(!driver->verify_access)) { | ||
| 257 | ret = -EPERM; | ||
| 258 | goto out_unref; | ||
| 259 | } | ||
| 260 | ret = driver->verify_access(bo, filp); | ||
| 261 | if (unlikely(ret != 0)) | ||
| 262 | goto out_unref; | ||
| 263 | |||
| 264 | vma->vm_ops = &ttm_bo_vm_ops; | ||
| 265 | |||
| 266 | /* | ||
| 267 | * Note: We're transferring the bo reference to | ||
| 268 | * vma->vm_private_data here. | ||
| 269 | */ | ||
| 270 | |||
| 271 | vma->vm_private_data = bo; | ||
| 272 | vma->vm_flags |= VM_RESERVED | VM_IO | VM_MIXEDMAP | VM_DONTEXPAND; | ||
| 273 | return 0; | ||
| 274 | out_unref: | ||
| 275 | ttm_bo_unref(&bo); | ||
| 276 | return ret; | ||
| 277 | } | ||
| 278 | EXPORT_SYMBOL(ttm_bo_mmap); | ||
| 279 | |||
| 280 | int ttm_fbdev_mmap(struct vm_area_struct *vma, struct ttm_buffer_object *bo) | ||
| 281 | { | ||
| 282 | if (vma->vm_pgoff != 0) | ||
| 283 | return -EACCES; | ||
| 284 | |||
| 285 | vma->vm_ops = &ttm_bo_vm_ops; | ||
| 286 | vma->vm_private_data = ttm_bo_reference(bo); | ||
| 287 | vma->vm_flags |= VM_RESERVED | VM_IO | VM_MIXEDMAP | VM_DONTEXPAND; | ||
| 288 | return 0; | ||
| 289 | } | ||
| 290 | EXPORT_SYMBOL(ttm_fbdev_mmap); | ||
| 291 | |||
| 292 | |||
| 293 | ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp, | ||
| 294 | const char __user *wbuf, char __user *rbuf, size_t count, | ||
| 295 | loff_t *f_pos, bool write) | ||
| 296 | { | ||
| 297 | struct ttm_buffer_object *bo; | ||
| 298 | struct ttm_bo_driver *driver; | ||
| 299 | struct ttm_bo_kmap_obj map; | ||
| 300 | unsigned long dev_offset = (*f_pos >> PAGE_SHIFT); | ||
| 301 | unsigned long kmap_offset; | ||
| 302 | unsigned long kmap_end; | ||
| 303 | unsigned long kmap_num; | ||
| 304 | size_t io_size; | ||
| 305 | unsigned int page_offset; | ||
| 306 | char *virtual; | ||
| 307 | int ret; | ||
| 308 | bool no_wait = false; | ||
| 309 | bool dummy; | ||
| 310 | |||
| 311 | read_lock(&bdev->vm_lock); | ||
| 312 | bo = ttm_bo_vm_lookup_rb(bdev, dev_offset, 1); | ||
| 313 | if (likely(bo != NULL)) | ||
| 314 | ttm_bo_reference(bo); | ||
| 315 | read_unlock(&bdev->vm_lock); | ||
| 316 | |||
| 317 | if (unlikely(bo == NULL)) | ||
| 318 | return -EFAULT; | ||
| 319 | |||
| 320 | driver = bo->bdev->driver; | ||
| 321 | if (unlikely(driver->verify_access)) { | ||
| 322 | ret = -EPERM; | ||
| 323 | goto out_unref; | ||
| 324 | } | ||
| 325 | |||
| 326 | ret = driver->verify_access(bo, filp); | ||
| 327 | if (unlikely(ret != 0)) | ||
| 328 | goto out_unref; | ||
| 329 | |||
| 330 | kmap_offset = dev_offset - bo->vm_node->start; | ||
| 331 | if (unlikely(kmap_offset) >= bo->num_pages) { | ||
| 332 | ret = -EFBIG; | ||
| 333 | goto out_unref; | ||
| 334 | } | ||
| 335 | |||
| 336 | page_offset = *f_pos & ~PAGE_MASK; | ||
| 337 | io_size = bo->num_pages - kmap_offset; | ||
| 338 | io_size = (io_size << PAGE_SHIFT) - page_offset; | ||
| 339 | if (count < io_size) | ||
| 340 | io_size = count; | ||
| 341 | |||
| 342 | kmap_end = (*f_pos + count - 1) >> PAGE_SHIFT; | ||
| 343 | kmap_num = kmap_end - kmap_offset + 1; | ||
| 344 | |||
| 345 | ret = ttm_bo_reserve(bo, true, no_wait, false, 0); | ||
| 346 | |||
| 347 | switch (ret) { | ||
| 348 | case 0: | ||
| 349 | break; | ||
| 350 | case -ERESTART: | ||
| 351 | ret = -EINTR; | ||
| 352 | goto out_unref; | ||
| 353 | case -EBUSY: | ||
| 354 | ret = -EAGAIN; | ||
| 355 | goto out_unref; | ||
| 356 | default: | ||
| 357 | goto out_unref; | ||
| 358 | } | ||
| 359 | |||
| 360 | ret = ttm_bo_kmap(bo, kmap_offset, kmap_num, &map); | ||
| 361 | if (unlikely(ret != 0)) { | ||
| 362 | ttm_bo_unreserve(bo); | ||
| 363 | goto out_unref; | ||
| 364 | } | ||
| 365 | |||
| 366 | virtual = ttm_kmap_obj_virtual(&map, &dummy); | ||
| 367 | virtual += page_offset; | ||
| 368 | |||
| 369 | if (write) | ||
| 370 | ret = copy_from_user(virtual, wbuf, io_size); | ||
| 371 | else | ||
| 372 | ret = copy_to_user(rbuf, virtual, io_size); | ||
| 373 | |||
| 374 | ttm_bo_kunmap(&map); | ||
| 375 | ttm_bo_unreserve(bo); | ||
| 376 | ttm_bo_unref(&bo); | ||
| 377 | |||
| 378 | if (unlikely(ret != 0)) | ||
| 379 | return -EFBIG; | ||
| 380 | |||
| 381 | *f_pos += io_size; | ||
| 382 | |||
| 383 | return io_size; | ||
| 384 | out_unref: | ||
| 385 | ttm_bo_unref(&bo); | ||
| 386 | return ret; | ||
| 387 | } | ||
| 388 | |||
| 389 | ssize_t ttm_bo_fbdev_io(struct ttm_buffer_object *bo, const char __user *wbuf, | ||
| 390 | char __user *rbuf, size_t count, loff_t *f_pos, | ||
| 391 | bool write) | ||
| 392 | { | ||
| 393 | struct ttm_bo_kmap_obj map; | ||
| 394 | unsigned long kmap_offset; | ||
| 395 | unsigned long kmap_end; | ||
| 396 | unsigned long kmap_num; | ||
| 397 | size_t io_size; | ||
| 398 | unsigned int page_offset; | ||
| 399 | char *virtual; | ||
| 400 | int ret; | ||
| 401 | bool no_wait = false; | ||
| 402 | bool dummy; | ||
| 403 | |||
| 404 | kmap_offset = (*f_pos >> PAGE_SHIFT); | ||
| 405 | if (unlikely(kmap_offset) >= bo->num_pages) | ||
| 406 | return -EFBIG; | ||
| 407 | |||
| 408 | page_offset = *f_pos & ~PAGE_MASK; | ||
| 409 | io_size = bo->num_pages - kmap_offset; | ||
| 410 | io_size = (io_size << PAGE_SHIFT) - page_offset; | ||
| 411 | if (count < io_size) | ||
| 412 | io_size = count; | ||
| 413 | |||
| 414 | kmap_end = (*f_pos + count - 1) >> PAGE_SHIFT; | ||
| 415 | kmap_num = kmap_end - kmap_offset + 1; | ||
| 416 | |||
| 417 | ret = ttm_bo_reserve(bo, true, no_wait, false, 0); | ||
| 418 | |||
| 419 | switch (ret) { | ||
| 420 | case 0: | ||
| 421 | break; | ||
| 422 | case -ERESTART: | ||
| 423 | return -EINTR; | ||
| 424 | case -EBUSY: | ||
| 425 | return -EAGAIN; | ||
| 426 | default: | ||
| 427 | return ret; | ||
| 428 | } | ||
| 429 | |||
| 430 | ret = ttm_bo_kmap(bo, kmap_offset, kmap_num, &map); | ||
| 431 | if (unlikely(ret != 0)) { | ||
| 432 | ttm_bo_unreserve(bo); | ||
| 433 | return ret; | ||
| 434 | } | ||
| 435 | |||
| 436 | virtual = ttm_kmap_obj_virtual(&map, &dummy); | ||
| 437 | virtual += page_offset; | ||
| 438 | |||
| 439 | if (write) | ||
| 440 | ret = copy_from_user(virtual, wbuf, io_size); | ||
| 441 | else | ||
| 442 | ret = copy_to_user(rbuf, virtual, io_size); | ||
| 443 | |||
| 444 | ttm_bo_kunmap(&map); | ||
| 445 | ttm_bo_unreserve(bo); | ||
| 446 | ttm_bo_unref(&bo); | ||
| 447 | |||
| 448 | if (unlikely(ret != 0)) | ||
| 449 | return ret; | ||
| 450 | |||
| 451 | *f_pos += io_size; | ||
| 452 | |||
| 453 | return io_size; | ||
| 454 | } | ||
diff --git a/drivers/gpu/drm/ttm/ttm_global.c b/drivers/gpu/drm/ttm/ttm_global.c new file mode 100644 index 000000000000..0b14eb1972b8 --- /dev/null +++ b/drivers/gpu/drm/ttm/ttm_global.c | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright 2008-2009 VMware, Inc., Palo Alto, CA., USA | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | **************************************************************************/ | ||
| 27 | /* | ||
| 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include "ttm/ttm_module.h" | ||
| 32 | #include <linux/mutex.h> | ||
| 33 | #include <linux/slab.h> | ||
| 34 | #include <linux/module.h> | ||
| 35 | |||
| 36 | struct ttm_global_item { | ||
| 37 | struct mutex mutex; | ||
| 38 | void *object; | ||
| 39 | int refcount; | ||
| 40 | }; | ||
| 41 | |||
| 42 | static struct ttm_global_item glob[TTM_GLOBAL_NUM]; | ||
| 43 | |||
| 44 | void ttm_global_init(void) | ||
| 45 | { | ||
| 46 | int i; | ||
| 47 | |||
| 48 | for (i = 0; i < TTM_GLOBAL_NUM; ++i) { | ||
| 49 | struct ttm_global_item *item = &glob[i]; | ||
| 50 | mutex_init(&item->mutex); | ||
| 51 | item->object = NULL; | ||
| 52 | item->refcount = 0; | ||
| 53 | } | ||
| 54 | } | ||
| 55 | |||
| 56 | void ttm_global_release(void) | ||
| 57 | { | ||
| 58 | int i; | ||
| 59 | for (i = 0; i < TTM_GLOBAL_NUM; ++i) { | ||
| 60 | struct ttm_global_item *item = &glob[i]; | ||
| 61 | BUG_ON(item->object != NULL); | ||
| 62 | BUG_ON(item->refcount != 0); | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | int ttm_global_item_ref(struct ttm_global_reference *ref) | ||
| 67 | { | ||
| 68 | int ret; | ||
| 69 | struct ttm_global_item *item = &glob[ref->global_type]; | ||
| 70 | void *object; | ||
| 71 | |||
| 72 | mutex_lock(&item->mutex); | ||
| 73 | if (item->refcount == 0) { | ||
| 74 | item->object = kmalloc(ref->size, GFP_KERNEL); | ||
| 75 | if (unlikely(item->object == NULL)) { | ||
| 76 | ret = -ENOMEM; | ||
| 77 | goto out_err; | ||
| 78 | } | ||
| 79 | |||
| 80 | ref->object = item->object; | ||
| 81 | ret = ref->init(ref); | ||
| 82 | if (unlikely(ret != 0)) | ||
| 83 | goto out_err; | ||
| 84 | |||
| 85 | ++item->refcount; | ||
| 86 | } | ||
| 87 | ref->object = item->object; | ||
| 88 | object = item->object; | ||
| 89 | mutex_unlock(&item->mutex); | ||
| 90 | return 0; | ||
| 91 | out_err: | ||
| 92 | kfree(item->object); | ||
| 93 | mutex_unlock(&item->mutex); | ||
| 94 | item->object = NULL; | ||
| 95 | return ret; | ||
| 96 | } | ||
| 97 | EXPORT_SYMBOL(ttm_global_item_ref); | ||
| 98 | |||
| 99 | void ttm_global_item_unref(struct ttm_global_reference *ref) | ||
| 100 | { | ||
| 101 | struct ttm_global_item *item = &glob[ref->global_type]; | ||
| 102 | |||
| 103 | mutex_lock(&item->mutex); | ||
| 104 | BUG_ON(item->refcount == 0); | ||
| 105 | BUG_ON(ref->object != item->object); | ||
| 106 | if (--item->refcount == 0) { | ||
| 107 | ref->release(ref); | ||
| 108 | kfree(item->object); | ||
| 109 | item->object = NULL; | ||
| 110 | } | ||
| 111 | mutex_unlock(&item->mutex); | ||
| 112 | } | ||
| 113 | EXPORT_SYMBOL(ttm_global_item_unref); | ||
| 114 | |||
diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c new file mode 100644 index 000000000000..87323d4ff68d --- /dev/null +++ b/drivers/gpu/drm/ttm/ttm_memory.c | |||
| @@ -0,0 +1,234 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | **************************************************************************/ | ||
| 27 | |||
| 28 | #include "ttm/ttm_memory.h" | ||
| 29 | #include <linux/spinlock.h> | ||
| 30 | #include <linux/sched.h> | ||
| 31 | #include <linux/wait.h> | ||
| 32 | #include <linux/mm.h> | ||
| 33 | #include <linux/module.h> | ||
| 34 | |||
| 35 | #define TTM_PFX "[TTM] " | ||
| 36 | #define TTM_MEMORY_ALLOC_RETRIES 4 | ||
| 37 | |||
| 38 | /** | ||
| 39 | * At this point we only support a single shrink callback. | ||
| 40 | * Extend this if needed, perhaps using a linked list of callbacks. | ||
| 41 | * Note that this function is reentrant: | ||
| 42 | * many threads may try to swap out at any given time. | ||
| 43 | */ | ||
| 44 | |||
| 45 | static void ttm_shrink(struct ttm_mem_global *glob, bool from_workqueue, | ||
| 46 | uint64_t extra) | ||
| 47 | { | ||
| 48 | int ret; | ||
| 49 | struct ttm_mem_shrink *shrink; | ||
| 50 | uint64_t target; | ||
| 51 | uint64_t total_target; | ||
| 52 | |||
| 53 | spin_lock(&glob->lock); | ||
| 54 | if (glob->shrink == NULL) | ||
| 55 | goto out; | ||
| 56 | |||
| 57 | if (from_workqueue) { | ||
| 58 | target = glob->swap_limit; | ||
| 59 | total_target = glob->total_memory_swap_limit; | ||
| 60 | } else if (capable(CAP_SYS_ADMIN)) { | ||
| 61 | total_target = glob->emer_total_memory; | ||
| 62 | target = glob->emer_memory; | ||
| 63 | } else { | ||
| 64 | total_target = glob->max_total_memory; | ||
| 65 | target = glob->max_memory; | ||
| 66 | } | ||
| 67 | |||
| 68 | total_target = (extra >= total_target) ? 0 : total_target - extra; | ||
| 69 | target = (extra >= target) ? 0 : target - extra; | ||
| 70 | |||
| 71 | while (glob->used_memory > target || | ||
| 72 | glob->used_total_memory > total_target) { | ||
| 73 | shrink = glob->shrink; | ||
| 74 | spin_unlock(&glob->lock); | ||
| 75 | ret = shrink->do_shrink(shrink); | ||
| 76 | spin_lock(&glob->lock); | ||
| 77 | if (unlikely(ret != 0)) | ||
| 78 | goto out; | ||
| 79 | } | ||
| 80 | out: | ||
| 81 | spin_unlock(&glob->lock); | ||
| 82 | } | ||
| 83 | |||
| 84 | static void ttm_shrink_work(struct work_struct *work) | ||
| 85 | { | ||
| 86 | struct ttm_mem_global *glob = | ||
| 87 | container_of(work, struct ttm_mem_global, work); | ||
| 88 | |||
| 89 | ttm_shrink(glob, true, 0ULL); | ||
| 90 | } | ||
| 91 | |||
| 92 | int ttm_mem_global_init(struct ttm_mem_global *glob) | ||
| 93 | { | ||
| 94 | struct sysinfo si; | ||
| 95 | uint64_t mem; | ||
| 96 | |||
| 97 | spin_lock_init(&glob->lock); | ||
| 98 | glob->swap_queue = create_singlethread_workqueue("ttm_swap"); | ||
| 99 | INIT_WORK(&glob->work, ttm_shrink_work); | ||
| 100 | init_waitqueue_head(&glob->queue); | ||
| 101 | |||
| 102 | si_meminfo(&si); | ||
| 103 | |||
| 104 | mem = si.totalram - si.totalhigh; | ||
| 105 | mem *= si.mem_unit; | ||
| 106 | |||
| 107 | glob->max_memory = mem >> 1; | ||
| 108 | glob->emer_memory = (mem >> 1) + (mem >> 2); | ||
| 109 | glob->swap_limit = glob->max_memory - (mem >> 3); | ||
| 110 | glob->used_memory = 0; | ||
| 111 | glob->used_total_memory = 0; | ||
| 112 | glob->shrink = NULL; | ||
| 113 | |||
| 114 | mem = si.totalram; | ||
| 115 | mem *= si.mem_unit; | ||
| 116 | |||
| 117 | glob->max_total_memory = mem >> 1; | ||
| 118 | glob->emer_total_memory = (mem >> 1) + (mem >> 2); | ||
| 119 | |||
| 120 | glob->total_memory_swap_limit = glob->max_total_memory - (mem >> 3); | ||
| 121 | |||
| 122 | printk(KERN_INFO TTM_PFX "TTM available graphics memory: %llu MiB\n", | ||
| 123 | glob->max_total_memory >> 20); | ||
| 124 | printk(KERN_INFO TTM_PFX "TTM available object memory: %llu MiB\n", | ||
| 125 | glob->max_memory >> 20); | ||
| 126 | |||
| 127 | return 0; | ||
| 128 | } | ||
| 129 | EXPORT_SYMBOL(ttm_mem_global_init); | ||
| 130 | |||
| 131 | void ttm_mem_global_release(struct ttm_mem_global *glob) | ||
| 132 | { | ||
| 133 | printk(KERN_INFO TTM_PFX "Used total memory is %llu bytes.\n", | ||
| 134 | (unsigned long long)glob->used_total_memory); | ||
| 135 | flush_workqueue(glob->swap_queue); | ||
| 136 | destroy_workqueue(glob->swap_queue); | ||
| 137 | glob->swap_queue = NULL; | ||
| 138 | } | ||
| 139 | EXPORT_SYMBOL(ttm_mem_global_release); | ||
| 140 | |||
| 141 | static inline void ttm_check_swapping(struct ttm_mem_global *glob) | ||
| 142 | { | ||
| 143 | bool needs_swapping; | ||
| 144 | |||
| 145 | spin_lock(&glob->lock); | ||
| 146 | needs_swapping = (glob->used_memory > glob->swap_limit || | ||
| 147 | glob->used_total_memory > | ||
| 148 | glob->total_memory_swap_limit); | ||
| 149 | spin_unlock(&glob->lock); | ||
| 150 | |||
| 151 | if (unlikely(needs_swapping)) | ||
| 152 | (void)queue_work(glob->swap_queue, &glob->work); | ||
| 153 | |||
| 154 | } | ||
| 155 | |||
| 156 | void ttm_mem_global_free(struct ttm_mem_global *glob, | ||
| 157 | uint64_t amount, bool himem) | ||
| 158 | { | ||
| 159 | spin_lock(&glob->lock); | ||
| 160 | glob->used_total_memory -= amount; | ||
| 161 | if (!himem) | ||
| 162 | glob->used_memory -= amount; | ||
| 163 | wake_up_all(&glob->queue); | ||
| 164 | spin_unlock(&glob->lock); | ||
| 165 | } | ||
| 166 | |||
| 167 | static int ttm_mem_global_reserve(struct ttm_mem_global *glob, | ||
| 168 | uint64_t amount, bool himem, bool reserve) | ||
| 169 | { | ||
| 170 | uint64_t limit; | ||
| 171 | uint64_t lomem_limit; | ||
| 172 | int ret = -ENOMEM; | ||
| 173 | |||
| 174 | spin_lock(&glob->lock); | ||
| 175 | |||
| 176 | if (capable(CAP_SYS_ADMIN)) { | ||
| 177 | limit = glob->emer_total_memory; | ||
| 178 | lomem_limit = glob->emer_memory; | ||
| 179 | } else { | ||
| 180 | limit = glob->max_total_memory; | ||
| 181 | lomem_limit = glob->max_memory; | ||
| 182 | } | ||
| 183 | |||
| 184 | if (unlikely(glob->used_total_memory + amount > limit)) | ||
| 185 | goto out_unlock; | ||
| 186 | if (unlikely(!himem && glob->used_memory + amount > lomem_limit)) | ||
| 187 | goto out_unlock; | ||
| 188 | |||
| 189 | if (reserve) { | ||
| 190 | glob->used_total_memory += amount; | ||
| 191 | if (!himem) | ||
| 192 | glob->used_memory += amount; | ||
| 193 | } | ||
| 194 | ret = 0; | ||
| 195 | out_unlock: | ||
| 196 | spin_unlock(&glob->lock); | ||
| 197 | ttm_check_swapping(glob); | ||
| 198 | |||
| 199 | return ret; | ||
| 200 | } | ||
| 201 | |||
| 202 | int ttm_mem_global_alloc(struct ttm_mem_global *glob, uint64_t memory, | ||
| 203 | bool no_wait, bool interruptible, bool himem) | ||
| 204 | { | ||
| 205 | int count = TTM_MEMORY_ALLOC_RETRIES; | ||
| 206 | |||
| 207 | while (unlikely(ttm_mem_global_reserve(glob, memory, himem, true) | ||
| 208 | != 0)) { | ||
| 209 | if (no_wait) | ||
| 210 | return -ENOMEM; | ||
| 211 | if (unlikely(count-- == 0)) | ||
| 212 | return -ENOMEM; | ||
| 213 | ttm_shrink(glob, false, memory + (memory >> 2) + 16); | ||
| 214 | } | ||
| 215 | |||
| 216 | return 0; | ||
| 217 | } | ||
| 218 | |||
| 219 | size_t ttm_round_pot(size_t size) | ||
| 220 | { | ||
| 221 | if ((size & (size - 1)) == 0) | ||
| 222 | return size; | ||
| 223 | else if (size > PAGE_SIZE) | ||
| 224 | return PAGE_ALIGN(size); | ||
| 225 | else { | ||
| 226 | size_t tmp_size = 4; | ||
| 227 | |||
| 228 | while (tmp_size < size) | ||
| 229 | tmp_size <<= 1; | ||
| 230 | |||
| 231 | return tmp_size; | ||
| 232 | } | ||
| 233 | return 0; | ||
| 234 | } | ||
diff --git a/drivers/gpu/drm/ttm/ttm_module.c b/drivers/gpu/drm/ttm/ttm_module.c new file mode 100644 index 000000000000..59ce8191d584 --- /dev/null +++ b/drivers/gpu/drm/ttm/ttm_module.c | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | **************************************************************************/ | ||
| 27 | /* | ||
| 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | ||
| 29 | * Jerome Glisse | ||
| 30 | */ | ||
| 31 | #include <linux/module.h> | ||
| 32 | #include <ttm/ttm_module.h> | ||
| 33 | |||
| 34 | static int __init ttm_init(void) | ||
| 35 | { | ||
| 36 | ttm_global_init(); | ||
| 37 | return 0; | ||
| 38 | } | ||
| 39 | |||
| 40 | static void __exit ttm_exit(void) | ||
| 41 | { | ||
| 42 | ttm_global_release(); | ||
| 43 | } | ||
| 44 | |||
| 45 | module_init(ttm_init); | ||
| 46 | module_exit(ttm_exit); | ||
| 47 | |||
| 48 | MODULE_AUTHOR("Thomas Hellstrom, Jerome Glisse"); | ||
| 49 | MODULE_DESCRIPTION("TTM memory manager subsystem (for DRM device)"); | ||
| 50 | MODULE_LICENSE("GPL and additional rights"); | ||
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c new file mode 100644 index 000000000000..c27ab3a877ad --- /dev/null +++ b/drivers/gpu/drm/ttm/ttm_tt.c | |||
| @@ -0,0 +1,635 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | **************************************************************************/ | ||
| 27 | /* | ||
| 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include <linux/version.h> | ||
| 32 | #include <linux/vmalloc.h> | ||
| 33 | #include <linux/sched.h> | ||
| 34 | #include <linux/highmem.h> | ||
| 35 | #include <linux/pagemap.h> | ||
| 36 | #include <linux/file.h> | ||
| 37 | #include <linux/swap.h> | ||
| 38 | #include "ttm/ttm_module.h" | ||
| 39 | #include "ttm/ttm_bo_driver.h" | ||
| 40 | #include "ttm/ttm_placement.h" | ||
| 41 | |||
| 42 | static int ttm_tt_swapin(struct ttm_tt *ttm); | ||
| 43 | |||
| 44 | #if defined(CONFIG_X86) | ||
| 45 | static void ttm_tt_clflush_page(struct page *page) | ||
| 46 | { | ||
| 47 | uint8_t *page_virtual; | ||
| 48 | unsigned int i; | ||
| 49 | |||
| 50 | if (unlikely(page == NULL)) | ||
| 51 | return; | ||
| 52 | |||
| 53 | page_virtual = kmap_atomic(page, KM_USER0); | ||
| 54 | |||
| 55 | for (i = 0; i < PAGE_SIZE; i += boot_cpu_data.x86_clflush_size) | ||
| 56 | clflush(page_virtual + i); | ||
| 57 | |||
| 58 | kunmap_atomic(page_virtual, KM_USER0); | ||
| 59 | } | ||
| 60 | |||
| 61 | static void ttm_tt_cache_flush_clflush(struct page *pages[], | ||
| 62 | unsigned long num_pages) | ||
| 63 | { | ||
| 64 | unsigned long i; | ||
| 65 | |||
| 66 | mb(); | ||
| 67 | for (i = 0; i < num_pages; ++i) | ||
| 68 | ttm_tt_clflush_page(*pages++); | ||
| 69 | mb(); | ||
| 70 | } | ||
| 71 | #else | ||
| 72 | static void ttm_tt_ipi_handler(void *null) | ||
| 73 | { | ||
| 74 | ; | ||
| 75 | } | ||
| 76 | #endif | ||
| 77 | |||
| 78 | void ttm_tt_cache_flush(struct page *pages[], unsigned long num_pages) | ||
| 79 | { | ||
| 80 | |||
| 81 | #if defined(CONFIG_X86) | ||
| 82 | if (cpu_has_clflush) { | ||
| 83 | ttm_tt_cache_flush_clflush(pages, num_pages); | ||
| 84 | return; | ||
| 85 | } | ||
| 86 | #else | ||
| 87 | if (on_each_cpu(ttm_tt_ipi_handler, NULL, 1) != 0) | ||
| 88 | printk(KERN_ERR TTM_PFX | ||
| 89 | "Timed out waiting for drm cache flush.\n"); | ||
| 90 | #endif | ||
| 91 | } | ||
| 92 | |||
| 93 | /** | ||
| 94 | * Allocates storage for pointers to the pages that back the ttm. | ||
| 95 | * | ||
| 96 | * Uses kmalloc if possible. Otherwise falls back to vmalloc. | ||
| 97 | */ | ||
| 98 | static void ttm_tt_alloc_page_directory(struct ttm_tt *ttm) | ||
| 99 | { | ||
| 100 | unsigned long size = ttm->num_pages * sizeof(*ttm->pages); | ||
| 101 | ttm->pages = NULL; | ||
| 102 | |||
| 103 | if (size <= PAGE_SIZE) | ||
| 104 | ttm->pages = kzalloc(size, GFP_KERNEL); | ||
| 105 | |||
| 106 | if (!ttm->pages) { | ||
| 107 | ttm->pages = vmalloc_user(size); | ||
| 108 | if (ttm->pages) | ||
| 109 | ttm->page_flags |= TTM_PAGE_FLAG_VMALLOC; | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | static void ttm_tt_free_page_directory(struct ttm_tt *ttm) | ||
| 114 | { | ||
| 115 | if (ttm->page_flags & TTM_PAGE_FLAG_VMALLOC) { | ||
| 116 | vfree(ttm->pages); | ||
| 117 | ttm->page_flags &= ~TTM_PAGE_FLAG_VMALLOC; | ||
| 118 | } else { | ||
| 119 | kfree(ttm->pages); | ||
| 120 | } | ||
| 121 | ttm->pages = NULL; | ||
| 122 | } | ||
| 123 | |||
| 124 | static struct page *ttm_tt_alloc_page(unsigned page_flags) | ||
| 125 | { | ||
| 126 | if (page_flags & TTM_PAGE_FLAG_ZERO_ALLOC) | ||
| 127 | return alloc_page(GFP_HIGHUSER | __GFP_ZERO); | ||
| 128 | |||
| 129 | return alloc_page(GFP_HIGHUSER); | ||
| 130 | } | ||
| 131 | |||
| 132 | static void ttm_tt_free_user_pages(struct ttm_tt *ttm) | ||
| 133 | { | ||
| 134 | int write; | ||
| 135 | int dirty; | ||
| 136 | struct page *page; | ||
| 137 | int i; | ||
| 138 | struct ttm_backend *be = ttm->be; | ||
| 139 | |||
| 140 | BUG_ON(!(ttm->page_flags & TTM_PAGE_FLAG_USER)); | ||
| 141 | write = ((ttm->page_flags & TTM_PAGE_FLAG_WRITE) != 0); | ||
| 142 | dirty = ((ttm->page_flags & TTM_PAGE_FLAG_USER_DIRTY) != 0); | ||
| 143 | |||
| 144 | if (be) | ||
| 145 | be->func->clear(be); | ||
| 146 | |||
| 147 | for (i = 0; i < ttm->num_pages; ++i) { | ||
| 148 | page = ttm->pages[i]; | ||
| 149 | if (page == NULL) | ||
| 150 | continue; | ||
| 151 | |||
| 152 | if (page == ttm->dummy_read_page) { | ||
| 153 | BUG_ON(write); | ||
| 154 | continue; | ||
| 155 | } | ||
| 156 | |||
| 157 | if (write && dirty && !PageReserved(page)) | ||
| 158 | set_page_dirty_lock(page); | ||
| 159 | |||
| 160 | ttm->pages[i] = NULL; | ||
| 161 | ttm_mem_global_free(ttm->bdev->mem_glob, PAGE_SIZE, false); | ||
| 162 | put_page(page); | ||
| 163 | } | ||
| 164 | ttm->state = tt_unpopulated; | ||
| 165 | ttm->first_himem_page = ttm->num_pages; | ||
| 166 | ttm->last_lomem_page = -1; | ||
| 167 | } | ||
| 168 | |||
| 169 | static struct page *__ttm_tt_get_page(struct ttm_tt *ttm, int index) | ||
| 170 | { | ||
| 171 | struct page *p; | ||
| 172 | struct ttm_bo_device *bdev = ttm->bdev; | ||
| 173 | struct ttm_mem_global *mem_glob = bdev->mem_glob; | ||
| 174 | int ret; | ||
| 175 | |||
| 176 | while (NULL == (p = ttm->pages[index])) { | ||
| 177 | p = ttm_tt_alloc_page(ttm->page_flags); | ||
| 178 | |||
| 179 | if (!p) | ||
| 180 | return NULL; | ||
| 181 | |||
| 182 | if (PageHighMem(p)) { | ||
| 183 | ret = | ||
| 184 | ttm_mem_global_alloc(mem_glob, PAGE_SIZE, | ||
| 185 | false, false, true); | ||
| 186 | if (unlikely(ret != 0)) | ||
| 187 | goto out_err; | ||
| 188 | ttm->pages[--ttm->first_himem_page] = p; | ||
| 189 | } else { | ||
| 190 | ret = | ||
| 191 | ttm_mem_global_alloc(mem_glob, PAGE_SIZE, | ||
| 192 | false, false, false); | ||
| 193 | if (unlikely(ret != 0)) | ||
| 194 | goto out_err; | ||
| 195 | ttm->pages[++ttm->last_lomem_page] = p; | ||
| 196 | } | ||
| 197 | } | ||
| 198 | return p; | ||
| 199 | out_err: | ||
| 200 | put_page(p); | ||
| 201 | return NULL; | ||
| 202 | } | ||
| 203 | |||
| 204 | struct page *ttm_tt_get_page(struct ttm_tt *ttm, int index) | ||
| 205 | { | ||
| 206 | int ret; | ||
| 207 | |||
| 208 | if (unlikely(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) { | ||
| 209 | ret = ttm_tt_swapin(ttm); | ||
| 210 | if (unlikely(ret != 0)) | ||
| 211 | return NULL; | ||
| 212 | } | ||
| 213 | return __ttm_tt_get_page(ttm, index); | ||
| 214 | } | ||
| 215 | |||
| 216 | int ttm_tt_populate(struct ttm_tt *ttm) | ||
| 217 | { | ||
| 218 | struct page *page; | ||
| 219 | unsigned long i; | ||
| 220 | struct ttm_backend *be; | ||
| 221 | int ret; | ||
| 222 | |||
| 223 | if (ttm->state != tt_unpopulated) | ||
| 224 | return 0; | ||
| 225 | |||
| 226 | if (unlikely(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) { | ||
| 227 | ret = ttm_tt_swapin(ttm); | ||
| 228 | if (unlikely(ret != 0)) | ||
| 229 | return ret; | ||
| 230 | } | ||
| 231 | |||
| 232 | be = ttm->be; | ||
| 233 | |||
| 234 | for (i = 0; i < ttm->num_pages; ++i) { | ||
| 235 | page = __ttm_tt_get_page(ttm, i); | ||
| 236 | if (!page) | ||
| 237 | return -ENOMEM; | ||
| 238 | } | ||
| 239 | |||
| 240 | be->func->populate(be, ttm->num_pages, ttm->pages, | ||
| 241 | ttm->dummy_read_page); | ||
| 242 | ttm->state = tt_unbound; | ||
| 243 | return 0; | ||
| 244 | } | ||
| 245 | |||
| 246 | #ifdef CONFIG_X86 | ||
| 247 | static inline int ttm_tt_set_page_caching(struct page *p, | ||
| 248 | enum ttm_caching_state c_state) | ||
| 249 | { | ||
| 250 | if (PageHighMem(p)) | ||
| 251 | return 0; | ||
| 252 | |||
| 253 | switch (c_state) { | ||
| 254 | case tt_cached: | ||
| 255 | return set_pages_wb(p, 1); | ||
| 256 | case tt_wc: | ||
| 257 | return set_memory_wc((unsigned long) page_address(p), 1); | ||
| 258 | default: | ||
| 259 | return set_pages_uc(p, 1); | ||
| 260 | } | ||
| 261 | } | ||
| 262 | #else /* CONFIG_X86 */ | ||
| 263 | static inline int ttm_tt_set_page_caching(struct page *p, | ||
| 264 | enum ttm_caching_state c_state) | ||
| 265 | { | ||
| 266 | return 0; | ||
| 267 | } | ||
| 268 | #endif /* CONFIG_X86 */ | ||
| 269 | |||
| 270 | /* | ||
| 271 | * Change caching policy for the linear kernel map | ||
| 272 | * for range of pages in a ttm. | ||
| 273 | */ | ||
| 274 | |||
| 275 | static int ttm_tt_set_caching(struct ttm_tt *ttm, | ||
| 276 | enum ttm_caching_state c_state) | ||
| 277 | { | ||
| 278 | int i, j; | ||
| 279 | struct page *cur_page; | ||
| 280 | int ret; | ||
| 281 | |||
| 282 | if (ttm->caching_state == c_state) | ||
| 283 | return 0; | ||
| 284 | |||
| 285 | if (c_state != tt_cached) { | ||
| 286 | ret = ttm_tt_populate(ttm); | ||
| 287 | if (unlikely(ret != 0)) | ||
| 288 | return ret; | ||
| 289 | } | ||
| 290 | |||
| 291 | if (ttm->caching_state == tt_cached) | ||
| 292 | ttm_tt_cache_flush(ttm->pages, ttm->num_pages); | ||
| 293 | |||
| 294 | for (i = 0; i < ttm->num_pages; ++i) { | ||
| 295 | cur_page = ttm->pages[i]; | ||
| 296 | if (likely(cur_page != NULL)) { | ||
| 297 | ret = ttm_tt_set_page_caching(cur_page, c_state); | ||
| 298 | if (unlikely(ret != 0)) | ||
| 299 | goto out_err; | ||
| 300 | } | ||
| 301 | } | ||
| 302 | |||
| 303 | ttm->caching_state = c_state; | ||
| 304 | |||
| 305 | return 0; | ||
| 306 | |||
| 307 | out_err: | ||
| 308 | for (j = 0; j < i; ++j) { | ||
| 309 | cur_page = ttm->pages[j]; | ||
| 310 | if (likely(cur_page != NULL)) { | ||
| 311 | (void)ttm_tt_set_page_caching(cur_page, | ||
| 312 | ttm->caching_state); | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | return ret; | ||
| 317 | } | ||
| 318 | |||
| 319 | int ttm_tt_set_placement_caching(struct ttm_tt *ttm, uint32_t placement) | ||
| 320 | { | ||
| 321 | enum ttm_caching_state state; | ||
| 322 | |||
| 323 | if (placement & TTM_PL_FLAG_WC) | ||
| 324 | state = tt_wc; | ||
| 325 | else if (placement & TTM_PL_FLAG_UNCACHED) | ||
| 326 | state = tt_uncached; | ||
| 327 | else | ||
| 328 | state = tt_cached; | ||
| 329 | |||
| 330 | return ttm_tt_set_caching(ttm, state); | ||
| 331 | } | ||
| 332 | |||
| 333 | static void ttm_tt_free_alloced_pages(struct ttm_tt *ttm) | ||
| 334 | { | ||
| 335 | int i; | ||
| 336 | struct page *cur_page; | ||
| 337 | struct ttm_backend *be = ttm->be; | ||
| 338 | |||
| 339 | if (be) | ||
| 340 | be->func->clear(be); | ||
| 341 | (void)ttm_tt_set_caching(ttm, tt_cached); | ||
| 342 | for (i = 0; i < ttm->num_pages; ++i) { | ||
| 343 | cur_page = ttm->pages[i]; | ||
| 344 | ttm->pages[i] = NULL; | ||
| 345 | if (cur_page) { | ||
| 346 | if (page_count(cur_page) != 1) | ||
| 347 | printk(KERN_ERR TTM_PFX | ||
| 348 | "Erroneous page count. " | ||
| 349 | "Leaking pages.\n"); | ||
| 350 | ttm_mem_global_free(ttm->bdev->mem_glob, PAGE_SIZE, | ||
| 351 | PageHighMem(cur_page)); | ||
| 352 | __free_page(cur_page); | ||
| 353 | } | ||
| 354 | } | ||
| 355 | ttm->state = tt_unpopulated; | ||
| 356 | ttm->first_himem_page = ttm->num_pages; | ||
| 357 | ttm->last_lomem_page = -1; | ||
| 358 | } | ||
| 359 | |||
| 360 | void ttm_tt_destroy(struct ttm_tt *ttm) | ||
| 361 | { | ||
| 362 | struct ttm_backend *be; | ||
| 363 | |||
| 364 | if (unlikely(ttm == NULL)) | ||
| 365 | return; | ||
| 366 | |||
| 367 | be = ttm->be; | ||
| 368 | if (likely(be != NULL)) { | ||
| 369 | be->func->destroy(be); | ||
| 370 | ttm->be = NULL; | ||
| 371 | } | ||
| 372 | |||
| 373 | if (likely(ttm->pages != NULL)) { | ||
| 374 | if (ttm->page_flags & TTM_PAGE_FLAG_USER) | ||
| 375 | ttm_tt_free_user_pages(ttm); | ||
| 376 | else | ||
| 377 | ttm_tt_free_alloced_pages(ttm); | ||
| 378 | |||
| 379 | ttm_tt_free_page_directory(ttm); | ||
| 380 | } | ||
| 381 | |||
| 382 | if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTANT_SWAP) && | ||
| 383 | ttm->swap_storage) | ||
| 384 | fput(ttm->swap_storage); | ||
| 385 | |||
| 386 | kfree(ttm); | ||
| 387 | } | ||
| 388 | |||
| 389 | int ttm_tt_set_user(struct ttm_tt *ttm, | ||
| 390 | struct task_struct *tsk, | ||
| 391 | unsigned long start, unsigned long num_pages) | ||
| 392 | { | ||
| 393 | struct mm_struct *mm = tsk->mm; | ||
| 394 | int ret; | ||
| 395 | int write = (ttm->page_flags & TTM_PAGE_FLAG_WRITE) != 0; | ||
| 396 | struct ttm_mem_global *mem_glob = ttm->bdev->mem_glob; | ||
| 397 | |||
| 398 | BUG_ON(num_pages != ttm->num_pages); | ||
| 399 | BUG_ON((ttm->page_flags & TTM_PAGE_FLAG_USER) == 0); | ||
| 400 | |||
| 401 | /** | ||
| 402 | * Account user pages as lowmem pages for now. | ||
| 403 | */ | ||
| 404 | |||
| 405 | ret = ttm_mem_global_alloc(mem_glob, num_pages * PAGE_SIZE, | ||
| 406 | false, false, false); | ||
| 407 | if (unlikely(ret != 0)) | ||
| 408 | return ret; | ||
| 409 | |||
| 410 | down_read(&mm->mmap_sem); | ||
| 411 | ret = get_user_pages(tsk, mm, start, num_pages, | ||
| 412 | write, 0, ttm->pages, NULL); | ||
| 413 | up_read(&mm->mmap_sem); | ||
| 414 | |||
| 415 | if (ret != num_pages && write) { | ||
| 416 | ttm_tt_free_user_pages(ttm); | ||
| 417 | ttm_mem_global_free(mem_glob, num_pages * PAGE_SIZE, false); | ||
| 418 | return -ENOMEM; | ||
| 419 | } | ||
| 420 | |||
| 421 | ttm->tsk = tsk; | ||
| 422 | ttm->start = start; | ||
| 423 | ttm->state = tt_unbound; | ||
| 424 | |||
| 425 | return 0; | ||
| 426 | } | ||
| 427 | |||
| 428 | struct ttm_tt *ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size, | ||
| 429 | uint32_t page_flags, struct page *dummy_read_page) | ||
| 430 | { | ||
| 431 | struct ttm_bo_driver *bo_driver = bdev->driver; | ||
| 432 | struct ttm_tt *ttm; | ||
| 433 | |||
| 434 | if (!bo_driver) | ||
| 435 | return NULL; | ||
| 436 | |||
| 437 | ttm = kzalloc(sizeof(*ttm), GFP_KERNEL); | ||
| 438 | if (!ttm) | ||
| 439 | return NULL; | ||
| 440 | |||
| 441 | ttm->bdev = bdev; | ||
| 442 | |||
| 443 | ttm->num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
| 444 | ttm->first_himem_page = ttm->num_pages; | ||
| 445 | ttm->last_lomem_page = -1; | ||
| 446 | ttm->caching_state = tt_cached; | ||
| 447 | ttm->page_flags = page_flags; | ||
| 448 | |||
| 449 | ttm->dummy_read_page = dummy_read_page; | ||
| 450 | |||
| 451 | ttm_tt_alloc_page_directory(ttm); | ||
| 452 | if (!ttm->pages) { | ||
| 453 | ttm_tt_destroy(ttm); | ||
| 454 | printk(KERN_ERR TTM_PFX "Failed allocating page table\n"); | ||
| 455 | return NULL; | ||
| 456 | } | ||
| 457 | ttm->be = bo_driver->create_ttm_backend_entry(bdev); | ||
| 458 | if (!ttm->be) { | ||
| 459 | ttm_tt_destroy(ttm); | ||
| 460 | printk(KERN_ERR TTM_PFX "Failed creating ttm backend entry\n"); | ||
| 461 | return NULL; | ||
| 462 | } | ||
| 463 | ttm->state = tt_unpopulated; | ||
| 464 | return ttm; | ||
| 465 | } | ||
| 466 | |||
| 467 | void ttm_tt_unbind(struct ttm_tt *ttm) | ||
| 468 | { | ||
| 469 | int ret; | ||
| 470 | struct ttm_backend *be = ttm->be; | ||
| 471 | |||
| 472 | if (ttm->state == tt_bound) { | ||
| 473 | ret = be->func->unbind(be); | ||
| 474 | BUG_ON(ret); | ||
| 475 | ttm->state = tt_unbound; | ||
| 476 | } | ||
| 477 | } | ||
| 478 | |||
| 479 | int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem) | ||
| 480 | { | ||
| 481 | int ret = 0; | ||
| 482 | struct ttm_backend *be; | ||
| 483 | |||
| 484 | if (!ttm) | ||
| 485 | return -EINVAL; | ||
| 486 | |||
| 487 | if (ttm->state == tt_bound) | ||
| 488 | return 0; | ||
| 489 | |||
| 490 | be = ttm->be; | ||
| 491 | |||
| 492 | ret = ttm_tt_populate(ttm); | ||
| 493 | if (ret) | ||
| 494 | return ret; | ||
| 495 | |||
| 496 | ret = be->func->bind(be, bo_mem); | ||
| 497 | if (ret) { | ||
| 498 | printk(KERN_ERR TTM_PFX "Couldn't bind backend.\n"); | ||
| 499 | return ret; | ||
| 500 | } | ||
| 501 | |||
| 502 | ttm->state = tt_bound; | ||
| 503 | |||
| 504 | if (ttm->page_flags & TTM_PAGE_FLAG_USER) | ||
| 505 | ttm->page_flags |= TTM_PAGE_FLAG_USER_DIRTY; | ||
| 506 | return 0; | ||
| 507 | } | ||
| 508 | EXPORT_SYMBOL(ttm_tt_bind); | ||
| 509 | |||
| 510 | static int ttm_tt_swapin(struct ttm_tt *ttm) | ||
| 511 | { | ||
| 512 | struct address_space *swap_space; | ||
| 513 | struct file *swap_storage; | ||
| 514 | struct page *from_page; | ||
| 515 | struct page *to_page; | ||
| 516 | void *from_virtual; | ||
| 517 | void *to_virtual; | ||
| 518 | int i; | ||
| 519 | int ret; | ||
| 520 | |||
| 521 | if (ttm->page_flags & TTM_PAGE_FLAG_USER) { | ||
| 522 | ret = ttm_tt_set_user(ttm, ttm->tsk, ttm->start, | ||
| 523 | ttm->num_pages); | ||
| 524 | if (unlikely(ret != 0)) | ||
| 525 | return ret; | ||
| 526 | |||
| 527 | ttm->page_flags &= ~TTM_PAGE_FLAG_SWAPPED; | ||
| 528 | return 0; | ||
| 529 | } | ||
| 530 | |||
| 531 | swap_storage = ttm->swap_storage; | ||
| 532 | BUG_ON(swap_storage == NULL); | ||
| 533 | |||
| 534 | swap_space = swap_storage->f_path.dentry->d_inode->i_mapping; | ||
| 535 | |||
| 536 | for (i = 0; i < ttm->num_pages; ++i) { | ||
| 537 | from_page = read_mapping_page(swap_space, i, NULL); | ||
| 538 | if (IS_ERR(from_page)) | ||
| 539 | goto out_err; | ||
| 540 | to_page = __ttm_tt_get_page(ttm, i); | ||
| 541 | if (unlikely(to_page == NULL)) | ||
| 542 | goto out_err; | ||
| 543 | |||
| 544 | preempt_disable(); | ||
| 545 | from_virtual = kmap_atomic(from_page, KM_USER0); | ||
| 546 | to_virtual = kmap_atomic(to_page, KM_USER1); | ||
| 547 | memcpy(to_virtual, from_virtual, PAGE_SIZE); | ||
| 548 | kunmap_atomic(to_virtual, KM_USER1); | ||
| 549 | kunmap_atomic(from_virtual, KM_USER0); | ||
| 550 | preempt_enable(); | ||
| 551 | page_cache_release(from_page); | ||
| 552 | } | ||
| 553 | |||
| 554 | if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTANT_SWAP)) | ||
| 555 | fput(swap_storage); | ||
| 556 | ttm->swap_storage = NULL; | ||
| 557 | ttm->page_flags &= ~TTM_PAGE_FLAG_SWAPPED; | ||
| 558 | |||
| 559 | return 0; | ||
| 560 | out_err: | ||
| 561 | ttm_tt_free_alloced_pages(ttm); | ||
| 562 | return -ENOMEM; | ||
| 563 | } | ||
| 564 | |||
| 565 | int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistant_swap_storage) | ||
| 566 | { | ||
| 567 | struct address_space *swap_space; | ||
| 568 | struct file *swap_storage; | ||
| 569 | struct page *from_page; | ||
| 570 | struct page *to_page; | ||
| 571 | void *from_virtual; | ||
| 572 | void *to_virtual; | ||
| 573 | int i; | ||
| 574 | |||
| 575 | BUG_ON(ttm->state != tt_unbound && ttm->state != tt_unpopulated); | ||
| 576 | BUG_ON(ttm->caching_state != tt_cached); | ||
| 577 | |||
| 578 | /* | ||
| 579 | * For user buffers, just unpin the pages, as there should be | ||
| 580 | * vma references. | ||
| 581 | */ | ||
| 582 | |||
| 583 | if (ttm->page_flags & TTM_PAGE_FLAG_USER) { | ||
| 584 | ttm_tt_free_user_pages(ttm); | ||
| 585 | ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED; | ||
| 586 | ttm->swap_storage = NULL; | ||
| 587 | return 0; | ||
| 588 | } | ||
| 589 | |||
| 590 | if (!persistant_swap_storage) { | ||
| 591 | swap_storage = shmem_file_setup("ttm swap", | ||
| 592 | ttm->num_pages << PAGE_SHIFT, | ||
| 593 | 0); | ||
| 594 | if (unlikely(IS_ERR(swap_storage))) { | ||
| 595 | printk(KERN_ERR "Failed allocating swap storage.\n"); | ||
| 596 | return -ENOMEM; | ||
| 597 | } | ||
| 598 | } else | ||
| 599 | swap_storage = persistant_swap_storage; | ||
| 600 | |||
| 601 | swap_space = swap_storage->f_path.dentry->d_inode->i_mapping; | ||
| 602 | |||
| 603 | for (i = 0; i < ttm->num_pages; ++i) { | ||
| 604 | from_page = ttm->pages[i]; | ||
| 605 | if (unlikely(from_page == NULL)) | ||
| 606 | continue; | ||
| 607 | to_page = read_mapping_page(swap_space, i, NULL); | ||
| 608 | if (unlikely(to_page == NULL)) | ||
| 609 | goto out_err; | ||
| 610 | |||
| 611 | preempt_disable(); | ||
| 612 | from_virtual = kmap_atomic(from_page, KM_USER0); | ||
| 613 | to_virtual = kmap_atomic(to_page, KM_USER1); | ||
| 614 | memcpy(to_virtual, from_virtual, PAGE_SIZE); | ||
| 615 | kunmap_atomic(to_virtual, KM_USER1); | ||
| 616 | kunmap_atomic(from_virtual, KM_USER0); | ||
| 617 | preempt_enable(); | ||
| 618 | set_page_dirty(to_page); | ||
| 619 | mark_page_accessed(to_page); | ||
| 620 | page_cache_release(to_page); | ||
| 621 | } | ||
| 622 | |||
| 623 | ttm_tt_free_alloced_pages(ttm); | ||
| 624 | ttm->swap_storage = swap_storage; | ||
| 625 | ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED; | ||
| 626 | if (persistant_swap_storage) | ||
| 627 | ttm->page_flags |= TTM_PAGE_FLAG_PERSISTANT_SWAP; | ||
| 628 | |||
| 629 | return 0; | ||
| 630 | out_err: | ||
| 631 | if (!persistant_swap_storage) | ||
| 632 | fput(swap_storage); | ||
| 633 | |||
| 634 | return -ENOMEM; | ||
| 635 | } | ||
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 0dcf9ca0b0ac..d0fcf36c2ab2 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
| @@ -115,5 +115,7 @@ source "drivers/staging/line6/Kconfig" | |||
| 115 | 115 | ||
| 116 | source "drivers/staging/serqt_usb/Kconfig" | 116 | source "drivers/staging/serqt_usb/Kconfig" |
| 117 | 117 | ||
| 118 | source "drivers/gpu/drm/radeon/Kconfig" | ||
| 119 | |||
| 118 | endif # !STAGING_EXCLUDE_BUILD | 120 | endif # !STAGING_EXCLUDE_BUILD |
| 119 | endif # STAGING | 121 | endif # STAGING |
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index f8634ab53b8f..45c18672b093 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h | |||
| @@ -254,8 +254,8 @@ | |||
| 254 | {0x1002, 0x940A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \ | 254 | {0x1002, 0x940A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \ |
| 255 | {0x1002, 0x940B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \ | 255 | {0x1002, 0x940B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \ |
| 256 | {0x1002, 0x940F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \ | 256 | {0x1002, 0x940F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R600|RADEON_NEW_MEMMAP}, \ |
| 257 | {0x1002, 0x94A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \ | 257 | {0x1002, 0x94A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 258 | {0x1002, 0x94A1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \ | 258 | {0x1002, 0x94A1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 259 | {0x1002, 0x94B1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \ | 259 | {0x1002, 0x94B1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \ |
| 260 | {0x1002, 0x94B3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \ | 260 | {0x1002, 0x94B3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \ |
| 261 | {0x1002, 0x94B5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \ | 261 | {0x1002, 0x94B5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV740|RADEON_NEW_MEMMAP}, \ |
| @@ -273,8 +273,8 @@ | |||
| 273 | {0x1002, 0x9456, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \ | 273 | {0x1002, 0x9456, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \ |
| 274 | {0x1002, 0x945A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ | 274 | {0x1002, 0x945A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 275 | {0x1002, 0x945B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ | 275 | {0x1002, 0x945B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 276 | {0x1002, 0x9460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ | 276 | {0x1002, 0x9460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \ |
| 277 | {0x1002, 0x9462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ | 277 | {0x1002, 0x9462, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_NEW_MEMMAP}, \ |
| 278 | {0x1002, 0x946A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ | 278 | {0x1002, 0x946A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 279 | {0x1002, 0x946B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ | 279 | {0x1002, 0x946B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
| 280 | {0x1002, 0x947A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ | 280 | {0x1002, 0x947A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ |
diff --git a/include/drm/radeon_drm.h b/include/drm/radeon_drm.h index fe3e3a4b4aed..41862e9a4c20 100644 --- a/include/drm/radeon_drm.h +++ b/include/drm/radeon_drm.h | |||
| @@ -496,6 +496,16 @@ typedef struct { | |||
| 496 | #define DRM_RADEON_SETPARAM 0x19 | 496 | #define DRM_RADEON_SETPARAM 0x19 |
| 497 | #define DRM_RADEON_SURF_ALLOC 0x1a | 497 | #define DRM_RADEON_SURF_ALLOC 0x1a |
| 498 | #define DRM_RADEON_SURF_FREE 0x1b | 498 | #define DRM_RADEON_SURF_FREE 0x1b |
| 499 | /* KMS ioctl */ | ||
| 500 | #define DRM_RADEON_GEM_INFO 0x1c | ||
| 501 | #define DRM_RADEON_GEM_CREATE 0x1d | ||
| 502 | #define DRM_RADEON_GEM_MMAP 0x1e | ||
| 503 | #define DRM_RADEON_GEM_PREAD 0x21 | ||
| 504 | #define DRM_RADEON_GEM_PWRITE 0x22 | ||
| 505 | #define DRM_RADEON_GEM_SET_DOMAIN 0x23 | ||
| 506 | #define DRM_RADEON_GEM_WAIT_IDLE 0x24 | ||
| 507 | #define DRM_RADEON_CS 0x26 | ||
| 508 | #define DRM_RADEON_INFO 0x27 | ||
| 499 | 509 | ||
| 500 | #define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t) | 510 | #define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t) |
| 501 | #define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START) | 511 | #define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START) |
| @@ -524,6 +534,17 @@ typedef struct { | |||
| 524 | #define DRM_IOCTL_RADEON_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t) | 534 | #define DRM_IOCTL_RADEON_SETPARAM DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SETPARAM, drm_radeon_setparam_t) |
| 525 | #define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t) | 535 | #define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t) |
| 526 | #define DRM_IOCTL_RADEON_SURF_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t) | 536 | #define DRM_IOCTL_RADEON_SURF_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t) |
| 537 | /* KMS */ | ||
| 538 | #define DRM_IOCTL_RADEON_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_INFO, struct drm_radeon_gem_info) | ||
| 539 | #define DRM_IOCTL_RADEON_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_CREATE, struct drm_radeon_gem_create) | ||
| 540 | #define DRM_IOCTL_RADEON_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_MMAP, struct drm_radeon_gem_mmap) | ||
| 541 | #define DRM_IOCTL_RADEON_GEM_PREAD DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PREAD, struct drm_radeon_gem_pread) | ||
| 542 | #define DRM_IOCTL_RADEON_GEM_PWRITE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PWRITE, struct drm_radeon_gem_pwrite) | ||
| 543 | #define DRM_IOCTL_RADEON_GEM_SET_DOMAIN DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_DOMAIN, struct drm_radeon_gem_set_domain) | ||
| 544 | #define DRM_IOCTL_RADEON_GEM_WAIT_IDLE DRM_IOW(DRM_COMMAND_BASE + DRM_RADEON_GEM_WAIT_IDLE, struct drm_radeon_gem_wait_idle) | ||
| 545 | #define DRM_IOCTL_RADEON_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs) | ||
| 546 | #define DRM_IOCTL_RADEON_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_INFO, struct drm_radeon_info) | ||
| 547 | |||
| 527 | 548 | ||
| 528 | typedef struct drm_radeon_init { | 549 | typedef struct drm_radeon_init { |
| 529 | enum { | 550 | enum { |
| @@ -682,6 +703,7 @@ typedef struct drm_radeon_indirect { | |||
| 682 | #define RADEON_PARAM_VBLANK_CRTC 13 /* VBLANK CRTC */ | 703 | #define RADEON_PARAM_VBLANK_CRTC 13 /* VBLANK CRTC */ |
| 683 | #define RADEON_PARAM_FB_LOCATION 14 /* FB location */ | 704 | #define RADEON_PARAM_FB_LOCATION 14 /* FB location */ |
| 684 | #define RADEON_PARAM_NUM_GB_PIPES 15 /* num GB pipes */ | 705 | #define RADEON_PARAM_NUM_GB_PIPES 15 /* num GB pipes */ |
| 706 | #define RADEON_PARAM_DEVICE_ID 16 | ||
| 685 | 707 | ||
| 686 | typedef struct drm_radeon_getparam { | 708 | typedef struct drm_radeon_getparam { |
| 687 | int param; | 709 | int param; |
| @@ -751,4 +773,112 @@ typedef struct drm_radeon_surface_free { | |||
| 751 | #define DRM_RADEON_VBLANK_CRTC1 1 | 773 | #define DRM_RADEON_VBLANK_CRTC1 1 |
| 752 | #define DRM_RADEON_VBLANK_CRTC2 2 | 774 | #define DRM_RADEON_VBLANK_CRTC2 2 |
| 753 | 775 | ||
| 776 | /* | ||
| 777 | * Kernel modesetting world below. | ||
| 778 | */ | ||
| 779 | #define RADEON_GEM_DOMAIN_CPU 0x1 | ||
| 780 | #define RADEON_GEM_DOMAIN_GTT 0x2 | ||
| 781 | #define RADEON_GEM_DOMAIN_VRAM 0x4 | ||
| 782 | |||
| 783 | struct drm_radeon_gem_info { | ||
| 784 | uint64_t gart_size; | ||
| 785 | uint64_t vram_size; | ||
| 786 | uint64_t vram_visible; | ||
| 787 | }; | ||
| 788 | |||
| 789 | #define RADEON_GEM_NO_BACKING_STORE 1 | ||
| 790 | |||
| 791 | struct drm_radeon_gem_create { | ||
| 792 | uint64_t size; | ||
| 793 | uint64_t alignment; | ||
| 794 | uint32_t handle; | ||
| 795 | uint32_t initial_domain; | ||
| 796 | uint32_t flags; | ||
| 797 | }; | ||
| 798 | |||
| 799 | struct drm_radeon_gem_mmap { | ||
| 800 | uint32_t handle; | ||
| 801 | uint32_t pad; | ||
| 802 | uint64_t offset; | ||
| 803 | uint64_t size; | ||
| 804 | uint64_t addr_ptr; | ||
| 805 | }; | ||
| 806 | |||
| 807 | struct drm_radeon_gem_set_domain { | ||
| 808 | uint32_t handle; | ||
| 809 | uint32_t read_domains; | ||
| 810 | uint32_t write_domain; | ||
| 811 | }; | ||
| 812 | |||
| 813 | struct drm_radeon_gem_wait_idle { | ||
| 814 | uint32_t handle; | ||
| 815 | uint32_t pad; | ||
| 816 | }; | ||
| 817 | |||
| 818 | struct drm_radeon_gem_busy { | ||
| 819 | uint32_t handle; | ||
| 820 | uint32_t busy; | ||
| 821 | }; | ||
| 822 | |||
| 823 | struct drm_radeon_gem_pread { | ||
| 824 | /** Handle for the object being read. */ | ||
| 825 | uint32_t handle; | ||
| 826 | uint32_t pad; | ||
| 827 | /** Offset into the object to read from */ | ||
| 828 | uint64_t offset; | ||
| 829 | /** Length of data to read */ | ||
| 830 | uint64_t size; | ||
| 831 | /** Pointer to write the data into. */ | ||
| 832 | /* void *, but pointers are not 32/64 compatible */ | ||
| 833 | uint64_t data_ptr; | ||
| 834 | }; | ||
| 835 | |||
| 836 | struct drm_radeon_gem_pwrite { | ||
| 837 | /** Handle for the object being written to. */ | ||
| 838 | uint32_t handle; | ||
| 839 | uint32_t pad; | ||
| 840 | /** Offset into the object to write to */ | ||
| 841 | uint64_t offset; | ||
| 842 | /** Length of data to write */ | ||
| 843 | uint64_t size; | ||
| 844 | /** Pointer to read the data from. */ | ||
| 845 | /* void *, but pointers are not 32/64 compatible */ | ||
| 846 | uint64_t data_ptr; | ||
| 847 | }; | ||
| 848 | |||
| 849 | #define RADEON_CHUNK_ID_RELOCS 0x01 | ||
| 850 | #define RADEON_CHUNK_ID_IB 0x02 | ||
| 851 | |||
| 852 | struct drm_radeon_cs_chunk { | ||
| 853 | uint32_t chunk_id; | ||
| 854 | uint32_t length_dw; | ||
| 855 | uint64_t chunk_data; | ||
| 856 | }; | ||
| 857 | |||
| 858 | struct drm_radeon_cs_reloc { | ||
| 859 | uint32_t handle; | ||
| 860 | uint32_t read_domains; | ||
| 861 | uint32_t write_domain; | ||
| 862 | uint32_t flags; | ||
| 863 | }; | ||
| 864 | |||
| 865 | struct drm_radeon_cs { | ||
| 866 | uint32_t num_chunks; | ||
| 867 | uint32_t cs_id; | ||
| 868 | /* this points to uint64_t * which point to cs chunks */ | ||
| 869 | uint64_t chunks; | ||
| 870 | /* updates to the limits after this CS ioctl */ | ||
| 871 | uint64_t gart_limit; | ||
| 872 | uint64_t vram_limit; | ||
| 873 | }; | ||
| 874 | |||
| 875 | #define RADEON_INFO_DEVICE_ID 0x00 | ||
| 876 | #define RADEON_INFO_NUM_GB_PIPES 0x01 | ||
| 877 | |||
| 878 | struct drm_radeon_info { | ||
| 879 | uint32_t request; | ||
| 880 | uint32_t pad; | ||
| 881 | uint64_t value; | ||
| 882 | }; | ||
| 883 | |||
| 754 | #endif | 884 | #endif |
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h new file mode 100644 index 000000000000..cd22ab4b495c --- /dev/null +++ b/include/drm/ttm/ttm_bo_api.h | |||
| @@ -0,0 +1,618 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | **************************************************************************/ | ||
| 27 | /* | ||
| 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | ||
| 29 | */ | ||
| 30 | |||
| 31 | #ifndef _TTM_BO_API_H_ | ||
| 32 | #define _TTM_BO_API_H_ | ||
| 33 | |||
| 34 | #include "drm_hashtab.h" | ||
| 35 | #include <linux/kref.h> | ||
| 36 | #include <linux/list.h> | ||
| 37 | #include <linux/wait.h> | ||
| 38 | #include <linux/mutex.h> | ||
| 39 | #include <linux/mm.h> | ||
| 40 | #include <linux/rbtree.h> | ||
| 41 | #include <linux/bitmap.h> | ||
| 42 | |||
| 43 | struct ttm_bo_device; | ||
| 44 | |||
| 45 | struct drm_mm_node; | ||
| 46 | |||
| 47 | /** | ||
| 48 | * struct ttm_mem_reg | ||
| 49 | * | ||
| 50 | * @mm_node: Memory manager node. | ||
| 51 | * @size: Requested size of memory region. | ||
| 52 | * @num_pages: Actual size of memory region in pages. | ||
| 53 | * @page_alignment: Page alignment. | ||
| 54 | * @placement: Placement flags. | ||
| 55 | * | ||
| 56 | * Structure indicating the placement and space resources used by a | ||
| 57 | * buffer object. | ||
| 58 | */ | ||
| 59 | |||
| 60 | struct ttm_mem_reg { | ||
| 61 | struct drm_mm_node *mm_node; | ||
| 62 | unsigned long size; | ||
| 63 | unsigned long num_pages; | ||
| 64 | uint32_t page_alignment; | ||
| 65 | uint32_t mem_type; | ||
| 66 | uint32_t placement; | ||
| 67 | }; | ||
| 68 | |||
| 69 | /** | ||
| 70 | * enum ttm_bo_type | ||
| 71 | * | ||
| 72 | * @ttm_bo_type_device: These are 'normal' buffers that can | ||
| 73 | * be mmapped by user space. Each of these bos occupy a slot in the | ||
| 74 | * device address space, that can be used for normal vm operations. | ||
| 75 | * | ||
| 76 | * @ttm_bo_type_user: These are user-space memory areas that are made | ||
| 77 | * available to the GPU by mapping the buffer pages into the GPU aperture | ||
| 78 | * space. These buffers cannot be mmaped from the device address space. | ||
| 79 | * | ||
| 80 | * @ttm_bo_type_kernel: These buffers are like ttm_bo_type_device buffers, | ||
| 81 | * but they cannot be accessed from user-space. For kernel-only use. | ||
| 82 | */ | ||
| 83 | |||
| 84 | enum ttm_bo_type { | ||
| 85 | ttm_bo_type_device, | ||
| 86 | ttm_bo_type_user, | ||
| 87 | ttm_bo_type_kernel | ||
| 88 | }; | ||
| 89 | |||
| 90 | struct ttm_tt; | ||
| 91 | |||
| 92 | /** | ||
| 93 | * struct ttm_buffer_object | ||
| 94 | * | ||
| 95 | * @bdev: Pointer to the buffer object device structure. | ||
| 96 | * @buffer_start: The virtual user-space start address of ttm_bo_type_user | ||
| 97 | * buffers. | ||
| 98 | * @type: The bo type. | ||
| 99 | * @destroy: Destruction function. If NULL, kfree is used. | ||
| 100 | * @num_pages: Actual number of pages. | ||
| 101 | * @addr_space_offset: Address space offset. | ||
| 102 | * @acc_size: Accounted size for this object. | ||
| 103 | * @kref: Reference count of this buffer object. When this refcount reaches | ||
| 104 | * zero, the object is put on the delayed delete list. | ||
| 105 | * @list_kref: List reference count of this buffer object. This member is | ||
| 106 | * used to avoid destruction while the buffer object is still on a list. | ||
| 107 | * Lru lists may keep one refcount, the delayed delete list, and kref != 0 | ||
| 108 | * keeps one refcount. When this refcount reaches zero, | ||
| 109 | * the object is destroyed. | ||
| 110 | * @event_queue: Queue for processes waiting on buffer object status change. | ||
| 111 | * @lock: spinlock protecting mostly synchronization members. | ||
| 112 | * @proposed_placement: Proposed placement for the buffer. Changed only by the | ||
| 113 | * creator prior to validation as opposed to bo->mem.proposed_flags which is | ||
| 114 | * changed by the implementation prior to a buffer move if it wants to outsmart | ||
| 115 | * the buffer creator / user. This latter happens, for example, at eviction. | ||
| 116 | * @mem: structure describing current placement. | ||
| 117 | * @persistant_swap_storage: Usually the swap storage is deleted for buffers | ||
| 118 | * pinned in physical memory. If this behaviour is not desired, this member | ||
| 119 | * holds a pointer to a persistant shmem object. | ||
| 120 | * @ttm: TTM structure holding system pages. | ||
| 121 | * @evicted: Whether the object was evicted without user-space knowing. | ||
| 122 | * @cpu_writes: For synchronization. Number of cpu writers. | ||
| 123 | * @lru: List head for the lru list. | ||
| 124 | * @ddestroy: List head for the delayed destroy list. | ||
| 125 | * @swap: List head for swap LRU list. | ||
| 126 | * @val_seq: Sequence of the validation holding the @reserved lock. | ||
| 127 | * Used to avoid starvation when many processes compete to validate the | ||
| 128 | * buffer. This member is protected by the bo_device::lru_lock. | ||
| 129 | * @seq_valid: The value of @val_seq is valid. This value is protected by | ||
| 130 | * the bo_device::lru_lock. | ||
| 131 | * @reserved: Deadlock-free lock used for synchronization state transitions. | ||
| 132 | * @sync_obj_arg: Opaque argument to synchronization object function. | ||
| 133 | * @sync_obj: Pointer to a synchronization object. | ||
| 134 | * @priv_flags: Flags describing buffer object internal state. | ||
| 135 | * @vm_rb: Rb node for the vm rb tree. | ||
| 136 | * @vm_node: Address space manager node. | ||
| 137 | * @offset: The current GPU offset, which can have different meanings | ||
| 138 | * depending on the memory type. For SYSTEM type memory, it should be 0. | ||
| 139 | * @cur_placement: Hint of current placement. | ||
| 140 | * | ||
| 141 | * Base class for TTM buffer object, that deals with data placement and CPU | ||
| 142 | * mappings. GPU mappings are really up to the driver, but for simpler GPUs | ||
| 143 | * the driver can usually use the placement offset @offset directly as the | ||
| 144 | * GPU virtual address. For drivers implementing multiple | ||
| 145 | * GPU memory manager contexts, the driver should manage the address space | ||
| 146 | * in these contexts separately and use these objects to get the correct | ||
| 147 | * placement and caching for these GPU maps. This makes it possible to use | ||
| 148 | * these objects for even quite elaborate memory management schemes. | ||
| 149 | * The destroy member, the API visibility of this object makes it possible | ||
| 150 | * to derive driver specific types. | ||
| 151 | */ | ||
| 152 | |||
| 153 | struct ttm_buffer_object { | ||
| 154 | /** | ||
| 155 | * Members constant at init. | ||
| 156 | */ | ||
| 157 | |||
| 158 | struct ttm_bo_device *bdev; | ||
| 159 | unsigned long buffer_start; | ||
| 160 | enum ttm_bo_type type; | ||
| 161 | void (*destroy) (struct ttm_buffer_object *); | ||
| 162 | unsigned long num_pages; | ||
| 163 | uint64_t addr_space_offset; | ||
| 164 | size_t acc_size; | ||
| 165 | |||
| 166 | /** | ||
| 167 | * Members not needing protection. | ||
| 168 | */ | ||
| 169 | |||
| 170 | struct kref kref; | ||
| 171 | struct kref list_kref; | ||
| 172 | wait_queue_head_t event_queue; | ||
| 173 | spinlock_t lock; | ||
| 174 | |||
| 175 | /** | ||
| 176 | * Members protected by the bo::reserved lock. | ||
| 177 | */ | ||
| 178 | |||
| 179 | uint32_t proposed_placement; | ||
| 180 | struct ttm_mem_reg mem; | ||
| 181 | struct file *persistant_swap_storage; | ||
| 182 | struct ttm_tt *ttm; | ||
| 183 | bool evicted; | ||
| 184 | |||
| 185 | /** | ||
| 186 | * Members protected by the bo::reserved lock only when written to. | ||
| 187 | */ | ||
| 188 | |||
| 189 | atomic_t cpu_writers; | ||
| 190 | |||
| 191 | /** | ||
| 192 | * Members protected by the bdev::lru_lock. | ||
| 193 | */ | ||
| 194 | |||
| 195 | struct list_head lru; | ||
| 196 | struct list_head ddestroy; | ||
| 197 | struct list_head swap; | ||
| 198 | uint32_t val_seq; | ||
| 199 | bool seq_valid; | ||
| 200 | |||
| 201 | /** | ||
| 202 | * Members protected by the bdev::lru_lock | ||
| 203 | * only when written to. | ||
| 204 | */ | ||
| 205 | |||
| 206 | atomic_t reserved; | ||
| 207 | |||
| 208 | |||
| 209 | /** | ||
| 210 | * Members protected by the bo::lock | ||
| 211 | */ | ||
| 212 | |||
| 213 | void *sync_obj_arg; | ||
| 214 | void *sync_obj; | ||
| 215 | unsigned long priv_flags; | ||
| 216 | |||
| 217 | /** | ||
| 218 | * Members protected by the bdev::vm_lock | ||
| 219 | */ | ||
| 220 | |||
| 221 | struct rb_node vm_rb; | ||
| 222 | struct drm_mm_node *vm_node; | ||
| 223 | |||
| 224 | |||
| 225 | /** | ||
| 226 | * Special members that are protected by the reserve lock | ||
| 227 | * and the bo::lock when written to. Can be read with | ||
| 228 | * either of these locks held. | ||
| 229 | */ | ||
| 230 | |||
| 231 | unsigned long offset; | ||
| 232 | uint32_t cur_placement; | ||
| 233 | }; | ||
| 234 | |||
| 235 | /** | ||
| 236 | * struct ttm_bo_kmap_obj | ||
| 237 | * | ||
| 238 | * @virtual: The current kernel virtual address. | ||
| 239 | * @page: The page when kmap'ing a single page. | ||
| 240 | * @bo_kmap_type: Type of bo_kmap. | ||
| 241 | * | ||
| 242 | * Object describing a kernel mapping. Since a TTM bo may be located | ||
| 243 | * in various memory types with various caching policies, the | ||
| 244 | * mapping can either be an ioremap, a vmap, a kmap or part of a | ||
| 245 | * premapped region. | ||
| 246 | */ | ||
| 247 | |||
| 248 | struct ttm_bo_kmap_obj { | ||
| 249 | void *virtual; | ||
| 250 | struct page *page; | ||
| 251 | enum { | ||
| 252 | ttm_bo_map_iomap, | ||
| 253 | ttm_bo_map_vmap, | ||
| 254 | ttm_bo_map_kmap, | ||
| 255 | ttm_bo_map_premapped, | ||
| 256 | } bo_kmap_type; | ||
| 257 | }; | ||
| 258 | |||
| 259 | /** | ||
| 260 | * ttm_bo_reference - reference a struct ttm_buffer_object | ||
| 261 | * | ||
| 262 | * @bo: The buffer object. | ||
| 263 | * | ||
| 264 | * Returns a refcounted pointer to a buffer object. | ||
| 265 | */ | ||
| 266 | |||
| 267 | static inline struct ttm_buffer_object * | ||
| 268 | ttm_bo_reference(struct ttm_buffer_object *bo) | ||
| 269 | { | ||
| 270 | kref_get(&bo->kref); | ||
| 271 | return bo; | ||
| 272 | } | ||
| 273 | |||
| 274 | /** | ||
| 275 | * ttm_bo_wait - wait for buffer idle. | ||
| 276 | * | ||
| 277 | * @bo: The buffer object. | ||
| 278 | * @interruptible: Use interruptible wait. | ||
| 279 | * @no_wait: Return immediately if buffer is busy. | ||
| 280 | * | ||
| 281 | * This function must be called with the bo::mutex held, and makes | ||
| 282 | * sure any previous rendering to the buffer is completed. | ||
| 283 | * Note: It might be necessary to block validations before the | ||
| 284 | * wait by reserving the buffer. | ||
| 285 | * Returns -EBUSY if no_wait is true and the buffer is busy. | ||
| 286 | * Returns -ERESTART if interrupted by a signal. | ||
| 287 | */ | ||
| 288 | extern int ttm_bo_wait(struct ttm_buffer_object *bo, bool lazy, | ||
| 289 | bool interruptible, bool no_wait); | ||
| 290 | /** | ||
| 291 | * ttm_buffer_object_validate | ||
| 292 | * | ||
| 293 | * @bo: The buffer object. | ||
| 294 | * @proposed_placement: Proposed_placement for the buffer object. | ||
| 295 | * @interruptible: Sleep interruptible if sleeping. | ||
| 296 | * @no_wait: Return immediately if the buffer is busy. | ||
| 297 | * | ||
| 298 | * Changes placement and caching policy of the buffer object | ||
| 299 | * according to bo::proposed_flags. | ||
| 300 | * Returns | ||
| 301 | * -EINVAL on invalid proposed_flags. | ||
| 302 | * -ENOMEM on out-of-memory condition. | ||
| 303 | * -EBUSY if no_wait is true and buffer busy. | ||
| 304 | * -ERESTART if interrupted by a signal. | ||
| 305 | */ | ||
| 306 | extern int ttm_buffer_object_validate(struct ttm_buffer_object *bo, | ||
| 307 | uint32_t proposed_placement, | ||
| 308 | bool interruptible, bool no_wait); | ||
| 309 | /** | ||
| 310 | * ttm_bo_unref | ||
| 311 | * | ||
| 312 | * @bo: The buffer object. | ||
| 313 | * | ||
| 314 | * Unreference and clear a pointer to a buffer object. | ||
| 315 | */ | ||
| 316 | extern void ttm_bo_unref(struct ttm_buffer_object **bo); | ||
| 317 | |||
| 318 | /** | ||
| 319 | * ttm_bo_synccpu_write_grab | ||
| 320 | * | ||
| 321 | * @bo: The buffer object: | ||
| 322 | * @no_wait: Return immediately if buffer is busy. | ||
| 323 | * | ||
| 324 | * Synchronizes a buffer object for CPU RW access. This means | ||
| 325 | * blocking command submission that affects the buffer and | ||
| 326 | * waiting for buffer idle. This lock is recursive. | ||
| 327 | * Returns | ||
| 328 | * -EBUSY if the buffer is busy and no_wait is true. | ||
| 329 | * -ERESTART if interrupted by a signal. | ||
| 330 | */ | ||
| 331 | |||
| 332 | extern int | ||
| 333 | ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait); | ||
| 334 | /** | ||
| 335 | * ttm_bo_synccpu_write_release: | ||
| 336 | * | ||
| 337 | * @bo : The buffer object. | ||
| 338 | * | ||
| 339 | * Releases a synccpu lock. | ||
| 340 | */ | ||
| 341 | extern void ttm_bo_synccpu_write_release(struct ttm_buffer_object *bo); | ||
| 342 | |||
| 343 | /** | ||
| 344 | * ttm_buffer_object_init | ||
| 345 | * | ||
| 346 | * @bdev: Pointer to a ttm_bo_device struct. | ||
| 347 | * @bo: Pointer to a ttm_buffer_object to be initialized. | ||
| 348 | * @size: Requested size of buffer object. | ||
| 349 | * @type: Requested type of buffer object. | ||
| 350 | * @flags: Initial placement flags. | ||
| 351 | * @page_alignment: Data alignment in pages. | ||
| 352 | * @buffer_start: Virtual address of user space data backing a | ||
| 353 | * user buffer object. | ||
| 354 | * @interruptible: If needing to sleep to wait for GPU resources, | ||
| 355 | * sleep interruptible. | ||
| 356 | * @persistant_swap_storage: Usually the swap storage is deleted for buffers | ||
| 357 | * pinned in physical memory. If this behaviour is not desired, this member | ||
| 358 | * holds a pointer to a persistant shmem object. Typically, this would | ||
| 359 | * point to the shmem object backing a GEM object if TTM is used to back a | ||
| 360 | * GEM user interface. | ||
| 361 | * @acc_size: Accounted size for this object. | ||
| 362 | * @destroy: Destroy function. Use NULL for kfree(). | ||
| 363 | * | ||
| 364 | * This function initializes a pre-allocated struct ttm_buffer_object. | ||
| 365 | * As this object may be part of a larger structure, this function, | ||
| 366 | * together with the @destroy function, | ||
| 367 | * enables driver-specific objects derived from a ttm_buffer_object. | ||
| 368 | * On successful return, the object kref and list_kref are set to 1. | ||
| 369 | * Returns | ||
| 370 | * -ENOMEM: Out of memory. | ||
| 371 | * -EINVAL: Invalid placement flags. | ||
| 372 | * -ERESTART: Interrupted by signal while sleeping waiting for resources. | ||
| 373 | */ | ||
| 374 | |||
| 375 | extern int ttm_buffer_object_init(struct ttm_bo_device *bdev, | ||
| 376 | struct ttm_buffer_object *bo, | ||
| 377 | unsigned long size, | ||
| 378 | enum ttm_bo_type type, | ||
| 379 | uint32_t flags, | ||
| 380 | uint32_t page_alignment, | ||
| 381 | unsigned long buffer_start, | ||
| 382 | bool interrubtible, | ||
| 383 | struct file *persistant_swap_storage, | ||
| 384 | size_t acc_size, | ||
| 385 | void (*destroy) (struct ttm_buffer_object *)); | ||
| 386 | /** | ||
| 387 | * ttm_bo_synccpu_object_init | ||
| 388 | * | ||
| 389 | * @bdev: Pointer to a ttm_bo_device struct. | ||
| 390 | * @bo: Pointer to a ttm_buffer_object to be initialized. | ||
| 391 | * @size: Requested size of buffer object. | ||
| 392 | * @type: Requested type of buffer object. | ||
| 393 | * @flags: Initial placement flags. | ||
| 394 | * @page_alignment: Data alignment in pages. | ||
| 395 | * @buffer_start: Virtual address of user space data backing a | ||
| 396 | * user buffer object. | ||
| 397 | * @interruptible: If needing to sleep while waiting for GPU resources, | ||
| 398 | * sleep interruptible. | ||
| 399 | * @persistant_swap_storage: Usually the swap storage is deleted for buffers | ||
| 400 | * pinned in physical memory. If this behaviour is not desired, this member | ||
| 401 | * holds a pointer to a persistant shmem object. Typically, this would | ||
| 402 | * point to the shmem object backing a GEM object if TTM is used to back a | ||
| 403 | * GEM user interface. | ||
| 404 | * @p_bo: On successful completion *p_bo points to the created object. | ||
| 405 | * | ||
| 406 | * This function allocates a ttm_buffer_object, and then calls | ||
| 407 | * ttm_buffer_object_init on that object. | ||
| 408 | * The destroy function is set to kfree(). | ||
| 409 | * Returns | ||
| 410 | * -ENOMEM: Out of memory. | ||
| 411 | * -EINVAL: Invalid placement flags. | ||
| 412 | * -ERESTART: Interrupted by signal while waiting for resources. | ||
| 413 | */ | ||
| 414 | |||
| 415 | extern int ttm_buffer_object_create(struct ttm_bo_device *bdev, | ||
| 416 | unsigned long size, | ||
| 417 | enum ttm_bo_type type, | ||
| 418 | uint32_t flags, | ||
| 419 | uint32_t page_alignment, | ||
| 420 | unsigned long buffer_start, | ||
| 421 | bool interruptible, | ||
| 422 | struct file *persistant_swap_storage, | ||
| 423 | struct ttm_buffer_object **p_bo); | ||
| 424 | |||
| 425 | /** | ||
| 426 | * ttm_bo_check_placement | ||
| 427 | * | ||
| 428 | * @bo: the buffer object. | ||
| 429 | * @set_flags: placement flags to set. | ||
| 430 | * @clr_flags: placement flags to clear. | ||
| 431 | * | ||
| 432 | * Performs minimal validity checking on an intended change of | ||
| 433 | * placement flags. | ||
| 434 | * Returns | ||
| 435 | * -EINVAL: Intended change is invalid or not allowed. | ||
| 436 | */ | ||
| 437 | |||
| 438 | extern int ttm_bo_check_placement(struct ttm_buffer_object *bo, | ||
| 439 | uint32_t set_flags, uint32_t clr_flags); | ||
| 440 | |||
| 441 | /** | ||
| 442 | * ttm_bo_init_mm | ||
| 443 | * | ||
| 444 | * @bdev: Pointer to a ttm_bo_device struct. | ||
| 445 | * @mem_type: The memory type. | ||
| 446 | * @p_offset: offset for managed area in pages. | ||
| 447 | * @p_size: size managed area in pages. | ||
| 448 | * | ||
| 449 | * Initialize a manager for a given memory type. | ||
| 450 | * Note: if part of driver firstopen, it must be protected from a | ||
| 451 | * potentially racing lastclose. | ||
| 452 | * Returns: | ||
| 453 | * -EINVAL: invalid size or memory type. | ||
| 454 | * -ENOMEM: Not enough memory. | ||
| 455 | * May also return driver-specified errors. | ||
| 456 | */ | ||
| 457 | |||
| 458 | extern int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type, | ||
| 459 | unsigned long p_offset, unsigned long p_size); | ||
| 460 | /** | ||
| 461 | * ttm_bo_clean_mm | ||
| 462 | * | ||
| 463 | * @bdev: Pointer to a ttm_bo_device struct. | ||
| 464 | * @mem_type: The memory type. | ||
| 465 | * | ||
| 466 | * Take down a manager for a given memory type after first walking | ||
| 467 | * the LRU list to evict any buffers left alive. | ||
| 468 | * | ||
| 469 | * Normally, this function is part of lastclose() or unload(), and at that | ||
| 470 | * point there shouldn't be any buffers left created by user-space, since | ||
| 471 | * there should've been removed by the file descriptor release() method. | ||
| 472 | * However, before this function is run, make sure to signal all sync objects, | ||
| 473 | * and verify that the delayed delete queue is empty. The driver must also | ||
| 474 | * make sure that there are no NO_EVICT buffers present in this memory type | ||
| 475 | * when the call is made. | ||
| 476 | * | ||
| 477 | * If this function is part of a VT switch, the caller must make sure that | ||
| 478 | * there are no appications currently validating buffers before this | ||
| 479 | * function is called. The caller can do that by first taking the | ||
| 480 | * struct ttm_bo_device::ttm_lock in write mode. | ||
| 481 | * | ||
| 482 | * Returns: | ||
| 483 | * -EINVAL: invalid or uninitialized memory type. | ||
| 484 | * -EBUSY: There are still buffers left in this memory type. | ||
| 485 | */ | ||
| 486 | |||
| 487 | extern int ttm_bo_clean_mm(struct ttm_bo_device *bdev, unsigned mem_type); | ||
| 488 | |||
| 489 | /** | ||
| 490 | * ttm_bo_evict_mm | ||
| 491 | * | ||
| 492 | * @bdev: Pointer to a ttm_bo_device struct. | ||
| 493 | * @mem_type: The memory type. | ||
| 494 | * | ||
| 495 | * Evicts all buffers on the lru list of the memory type. | ||
| 496 | * This is normally part of a VT switch or an | ||
| 497 | * out-of-memory-space-due-to-fragmentation handler. | ||
| 498 | * The caller must make sure that there are no other processes | ||
| 499 | * currently validating buffers, and can do that by taking the | ||
| 500 | * struct ttm_bo_device::ttm_lock in write mode. | ||
| 501 | * | ||
| 502 | * Returns: | ||
| 503 | * -EINVAL: Invalid or uninitialized memory type. | ||
| 504 | * -ERESTART: The call was interrupted by a signal while waiting to | ||
| 505 | * evict a buffer. | ||
| 506 | */ | ||
| 507 | |||
| 508 | extern int ttm_bo_evict_mm(struct ttm_bo_device *bdev, unsigned mem_type); | ||
| 509 | |||
| 510 | /** | ||
| 511 | * ttm_kmap_obj_virtual | ||
| 512 | * | ||
| 513 | * @map: A struct ttm_bo_kmap_obj returned from ttm_bo_kmap. | ||
| 514 | * @is_iomem: Pointer to an integer that on return indicates 1 if the | ||
| 515 | * virtual map is io memory, 0 if normal memory. | ||
| 516 | * | ||
| 517 | * Returns the virtual address of a buffer object area mapped by ttm_bo_kmap. | ||
| 518 | * If *is_iomem is 1 on return, the virtual address points to an io memory area, | ||
| 519 | * that should strictly be accessed by the iowriteXX() and similar functions. | ||
| 520 | */ | ||
| 521 | |||
| 522 | static inline void *ttm_kmap_obj_virtual(struct ttm_bo_kmap_obj *map, | ||
| 523 | bool *is_iomem) | ||
| 524 | { | ||
| 525 | *is_iomem = (map->bo_kmap_type == ttm_bo_map_iomap || | ||
| 526 | map->bo_kmap_type == ttm_bo_map_premapped); | ||
| 527 | return map->virtual; | ||
| 528 | } | ||
| 529 | |||
| 530 | /** | ||
| 531 | * ttm_bo_kmap | ||
| 532 | * | ||
| 533 | * @bo: The buffer object. | ||
| 534 | * @start_page: The first page to map. | ||
| 535 | * @num_pages: Number of pages to map. | ||
| 536 | * @map: pointer to a struct ttm_bo_kmap_obj representing the map. | ||
| 537 | * | ||
| 538 | * Sets up a kernel virtual mapping, using ioremap, vmap or kmap to the | ||
| 539 | * data in the buffer object. The ttm_kmap_obj_virtual function can then be | ||
| 540 | * used to obtain a virtual address to the data. | ||
| 541 | * | ||
| 542 | * Returns | ||
| 543 | * -ENOMEM: Out of memory. | ||
| 544 | * -EINVAL: Invalid range. | ||
| 545 | */ | ||
| 546 | |||
| 547 | extern int ttm_bo_kmap(struct ttm_buffer_object *bo, unsigned long start_page, | ||
| 548 | unsigned long num_pages, struct ttm_bo_kmap_obj *map); | ||
| 549 | |||
| 550 | /** | ||
| 551 | * ttm_bo_kunmap | ||
| 552 | * | ||
| 553 | * @map: Object describing the map to unmap. | ||
| 554 | * | ||
| 555 | * Unmaps a kernel map set up by ttm_bo_kmap. | ||
| 556 | */ | ||
| 557 | |||
| 558 | extern void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map); | ||
| 559 | |||
| 560 | #if 0 | ||
| 561 | #endif | ||
| 562 | |||
| 563 | /** | ||
| 564 | * ttm_fbdev_mmap - mmap fbdev memory backed by a ttm buffer object. | ||
| 565 | * | ||
| 566 | * @vma: vma as input from the fbdev mmap method. | ||
| 567 | * @bo: The bo backing the address space. The address space will | ||
| 568 | * have the same size as the bo, and start at offset 0. | ||
| 569 | * | ||
| 570 | * This function is intended to be called by the fbdev mmap method | ||
| 571 | * if the fbdev address space is to be backed by a bo. | ||
| 572 | */ | ||
| 573 | |||
| 574 | extern int ttm_fbdev_mmap(struct vm_area_struct *vma, | ||
| 575 | struct ttm_buffer_object *bo); | ||
| 576 | |||
| 577 | /** | ||
| 578 | * ttm_bo_mmap - mmap out of the ttm device address space. | ||
| 579 | * | ||
| 580 | * @filp: filp as input from the mmap method. | ||
| 581 | * @vma: vma as input from the mmap method. | ||
| 582 | * @bdev: Pointer to the ttm_bo_device with the address space manager. | ||
| 583 | * | ||
| 584 | * This function is intended to be called by the device mmap method. | ||
| 585 | * if the device address space is to be backed by the bo manager. | ||
| 586 | */ | ||
| 587 | |||
| 588 | extern int ttm_bo_mmap(struct file *filp, struct vm_area_struct *vma, | ||
| 589 | struct ttm_bo_device *bdev); | ||
| 590 | |||
| 591 | /** | ||
| 592 | * ttm_bo_io | ||
| 593 | * | ||
| 594 | * @bdev: Pointer to the struct ttm_bo_device. | ||
| 595 | * @filp: Pointer to the struct file attempting to read / write. | ||
| 596 | * @wbuf: User-space pointer to address of buffer to write. NULL on read. | ||
| 597 | * @rbuf: User-space pointer to address of buffer to read into. | ||
| 598 | * Null on write. | ||
| 599 | * @count: Number of bytes to read / write. | ||
| 600 | * @f_pos: Pointer to current file position. | ||
| 601 | * @write: 1 for read, 0 for write. | ||
| 602 | * | ||
| 603 | * This function implements read / write into ttm buffer objects, and is | ||
| 604 | * intended to | ||
| 605 | * be called from the fops::read and fops::write method. | ||
| 606 | * Returns: | ||
| 607 | * See man (2) write, man(2) read. In particular, | ||
| 608 | * the function may return -EINTR if | ||
| 609 | * interrupted by a signal. | ||
| 610 | */ | ||
| 611 | |||
| 612 | extern ssize_t ttm_bo_io(struct ttm_bo_device *bdev, struct file *filp, | ||
| 613 | const char __user *wbuf, char __user *rbuf, | ||
| 614 | size_t count, loff_t *f_pos, bool write); | ||
| 615 | |||
| 616 | extern void ttm_bo_swapout_all(struct ttm_bo_device *bdev); | ||
| 617 | |||
| 618 | #endif | ||
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h new file mode 100644 index 000000000000..62ed733c52a2 --- /dev/null +++ b/include/drm/ttm/ttm_bo_driver.h | |||
| @@ -0,0 +1,867 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright (c) 2006-2009 Vmware, Inc., Palo Alto, CA., USA | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | **************************************************************************/ | ||
| 27 | /* | ||
| 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | ||
| 29 | */ | ||
| 30 | #ifndef _TTM_BO_DRIVER_H_ | ||
| 31 | #define _TTM_BO_DRIVER_H_ | ||
| 32 | |||
| 33 | #include "ttm/ttm_bo_api.h" | ||
| 34 | #include "ttm/ttm_memory.h" | ||
| 35 | #include "drm_mm.h" | ||
| 36 | #include "linux/workqueue.h" | ||
| 37 | #include "linux/fs.h" | ||
| 38 | #include "linux/spinlock.h" | ||
| 39 | |||
| 40 | struct ttm_backend; | ||
| 41 | |||
| 42 | struct ttm_backend_func { | ||
| 43 | /** | ||
| 44 | * struct ttm_backend_func member populate | ||
| 45 | * | ||
| 46 | * @backend: Pointer to a struct ttm_backend. | ||
| 47 | * @num_pages: Number of pages to populate. | ||
| 48 | * @pages: Array of pointers to ttm pages. | ||
| 49 | * @dummy_read_page: Page to be used instead of NULL pages in the | ||
| 50 | * array @pages. | ||
| 51 | * | ||
| 52 | * Populate the backend with ttm pages. Depending on the backend, | ||
| 53 | * it may or may not copy the @pages array. | ||
| 54 | */ | ||
| 55 | int (*populate) (struct ttm_backend *backend, | ||
| 56 | unsigned long num_pages, struct page **pages, | ||
| 57 | struct page *dummy_read_page); | ||
| 58 | /** | ||
| 59 | * struct ttm_backend_func member clear | ||
| 60 | * | ||
| 61 | * @backend: Pointer to a struct ttm_backend. | ||
| 62 | * | ||
| 63 | * This is an "unpopulate" function. Release all resources | ||
| 64 | * allocated with populate. | ||
| 65 | */ | ||
| 66 | void (*clear) (struct ttm_backend *backend); | ||
| 67 | |||
| 68 | /** | ||
| 69 | * struct ttm_backend_func member bind | ||
| 70 | * | ||
| 71 | * @backend: Pointer to a struct ttm_backend. | ||
| 72 | * @bo_mem: Pointer to a struct ttm_mem_reg describing the | ||
| 73 | * memory type and location for binding. | ||
| 74 | * | ||
| 75 | * Bind the backend pages into the aperture in the location | ||
| 76 | * indicated by @bo_mem. This function should be able to handle | ||
| 77 | * differences between aperture- and system page sizes. | ||
| 78 | */ | ||
| 79 | int (*bind) (struct ttm_backend *backend, struct ttm_mem_reg *bo_mem); | ||
| 80 | |||
| 81 | /** | ||
| 82 | * struct ttm_backend_func member unbind | ||
| 83 | * | ||
| 84 | * @backend: Pointer to a struct ttm_backend. | ||
| 85 | * | ||
| 86 | * Unbind previously bound backend pages. This function should be | ||
| 87 | * able to handle differences between aperture- and system page sizes. | ||
| 88 | */ | ||
| 89 | int (*unbind) (struct ttm_backend *backend); | ||
| 90 | |||
| 91 | /** | ||
| 92 | * struct ttm_backend_func member destroy | ||
| 93 | * | ||
| 94 | * @backend: Pointer to a struct ttm_backend. | ||
| 95 | * | ||
| 96 | * Destroy the backend. | ||
| 97 | */ | ||
| 98 | void (*destroy) (struct ttm_backend *backend); | ||
| 99 | }; | ||
| 100 | |||
| 101 | /** | ||
| 102 | * struct ttm_backend | ||
| 103 | * | ||
| 104 | * @bdev: Pointer to a struct ttm_bo_device. | ||
| 105 | * @flags: For driver use. | ||
| 106 | * @func: Pointer to a struct ttm_backend_func that describes | ||
| 107 | * the backend methods. | ||
| 108 | * | ||
| 109 | */ | ||
| 110 | |||
| 111 | struct ttm_backend { | ||
| 112 | struct ttm_bo_device *bdev; | ||
| 113 | uint32_t flags; | ||
| 114 | struct ttm_backend_func *func; | ||
| 115 | }; | ||
| 116 | |||
| 117 | #define TTM_PAGE_FLAG_VMALLOC (1 << 0) | ||
| 118 | #define TTM_PAGE_FLAG_USER (1 << 1) | ||
| 119 | #define TTM_PAGE_FLAG_USER_DIRTY (1 << 2) | ||
| 120 | #define TTM_PAGE_FLAG_WRITE (1 << 3) | ||
| 121 | #define TTM_PAGE_FLAG_SWAPPED (1 << 4) | ||
| 122 | #define TTM_PAGE_FLAG_PERSISTANT_SWAP (1 << 5) | ||
| 123 | #define TTM_PAGE_FLAG_ZERO_ALLOC (1 << 6) | ||
| 124 | |||
| 125 | enum ttm_caching_state { | ||
| 126 | tt_uncached, | ||
| 127 | tt_wc, | ||
| 128 | tt_cached | ||
| 129 | }; | ||
| 130 | |||
| 131 | /** | ||
| 132 | * struct ttm_tt | ||
| 133 | * | ||
| 134 | * @dummy_read_page: Page to map where the ttm_tt page array contains a NULL | ||
| 135 | * pointer. | ||
| 136 | * @pages: Array of pages backing the data. | ||
| 137 | * @first_himem_page: Himem pages are put last in the page array, which | ||
| 138 | * enables us to run caching attribute changes on only the first part | ||
| 139 | * of the page array containing lomem pages. This is the index of the | ||
| 140 | * first himem page. | ||
| 141 | * @last_lomem_page: Index of the last lomem page in the page array. | ||
| 142 | * @num_pages: Number of pages in the page array. | ||
| 143 | * @bdev: Pointer to the current struct ttm_bo_device. | ||
| 144 | * @be: Pointer to the ttm backend. | ||
| 145 | * @tsk: The task for user ttm. | ||
| 146 | * @start: virtual address for user ttm. | ||
| 147 | * @swap_storage: Pointer to shmem struct file for swap storage. | ||
| 148 | * @caching_state: The current caching state of the pages. | ||
| 149 | * @state: The current binding state of the pages. | ||
| 150 | * | ||
| 151 | * This is a structure holding the pages, caching- and aperture binding | ||
| 152 | * status for a buffer object that isn't backed by fixed (VRAM / AGP) | ||
| 153 | * memory. | ||
| 154 | */ | ||
| 155 | |||
| 156 | struct ttm_tt { | ||
| 157 | struct page *dummy_read_page; | ||
| 158 | struct page **pages; | ||
| 159 | long first_himem_page; | ||
| 160 | long last_lomem_page; | ||
| 161 | uint32_t page_flags; | ||
| 162 | unsigned long num_pages; | ||
| 163 | struct ttm_bo_device *bdev; | ||
| 164 | struct ttm_backend *be; | ||
| 165 | struct task_struct *tsk; | ||
| 166 | unsigned long start; | ||
| 167 | struct file *swap_storage; | ||
| 168 | enum ttm_caching_state caching_state; | ||
| 169 | enum { | ||
| 170 | tt_bound, | ||
| 171 | tt_unbound, | ||
| 172 | tt_unpopulated, | ||
| 173 | } state; | ||
| 174 | }; | ||
| 175 | |||
| 176 | #define TTM_MEMTYPE_FLAG_FIXED (1 << 0) /* Fixed (on-card) PCI memory */ | ||
| 177 | #define TTM_MEMTYPE_FLAG_MAPPABLE (1 << 1) /* Memory mappable */ | ||
| 178 | #define TTM_MEMTYPE_FLAG_NEEDS_IOREMAP (1 << 2) /* Fixed memory needs ioremap | ||
| 179 | before kernel access. */ | ||
| 180 | #define TTM_MEMTYPE_FLAG_CMA (1 << 3) /* Can't map aperture */ | ||
| 181 | |||
| 182 | /** | ||
| 183 | * struct ttm_mem_type_manager | ||
| 184 | * | ||
| 185 | * @has_type: The memory type has been initialized. | ||
| 186 | * @use_type: The memory type is enabled. | ||
| 187 | * @flags: TTM_MEMTYPE_XX flags identifying the traits of the memory | ||
| 188 | * managed by this memory type. | ||
| 189 | * @gpu_offset: If used, the GPU offset of the first managed page of | ||
| 190 | * fixed memory or the first managed location in an aperture. | ||
| 191 | * @io_offset: The io_offset of the first managed page of IO memory or | ||
| 192 | * the first managed location in an aperture. For TTM_MEMTYPE_FLAG_CMA | ||
| 193 | * memory, this should be set to NULL. | ||
| 194 | * @io_size: The size of a managed IO region (fixed memory or aperture). | ||
| 195 | * @io_addr: Virtual kernel address if the io region is pre-mapped. For | ||
| 196 | * TTM_MEMTYPE_FLAG_NEEDS_IOREMAP there is no pre-mapped io map and | ||
| 197 | * @io_addr should be set to NULL. | ||
| 198 | * @size: Size of the managed region. | ||
| 199 | * @available_caching: A mask of available caching types, TTM_PL_FLAG_XX, | ||
| 200 | * as defined in ttm_placement_common.h | ||
| 201 | * @default_caching: The default caching policy used for a buffer object | ||
| 202 | * placed in this memory type if the user doesn't provide one. | ||
| 203 | * @manager: The range manager used for this memory type. FIXME: If the aperture | ||
| 204 | * has a page size different from the underlying system, the granularity | ||
| 205 | * of this manager should take care of this. But the range allocating code | ||
| 206 | * in ttm_bo.c needs to be modified for this. | ||
| 207 | * @lru: The lru list for this memory type. | ||
| 208 | * | ||
| 209 | * This structure is used to identify and manage memory types for a device. | ||
| 210 | * It's set up by the ttm_bo_driver::init_mem_type method. | ||
| 211 | */ | ||
| 212 | |||
| 213 | struct ttm_mem_type_manager { | ||
| 214 | |||
| 215 | /* | ||
| 216 | * No protection. Constant from start. | ||
| 217 | */ | ||
| 218 | |||
| 219 | bool has_type; | ||
| 220 | bool use_type; | ||
| 221 | uint32_t flags; | ||
| 222 | unsigned long gpu_offset; | ||
| 223 | unsigned long io_offset; | ||
| 224 | unsigned long io_size; | ||
| 225 | void *io_addr; | ||
| 226 | uint64_t size; | ||
| 227 | uint32_t available_caching; | ||
| 228 | uint32_t default_caching; | ||
| 229 | |||
| 230 | /* | ||
| 231 | * Protected by the bdev->lru_lock. | ||
| 232 | * TODO: Consider one lru_lock per ttm_mem_type_manager. | ||
| 233 | * Plays ill with list removal, though. | ||
| 234 | */ | ||
| 235 | |||
| 236 | struct drm_mm manager; | ||
| 237 | struct list_head lru; | ||
| 238 | }; | ||
| 239 | |||
| 240 | /** | ||
| 241 | * struct ttm_bo_driver | ||
| 242 | * | ||
| 243 | * @mem_type_prio: Priority array of memory types to place a buffer object in | ||
| 244 | * if it fits without evicting buffers from any of these memory types. | ||
| 245 | * @mem_busy_prio: Priority array of memory types to place a buffer object in | ||
| 246 | * if it needs to evict buffers to make room. | ||
| 247 | * @num_mem_type_prio: Number of elements in the @mem_type_prio array. | ||
| 248 | * @num_mem_busy_prio: Number of elements in the @num_mem_busy_prio array. | ||
| 249 | * @create_ttm_backend_entry: Callback to create a struct ttm_backend. | ||
| 250 | * @invalidate_caches: Callback to invalidate read caches when a buffer object | ||
| 251 | * has been evicted. | ||
| 252 | * @init_mem_type: Callback to initialize a struct ttm_mem_type_manager | ||
| 253 | * structure. | ||
| 254 | * @evict_flags: Callback to obtain placement flags when a buffer is evicted. | ||
| 255 | * @move: Callback for a driver to hook in accelerated functions to | ||
| 256 | * move a buffer. | ||
| 257 | * If set to NULL, a potentially slow memcpy() move is used. | ||
| 258 | * @sync_obj_signaled: See ttm_fence_api.h | ||
| 259 | * @sync_obj_wait: See ttm_fence_api.h | ||
| 260 | * @sync_obj_flush: See ttm_fence_api.h | ||
| 261 | * @sync_obj_unref: See ttm_fence_api.h | ||
| 262 | * @sync_obj_ref: See ttm_fence_api.h | ||
| 263 | */ | ||
| 264 | |||
| 265 | struct ttm_bo_driver { | ||
| 266 | const uint32_t *mem_type_prio; | ||
| 267 | const uint32_t *mem_busy_prio; | ||
| 268 | uint32_t num_mem_type_prio; | ||
| 269 | uint32_t num_mem_busy_prio; | ||
| 270 | |||
| 271 | /** | ||
| 272 | * struct ttm_bo_driver member create_ttm_backend_entry | ||
| 273 | * | ||
| 274 | * @bdev: The buffer object device. | ||
| 275 | * | ||
| 276 | * Create a driver specific struct ttm_backend. | ||
| 277 | */ | ||
| 278 | |||
| 279 | struct ttm_backend *(*create_ttm_backend_entry) | ||
| 280 | (struct ttm_bo_device *bdev); | ||
| 281 | |||
| 282 | /** | ||
| 283 | * struct ttm_bo_driver member invalidate_caches | ||
| 284 | * | ||
| 285 | * @bdev: the buffer object device. | ||
| 286 | * @flags: new placement of the rebound buffer object. | ||
| 287 | * | ||
| 288 | * A previosly evicted buffer has been rebound in a | ||
| 289 | * potentially new location. Tell the driver that it might | ||
| 290 | * consider invalidating read (texture) caches on the next command | ||
| 291 | * submission as a consequence. | ||
| 292 | */ | ||
| 293 | |||
| 294 | int (*invalidate_caches) (struct ttm_bo_device *bdev, uint32_t flags); | ||
| 295 | int (*init_mem_type) (struct ttm_bo_device *bdev, uint32_t type, | ||
| 296 | struct ttm_mem_type_manager *man); | ||
| 297 | /** | ||
| 298 | * struct ttm_bo_driver member evict_flags: | ||
| 299 | * | ||
| 300 | * @bo: the buffer object to be evicted | ||
| 301 | * | ||
| 302 | * Return the bo flags for a buffer which is not mapped to the hardware. | ||
| 303 | * These will be placed in proposed_flags so that when the move is | ||
| 304 | * finished, they'll end up in bo->mem.flags | ||
| 305 | */ | ||
| 306 | |||
| 307 | uint32_t(*evict_flags) (struct ttm_buffer_object *bo); | ||
| 308 | /** | ||
| 309 | * struct ttm_bo_driver member move: | ||
| 310 | * | ||
| 311 | * @bo: the buffer to move | ||
| 312 | * @evict: whether this motion is evicting the buffer from | ||
| 313 | * the graphics address space | ||
| 314 | * @interruptible: Use interruptible sleeps if possible when sleeping. | ||
| 315 | * @no_wait: whether this should give up and return -EBUSY | ||
| 316 | * if this move would require sleeping | ||
| 317 | * @new_mem: the new memory region receiving the buffer | ||
| 318 | * | ||
| 319 | * Move a buffer between two memory regions. | ||
| 320 | */ | ||
| 321 | int (*move) (struct ttm_buffer_object *bo, | ||
| 322 | bool evict, bool interruptible, | ||
| 323 | bool no_wait, struct ttm_mem_reg *new_mem); | ||
| 324 | |||
| 325 | /** | ||
| 326 | * struct ttm_bo_driver_member verify_access | ||
| 327 | * | ||
| 328 | * @bo: Pointer to a buffer object. | ||
| 329 | * @filp: Pointer to a struct file trying to access the object. | ||
| 330 | * | ||
| 331 | * Called from the map / write / read methods to verify that the | ||
| 332 | * caller is permitted to access the buffer object. | ||
| 333 | * This member may be set to NULL, which will refuse this kind of | ||
| 334 | * access for all buffer objects. | ||
| 335 | * This function should return 0 if access is granted, -EPERM otherwise. | ||
| 336 | */ | ||
| 337 | int (*verify_access) (struct ttm_buffer_object *bo, | ||
| 338 | struct file *filp); | ||
| 339 | |||
| 340 | /** | ||
| 341 | * In case a driver writer dislikes the TTM fence objects, | ||
| 342 | * the driver writer can replace those with sync objects of | ||
| 343 | * his / her own. If it turns out that no driver writer is | ||
| 344 | * using these. I suggest we remove these hooks and plug in | ||
| 345 | * fences directly. The bo driver needs the following functionality: | ||
| 346 | * See the corresponding functions in the fence object API | ||
| 347 | * documentation. | ||
| 348 | */ | ||
| 349 | |||
| 350 | bool (*sync_obj_signaled) (void *sync_obj, void *sync_arg); | ||
| 351 | int (*sync_obj_wait) (void *sync_obj, void *sync_arg, | ||
| 352 | bool lazy, bool interruptible); | ||
| 353 | int (*sync_obj_flush) (void *sync_obj, void *sync_arg); | ||
| 354 | void (*sync_obj_unref) (void **sync_obj); | ||
| 355 | void *(*sync_obj_ref) (void *sync_obj); | ||
| 356 | }; | ||
| 357 | |||
| 358 | #define TTM_NUM_MEM_TYPES 8 | ||
| 359 | |||
| 360 | #define TTM_BO_PRIV_FLAG_MOVING 0 /* Buffer object is moving and needs | ||
| 361 | idling before CPU mapping */ | ||
| 362 | #define TTM_BO_PRIV_FLAG_MAX 1 | ||
| 363 | /** | ||
| 364 | * struct ttm_bo_device - Buffer object driver device-specific data. | ||
| 365 | * | ||
| 366 | * @mem_glob: Pointer to a struct ttm_mem_global object for accounting. | ||
| 367 | * @driver: Pointer to a struct ttm_bo_driver struct setup by the driver. | ||
| 368 | * @count: Current number of buffer object. | ||
| 369 | * @pages: Current number of pinned pages. | ||
| 370 | * @dummy_read_page: Pointer to a dummy page used for mapping requests | ||
| 371 | * of unpopulated pages. | ||
| 372 | * @shrink: A shrink callback object used for buffre object swap. | ||
| 373 | * @ttm_bo_extra_size: Extra size (sizeof(struct ttm_buffer_object) excluded) | ||
| 374 | * used by a buffer object. This is excluding page arrays and backing pages. | ||
| 375 | * @ttm_bo_size: This is @ttm_bo_extra_size + sizeof(struct ttm_buffer_object). | ||
| 376 | * @man: An array of mem_type_managers. | ||
| 377 | * @addr_space_mm: Range manager for the device address space. | ||
| 378 | * lru_lock: Spinlock that protects the buffer+device lru lists and | ||
| 379 | * ddestroy lists. | ||
| 380 | * @nice_mode: Try nicely to wait for buffer idle when cleaning a manager. | ||
| 381 | * If a GPU lockup has been detected, this is forced to 0. | ||
| 382 | * @dev_mapping: A pointer to the struct address_space representing the | ||
| 383 | * device address space. | ||
| 384 | * @wq: Work queue structure for the delayed delete workqueue. | ||
| 385 | * | ||
| 386 | */ | ||
| 387 | |||
| 388 | struct ttm_bo_device { | ||
| 389 | |||
| 390 | /* | ||
| 391 | * Constant after bo device init / atomic. | ||
| 392 | */ | ||
| 393 | |||
| 394 | struct ttm_mem_global *mem_glob; | ||
| 395 | struct ttm_bo_driver *driver; | ||
| 396 | struct page *dummy_read_page; | ||
| 397 | struct ttm_mem_shrink shrink; | ||
| 398 | |||
| 399 | size_t ttm_bo_extra_size; | ||
| 400 | size_t ttm_bo_size; | ||
| 401 | |||
| 402 | rwlock_t vm_lock; | ||
| 403 | /* | ||
| 404 | * Protected by the vm lock. | ||
| 405 | */ | ||
| 406 | struct ttm_mem_type_manager man[TTM_NUM_MEM_TYPES]; | ||
| 407 | struct rb_root addr_space_rb; | ||
| 408 | struct drm_mm addr_space_mm; | ||
| 409 | |||
| 410 | /* | ||
| 411 | * Might want to change this to one lock per manager. | ||
| 412 | */ | ||
| 413 | spinlock_t lru_lock; | ||
| 414 | /* | ||
| 415 | * Protected by the lru lock. | ||
| 416 | */ | ||
| 417 | struct list_head ddestroy; | ||
| 418 | struct list_head swap_lru; | ||
| 419 | |||
| 420 | /* | ||
| 421 | * Protected by load / firstopen / lastclose /unload sync. | ||
| 422 | */ | ||
| 423 | |||
| 424 | bool nice_mode; | ||
| 425 | struct address_space *dev_mapping; | ||
| 426 | |||
| 427 | /* | ||
| 428 | * Internal protection. | ||
| 429 | */ | ||
| 430 | |||
| 431 | struct delayed_work wq; | ||
| 432 | }; | ||
| 433 | |||
| 434 | /** | ||
| 435 | * ttm_flag_masked | ||
| 436 | * | ||
| 437 | * @old: Pointer to the result and original value. | ||
| 438 | * @new: New value of bits. | ||
| 439 | * @mask: Mask of bits to change. | ||
| 440 | * | ||
| 441 | * Convenience function to change a number of bits identified by a mask. | ||
| 442 | */ | ||
| 443 | |||
| 444 | static inline uint32_t | ||
| 445 | ttm_flag_masked(uint32_t *old, uint32_t new, uint32_t mask) | ||
| 446 | { | ||
| 447 | *old ^= (*old ^ new) & mask; | ||
| 448 | return *old; | ||
| 449 | } | ||
| 450 | |||
| 451 | /** | ||
| 452 | * ttm_tt_create | ||
| 453 | * | ||
| 454 | * @bdev: pointer to a struct ttm_bo_device: | ||
| 455 | * @size: Size of the data needed backing. | ||
| 456 | * @page_flags: Page flags as identified by TTM_PAGE_FLAG_XX flags. | ||
| 457 | * @dummy_read_page: See struct ttm_bo_device. | ||
| 458 | * | ||
| 459 | * Create a struct ttm_tt to back data with system memory pages. | ||
| 460 | * No pages are actually allocated. | ||
| 461 | * Returns: | ||
| 462 | * NULL: Out of memory. | ||
| 463 | */ | ||
| 464 | extern struct ttm_tt *ttm_tt_create(struct ttm_bo_device *bdev, | ||
| 465 | unsigned long size, | ||
| 466 | uint32_t page_flags, | ||
| 467 | struct page *dummy_read_page); | ||
| 468 | |||
| 469 | /** | ||
| 470 | * ttm_tt_set_user: | ||
| 471 | * | ||
| 472 | * @ttm: The struct ttm_tt to populate. | ||
| 473 | * @tsk: A struct task_struct for which @start is a valid user-space address. | ||
| 474 | * @start: A valid user-space address. | ||
| 475 | * @num_pages: Size in pages of the user memory area. | ||
| 476 | * | ||
| 477 | * Populate a struct ttm_tt with a user-space memory area after first pinning | ||
| 478 | * the pages backing it. | ||
| 479 | * Returns: | ||
| 480 | * !0: Error. | ||
| 481 | */ | ||
| 482 | |||
| 483 | extern int ttm_tt_set_user(struct ttm_tt *ttm, | ||
| 484 | struct task_struct *tsk, | ||
| 485 | unsigned long start, unsigned long num_pages); | ||
| 486 | |||
| 487 | /** | ||
| 488 | * ttm_ttm_bind: | ||
| 489 | * | ||
| 490 | * @ttm: The struct ttm_tt containing backing pages. | ||
| 491 | * @bo_mem: The struct ttm_mem_reg identifying the binding location. | ||
| 492 | * | ||
| 493 | * Bind the pages of @ttm to an aperture location identified by @bo_mem | ||
| 494 | */ | ||
| 495 | extern int ttm_tt_bind(struct ttm_tt *ttm, struct ttm_mem_reg *bo_mem); | ||
| 496 | |||
| 497 | /** | ||
| 498 | * ttm_ttm_destroy: | ||
| 499 | * | ||
| 500 | * @ttm: The struct ttm_tt. | ||
| 501 | * | ||
| 502 | * Unbind, unpopulate and destroy a struct ttm_tt. | ||
| 503 | */ | ||
| 504 | extern void ttm_tt_destroy(struct ttm_tt *ttm); | ||
| 505 | |||
| 506 | /** | ||
| 507 | * ttm_ttm_unbind: | ||
| 508 | * | ||
| 509 | * @ttm: The struct ttm_tt. | ||
| 510 | * | ||
| 511 | * Unbind a struct ttm_tt. | ||
| 512 | */ | ||
| 513 | extern void ttm_tt_unbind(struct ttm_tt *ttm); | ||
| 514 | |||
| 515 | /** | ||
| 516 | * ttm_ttm_destroy: | ||
| 517 | * | ||
| 518 | * @ttm: The struct ttm_tt. | ||
| 519 | * @index: Index of the desired page. | ||
| 520 | * | ||
| 521 | * Return a pointer to the struct page backing @ttm at page | ||
| 522 | * index @index. If the page is unpopulated, one will be allocated to | ||
| 523 | * populate that index. | ||
| 524 | * | ||
| 525 | * Returns: | ||
| 526 | * NULL on OOM. | ||
| 527 | */ | ||
| 528 | extern struct page *ttm_tt_get_page(struct ttm_tt *ttm, int index); | ||
| 529 | |||
| 530 | /** | ||
| 531 | * ttm_tt_cache_flush: | ||
| 532 | * | ||
| 533 | * @pages: An array of pointers to struct page:s to flush. | ||
| 534 | * @num_pages: Number of pages to flush. | ||
| 535 | * | ||
| 536 | * Flush the data of the indicated pages from the cpu caches. | ||
| 537 | * This is used when changing caching attributes of the pages from | ||
| 538 | * cache-coherent. | ||
| 539 | */ | ||
| 540 | extern void ttm_tt_cache_flush(struct page *pages[], unsigned long num_pages); | ||
| 541 | |||
| 542 | /** | ||
| 543 | * ttm_tt_set_placement_caching: | ||
| 544 | * | ||
| 545 | * @ttm A struct ttm_tt the backing pages of which will change caching policy. | ||
| 546 | * @placement: Flag indicating the desired caching policy. | ||
| 547 | * | ||
| 548 | * This function will change caching policy of any default kernel mappings of | ||
| 549 | * the pages backing @ttm. If changing from cached to uncached or | ||
| 550 | * write-combined, | ||
| 551 | * all CPU caches will first be flushed to make sure the data of the pages | ||
| 552 | * hit RAM. This function may be very costly as it involves global TLB | ||
| 553 | * and cache flushes and potential page splitting / combining. | ||
| 554 | */ | ||
| 555 | extern int ttm_tt_set_placement_caching(struct ttm_tt *ttm, uint32_t placement); | ||
| 556 | extern int ttm_tt_swapout(struct ttm_tt *ttm, | ||
| 557 | struct file *persistant_swap_storage); | ||
| 558 | |||
| 559 | /* | ||
| 560 | * ttm_bo.c | ||
| 561 | */ | ||
| 562 | |||
| 563 | /** | ||
| 564 | * ttm_mem_reg_is_pci | ||
| 565 | * | ||
| 566 | * @bdev: Pointer to a struct ttm_bo_device. | ||
| 567 | * @mem: A valid struct ttm_mem_reg. | ||
| 568 | * | ||
| 569 | * Returns true if the memory described by @mem is PCI memory, | ||
| 570 | * false otherwise. | ||
| 571 | */ | ||
| 572 | extern bool ttm_mem_reg_is_pci(struct ttm_bo_device *bdev, | ||
| 573 | struct ttm_mem_reg *mem); | ||
| 574 | |||
| 575 | /** | ||
| 576 | * ttm_bo_mem_space | ||
| 577 | * | ||
| 578 | * @bo: Pointer to a struct ttm_buffer_object. the data of which | ||
| 579 | * we want to allocate space for. | ||
| 580 | * @proposed_placement: Proposed new placement for the buffer object. | ||
| 581 | * @mem: A struct ttm_mem_reg. | ||
| 582 | * @interruptible: Sleep interruptible when sliping. | ||
| 583 | * @no_wait: Don't sleep waiting for space to become available. | ||
| 584 | * | ||
| 585 | * Allocate memory space for the buffer object pointed to by @bo, using | ||
| 586 | * the placement flags in @mem, potentially evicting other idle buffer objects. | ||
| 587 | * This function may sleep while waiting for space to become available. | ||
| 588 | * Returns: | ||
| 589 | * -EBUSY: No space available (only if no_wait == 1). | ||
| 590 | * -ENOMEM: Could not allocate memory for the buffer object, either due to | ||
| 591 | * fragmentation or concurrent allocators. | ||
| 592 | * -ERESTART: An interruptible sleep was interrupted by a signal. | ||
| 593 | */ | ||
| 594 | extern int ttm_bo_mem_space(struct ttm_buffer_object *bo, | ||
| 595 | uint32_t proposed_placement, | ||
| 596 | struct ttm_mem_reg *mem, | ||
| 597 | bool interruptible, bool no_wait); | ||
| 598 | /** | ||
| 599 | * ttm_bo_wait_for_cpu | ||
| 600 | * | ||
| 601 | * @bo: Pointer to a struct ttm_buffer_object. | ||
| 602 | * @no_wait: Don't sleep while waiting. | ||
| 603 | * | ||
| 604 | * Wait until a buffer object is no longer sync'ed for CPU access. | ||
| 605 | * Returns: | ||
| 606 | * -EBUSY: Buffer object was sync'ed for CPU access. (only if no_wait == 1). | ||
| 607 | * -ERESTART: An interruptible sleep was interrupted by a signal. | ||
| 608 | */ | ||
| 609 | |||
| 610 | extern int ttm_bo_wait_cpu(struct ttm_buffer_object *bo, bool no_wait); | ||
| 611 | |||
| 612 | /** | ||
| 613 | * ttm_bo_pci_offset - Get the PCI offset for the buffer object memory. | ||
| 614 | * | ||
| 615 | * @bo Pointer to a struct ttm_buffer_object. | ||
| 616 | * @bus_base On return the base of the PCI region | ||
| 617 | * @bus_offset On return the byte offset into the PCI region | ||
| 618 | * @bus_size On return the byte size of the buffer object or zero if | ||
| 619 | * the buffer object memory is not accessible through a PCI region. | ||
| 620 | * | ||
| 621 | * Returns: | ||
| 622 | * -EINVAL if the buffer object is currently not mappable. | ||
| 623 | * 0 otherwise. | ||
| 624 | */ | ||
| 625 | |||
| 626 | extern int ttm_bo_pci_offset(struct ttm_bo_device *bdev, | ||
| 627 | struct ttm_mem_reg *mem, | ||
| 628 | unsigned long *bus_base, | ||
| 629 | unsigned long *bus_offset, | ||
| 630 | unsigned long *bus_size); | ||
| 631 | |||
| 632 | extern int ttm_bo_device_release(struct ttm_bo_device *bdev); | ||
| 633 | |||
| 634 | /** | ||
| 635 | * ttm_bo_device_init | ||
| 636 | * | ||
| 637 | * @bdev: A pointer to a struct ttm_bo_device to initialize. | ||
| 638 | * @mem_global: A pointer to an initialized struct ttm_mem_global. | ||
| 639 | * @driver: A pointer to a struct ttm_bo_driver set up by the caller. | ||
| 640 | * @file_page_offset: Offset into the device address space that is available | ||
| 641 | * for buffer data. This ensures compatibility with other users of the | ||
| 642 | * address space. | ||
| 643 | * | ||
| 644 | * Initializes a struct ttm_bo_device: | ||
| 645 | * Returns: | ||
| 646 | * !0: Failure. | ||
| 647 | */ | ||
| 648 | extern int ttm_bo_device_init(struct ttm_bo_device *bdev, | ||
| 649 | struct ttm_mem_global *mem_glob, | ||
| 650 | struct ttm_bo_driver *driver, | ||
| 651 | uint64_t file_page_offset); | ||
| 652 | |||
| 653 | /** | ||
| 654 | * ttm_bo_reserve: | ||
| 655 | * | ||
| 656 | * @bo: A pointer to a struct ttm_buffer_object. | ||
| 657 | * @interruptible: Sleep interruptible if waiting. | ||
| 658 | * @no_wait: Don't sleep while trying to reserve, rather return -EBUSY. | ||
| 659 | * @use_sequence: If @bo is already reserved, Only sleep waiting for | ||
| 660 | * it to become unreserved if @sequence < (@bo)->sequence. | ||
| 661 | * | ||
| 662 | * Locks a buffer object for validation. (Or prevents other processes from | ||
| 663 | * locking it for validation) and removes it from lru lists, while taking | ||
| 664 | * a number of measures to prevent deadlocks. | ||
| 665 | * | ||
| 666 | * Deadlocks may occur when two processes try to reserve multiple buffers in | ||
| 667 | * different order, either by will or as a result of a buffer being evicted | ||
| 668 | * to make room for a buffer already reserved. (Buffers are reserved before | ||
| 669 | * they are evicted). The following algorithm prevents such deadlocks from | ||
| 670 | * occuring: | ||
| 671 | * 1) Buffers are reserved with the lru spinlock held. Upon successful | ||
| 672 | * reservation they are removed from the lru list. This stops a reserved buffer | ||
| 673 | * from being evicted. However the lru spinlock is released between the time | ||
| 674 | * a buffer is selected for eviction and the time it is reserved. | ||
| 675 | * Therefore a check is made when a buffer is reserved for eviction, that it | ||
| 676 | * is still the first buffer in the lru list, before it is removed from the | ||
| 677 | * list. @check_lru == 1 forces this check. If it fails, the function returns | ||
| 678 | * -EINVAL, and the caller should then choose a new buffer to evict and repeat | ||
| 679 | * the procedure. | ||
| 680 | * 2) Processes attempting to reserve multiple buffers other than for eviction, | ||
| 681 | * (typically execbuf), should first obtain a unique 32-bit | ||
| 682 | * validation sequence number, | ||
| 683 | * and call this function with @use_sequence == 1 and @sequence == the unique | ||
| 684 | * sequence number. If upon call of this function, the buffer object is already | ||
| 685 | * reserved, the validation sequence is checked against the validation | ||
| 686 | * sequence of the process currently reserving the buffer, | ||
| 687 | * and if the current validation sequence is greater than that of the process | ||
| 688 | * holding the reservation, the function returns -EAGAIN. Otherwise it sleeps | ||
| 689 | * waiting for the buffer to become unreserved, after which it retries | ||
| 690 | * reserving. | ||
| 691 | * The caller should, when receiving an -EAGAIN error | ||
| 692 | * release all its buffer reservations, wait for @bo to become unreserved, and | ||
| 693 | * then rerun the validation with the same validation sequence. This procedure | ||
| 694 | * will always guarantee that the process with the lowest validation sequence | ||
| 695 | * will eventually succeed, preventing both deadlocks and starvation. | ||
| 696 | * | ||
| 697 | * Returns: | ||
| 698 | * -EAGAIN: The reservation may cause a deadlock. | ||
| 699 | * Release all buffer reservations, wait for @bo to become unreserved and | ||
| 700 | * try again. (only if use_sequence == 1). | ||
| 701 | * -ERESTART: A wait for the buffer to become unreserved was interrupted by | ||
| 702 | * a signal. Release all buffer reservations and return to user-space. | ||
| 703 | */ | ||
| 704 | extern int ttm_bo_reserve(struct ttm_buffer_object *bo, | ||
| 705 | bool interruptible, | ||
| 706 | bool no_wait, bool use_sequence, uint32_t sequence); | ||
| 707 | |||
| 708 | /** | ||
| 709 | * ttm_bo_unreserve | ||
| 710 | * | ||
| 711 | * @bo: A pointer to a struct ttm_buffer_object. | ||
| 712 | * | ||
| 713 | * Unreserve a previous reservation of @bo. | ||
| 714 | */ | ||
| 715 | extern void ttm_bo_unreserve(struct ttm_buffer_object *bo); | ||
| 716 | |||
| 717 | /** | ||
| 718 | * ttm_bo_wait_unreserved | ||
| 719 | * | ||
| 720 | * @bo: A pointer to a struct ttm_buffer_object. | ||
| 721 | * | ||
| 722 | * Wait for a struct ttm_buffer_object to become unreserved. | ||
| 723 | * This is typically used in the execbuf code to relax cpu-usage when | ||
| 724 | * a potential deadlock condition backoff. | ||
| 725 | */ | ||
| 726 | extern int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo, | ||
| 727 | bool interruptible); | ||
| 728 | |||
| 729 | /** | ||
| 730 | * ttm_bo_block_reservation | ||
| 731 | * | ||
| 732 | * @bo: A pointer to a struct ttm_buffer_object. | ||
| 733 | * @interruptible: Use interruptible sleep when waiting. | ||
| 734 | * @no_wait: Don't sleep, but rather return -EBUSY. | ||
| 735 | * | ||
| 736 | * Block reservation for validation by simply reserving the buffer. | ||
| 737 | * This is intended for single buffer use only without eviction, | ||
| 738 | * and thus needs no deadlock protection. | ||
| 739 | * | ||
| 740 | * Returns: | ||
| 741 | * -EBUSY: If no_wait == 1 and the buffer is already reserved. | ||
| 742 | * -ERESTART: If interruptible == 1 and the process received a signal | ||
| 743 | * while sleeping. | ||
| 744 | */ | ||
| 745 | extern int ttm_bo_block_reservation(struct ttm_buffer_object *bo, | ||
| 746 | bool interruptible, bool no_wait); | ||
| 747 | |||
| 748 | /** | ||
| 749 | * ttm_bo_unblock_reservation | ||
| 750 | * | ||
| 751 | * @bo: A pointer to a struct ttm_buffer_object. | ||
| 752 | * | ||
| 753 | * Unblocks reservation leaving lru lists untouched. | ||
| 754 | */ | ||
| 755 | extern void ttm_bo_unblock_reservation(struct ttm_buffer_object *bo); | ||
| 756 | |||
| 757 | /* | ||
| 758 | * ttm_bo_util.c | ||
| 759 | */ | ||
| 760 | |||
| 761 | /** | ||
| 762 | * ttm_bo_move_ttm | ||
| 763 | * | ||
| 764 | * @bo: A pointer to a struct ttm_buffer_object. | ||
| 765 | * @evict: 1: This is an eviction. Don't try to pipeline. | ||
| 766 | * @no_wait: Never sleep, but rather return with -EBUSY. | ||
| 767 | * @new_mem: struct ttm_mem_reg indicating where to move. | ||
| 768 | * | ||
| 769 | * Optimized move function for a buffer object with both old and | ||
| 770 | * new placement backed by a TTM. The function will, if successful, | ||
| 771 | * free any old aperture space, and set (@new_mem)->mm_node to NULL, | ||
| 772 | * and update the (@bo)->mem placement flags. If unsuccessful, the old | ||
| 773 | * data remains untouched, and it's up to the caller to free the | ||
| 774 | * memory space indicated by @new_mem. | ||
| 775 | * Returns: | ||
| 776 | * !0: Failure. | ||
| 777 | */ | ||
| 778 | |||
| 779 | extern int ttm_bo_move_ttm(struct ttm_buffer_object *bo, | ||
| 780 | bool evict, bool no_wait, | ||
| 781 | struct ttm_mem_reg *new_mem); | ||
| 782 | |||
| 783 | /** | ||
| 784 | * ttm_bo_move_memcpy | ||
| 785 | * | ||
| 786 | * @bo: A pointer to a struct ttm_buffer_object. | ||
| 787 | * @evict: 1: This is an eviction. Don't try to pipeline. | ||
| 788 | * @no_wait: Never sleep, but rather return with -EBUSY. | ||
| 789 | * @new_mem: struct ttm_mem_reg indicating where to move. | ||
| 790 | * | ||
| 791 | * Fallback move function for a mappable buffer object in mappable memory. | ||
| 792 | * The function will, if successful, | ||
| 793 | * free any old aperture space, and set (@new_mem)->mm_node to NULL, | ||
| 794 | * and update the (@bo)->mem placement flags. If unsuccessful, the old | ||
| 795 | * data remains untouched, and it's up to the caller to free the | ||
| 796 | * memory space indicated by @new_mem. | ||
| 797 | * Returns: | ||
| 798 | * !0: Failure. | ||
| 799 | */ | ||
| 800 | |||
| 801 | extern int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, | ||
| 802 | bool evict, | ||
| 803 | bool no_wait, struct ttm_mem_reg *new_mem); | ||
| 804 | |||
| 805 | /** | ||
| 806 | * ttm_bo_free_old_node | ||
| 807 | * | ||
| 808 | * @bo: A pointer to a struct ttm_buffer_object. | ||
| 809 | * | ||
| 810 | * Utility function to free an old placement after a successful move. | ||
| 811 | */ | ||
| 812 | extern void ttm_bo_free_old_node(struct ttm_buffer_object *bo); | ||
| 813 | |||
| 814 | /** | ||
| 815 | * ttm_bo_move_accel_cleanup. | ||
| 816 | * | ||
| 817 | * @bo: A pointer to a struct ttm_buffer_object. | ||
| 818 | * @sync_obj: A sync object that signals when moving is complete. | ||
| 819 | * @sync_obj_arg: An argument to pass to the sync object idle / wait | ||
| 820 | * functions. | ||
| 821 | * @evict: This is an evict move. Don't return until the buffer is idle. | ||
| 822 | * @no_wait: Never sleep, but rather return with -EBUSY. | ||
| 823 | * @new_mem: struct ttm_mem_reg indicating where to move. | ||
| 824 | * | ||
| 825 | * Accelerated move function to be called when an accelerated move | ||
| 826 | * has been scheduled. The function will create a new temporary buffer object | ||
| 827 | * representing the old placement, and put the sync object on both buffer | ||
| 828 | * objects. After that the newly created buffer object is unref'd to be | ||
| 829 | * destroyed when the move is complete. This will help pipeline | ||
| 830 | * buffer moves. | ||
| 831 | */ | ||
| 832 | |||
| 833 | extern int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, | ||
| 834 | void *sync_obj, | ||
| 835 | void *sync_obj_arg, | ||
| 836 | bool evict, bool no_wait, | ||
| 837 | struct ttm_mem_reg *new_mem); | ||
| 838 | /** | ||
| 839 | * ttm_io_prot | ||
| 840 | * | ||
| 841 | * @c_state: Caching state. | ||
| 842 | * @tmp: Page protection flag for a normal, cached mapping. | ||
| 843 | * | ||
| 844 | * Utility function that returns the pgprot_t that should be used for | ||
| 845 | * setting up a PTE with the caching model indicated by @c_state. | ||
| 846 | */ | ||
| 847 | extern pgprot_t ttm_io_prot(enum ttm_caching_state c_state, pgprot_t tmp); | ||
| 848 | |||
| 849 | #if (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE))) | ||
| 850 | #define TTM_HAS_AGP | ||
| 851 | #include <linux/agp_backend.h> | ||
| 852 | |||
| 853 | /** | ||
| 854 | * ttm_agp_backend_init | ||
| 855 | * | ||
| 856 | * @bdev: Pointer to a struct ttm_bo_device. | ||
| 857 | * @bridge: The agp bridge this device is sitting on. | ||
| 858 | * | ||
| 859 | * Create a TTM backend that uses the indicated AGP bridge as an aperture | ||
| 860 | * for TT memory. This function uses the linux agpgart interface to | ||
| 861 | * bind and unbind memory backing a ttm_tt. | ||
| 862 | */ | ||
| 863 | extern struct ttm_backend *ttm_agp_backend_init(struct ttm_bo_device *bdev, | ||
| 864 | struct agp_bridge_data *bridge); | ||
| 865 | #endif | ||
| 866 | |||
| 867 | #endif | ||
diff --git a/include/drm/ttm/ttm_memory.h b/include/drm/ttm/ttm_memory.h new file mode 100644 index 000000000000..d8b8f042c4f1 --- /dev/null +++ b/include/drm/ttm/ttm_memory.h | |||
| @@ -0,0 +1,153 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | **************************************************************************/ | ||
| 27 | |||
| 28 | #ifndef TTM_MEMORY_H | ||
| 29 | #define TTM_MEMORY_H | ||
| 30 | |||
| 31 | #include <linux/workqueue.h> | ||
| 32 | #include <linux/spinlock.h> | ||
| 33 | #include <linux/wait.h> | ||
| 34 | #include <linux/errno.h> | ||
| 35 | |||
| 36 | /** | ||
| 37 | * struct ttm_mem_shrink - callback to shrink TTM memory usage. | ||
| 38 | * | ||
| 39 | * @do_shrink: The callback function. | ||
| 40 | * | ||
| 41 | * Arguments to the do_shrink functions are intended to be passed using | ||
| 42 | * inheritance. That is, the argument class derives from struct ttm_mem_srink, | ||
| 43 | * and can be accessed using container_of(). | ||
| 44 | */ | ||
| 45 | |||
| 46 | struct ttm_mem_shrink { | ||
| 47 | int (*do_shrink) (struct ttm_mem_shrink *); | ||
| 48 | }; | ||
| 49 | |||
| 50 | /** | ||
| 51 | * struct ttm_mem_global - Global memory accounting structure. | ||
| 52 | * | ||
| 53 | * @shrink: A single callback to shrink TTM memory usage. Extend this | ||
| 54 | * to a linked list to be able to handle multiple callbacks when needed. | ||
| 55 | * @swap_queue: A workqueue to handle shrinking in low memory situations. We | ||
| 56 | * need a separate workqueue since it will spend a lot of time waiting | ||
| 57 | * for the GPU, and this will otherwise block other workqueue tasks(?) | ||
| 58 | * At this point we use only a single-threaded workqueue. | ||
| 59 | * @work: The workqueue callback for the shrink queue. | ||
| 60 | * @queue: Wait queue for processes suspended waiting for memory. | ||
| 61 | * @lock: Lock to protect the @shrink - and the memory accounting members, | ||
| 62 | * that is, essentially the whole structure with some exceptions. | ||
| 63 | * @emer_memory: Lowmem memory limit available for root. | ||
| 64 | * @max_memory: Lowmem memory limit available for non-root. | ||
| 65 | * @swap_limit: Lowmem memory limit where the shrink workqueue kicks in. | ||
| 66 | * @used_memory: Currently used lowmem memory. | ||
| 67 | * @used_total_memory: Currently used total (lowmem + highmem) memory. | ||
| 68 | * @total_memory_swap_limit: Total memory limit where the shrink workqueue | ||
| 69 | * kicks in. | ||
| 70 | * @max_total_memory: Total memory available to non-root processes. | ||
| 71 | * @emer_total_memory: Total memory available to root processes. | ||
| 72 | * | ||
| 73 | * Note that this structure is not per device. It should be global for all | ||
| 74 | * graphics devices. | ||
| 75 | */ | ||
| 76 | |||
| 77 | struct ttm_mem_global { | ||
| 78 | struct ttm_mem_shrink *shrink; | ||
| 79 | struct workqueue_struct *swap_queue; | ||
| 80 | struct work_struct work; | ||
| 81 | wait_queue_head_t queue; | ||
| 82 | spinlock_t lock; | ||
| 83 | uint64_t emer_memory; | ||
| 84 | uint64_t max_memory; | ||
| 85 | uint64_t swap_limit; | ||
| 86 | uint64_t used_memory; | ||
| 87 | uint64_t used_total_memory; | ||
| 88 | uint64_t total_memory_swap_limit; | ||
| 89 | uint64_t max_total_memory; | ||
| 90 | uint64_t emer_total_memory; | ||
| 91 | }; | ||
| 92 | |||
| 93 | /** | ||
| 94 | * ttm_mem_init_shrink - initialize a struct ttm_mem_shrink object | ||
| 95 | * | ||
| 96 | * @shrink: The object to initialize. | ||
| 97 | * @func: The callback function. | ||
| 98 | */ | ||
| 99 | |||
| 100 | static inline void ttm_mem_init_shrink(struct ttm_mem_shrink *shrink, | ||
| 101 | int (*func) (struct ttm_mem_shrink *)) | ||
| 102 | { | ||
| 103 | shrink->do_shrink = func; | ||
| 104 | } | ||
| 105 | |||
| 106 | /** | ||
| 107 | * ttm_mem_register_shrink - register a struct ttm_mem_shrink object. | ||
| 108 | * | ||
| 109 | * @glob: The struct ttm_mem_global object to register with. | ||
| 110 | * @shrink: An initialized struct ttm_mem_shrink object to register. | ||
| 111 | * | ||
| 112 | * Returns: | ||
| 113 | * -EBUSY: There's already a callback registered. (May change). | ||
| 114 | */ | ||
| 115 | |||
| 116 | static inline int ttm_mem_register_shrink(struct ttm_mem_global *glob, | ||
| 117 | struct ttm_mem_shrink *shrink) | ||
| 118 | { | ||
| 119 | spin_lock(&glob->lock); | ||
| 120 | if (glob->shrink != NULL) { | ||
| 121 | spin_unlock(&glob->lock); | ||
| 122 | return -EBUSY; | ||
| 123 | } | ||
| 124 | glob->shrink = shrink; | ||
| 125 | spin_unlock(&glob->lock); | ||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | /** | ||
| 130 | * ttm_mem_unregister_shrink - unregister a struct ttm_mem_shrink object. | ||
| 131 | * | ||
| 132 | * @glob: The struct ttm_mem_global object to unregister from. | ||
| 133 | * @shrink: A previously registert struct ttm_mem_shrink object. | ||
| 134 | * | ||
| 135 | */ | ||
| 136 | |||
| 137 | static inline void ttm_mem_unregister_shrink(struct ttm_mem_global *glob, | ||
| 138 | struct ttm_mem_shrink *shrink) | ||
| 139 | { | ||
| 140 | spin_lock(&glob->lock); | ||
| 141 | BUG_ON(glob->shrink != shrink); | ||
| 142 | glob->shrink = NULL; | ||
| 143 | spin_unlock(&glob->lock); | ||
| 144 | } | ||
| 145 | |||
| 146 | extern int ttm_mem_global_init(struct ttm_mem_global *glob); | ||
| 147 | extern void ttm_mem_global_release(struct ttm_mem_global *glob); | ||
| 148 | extern int ttm_mem_global_alloc(struct ttm_mem_global *glob, uint64_t memory, | ||
| 149 | bool no_wait, bool interruptible, bool himem); | ||
| 150 | extern void ttm_mem_global_free(struct ttm_mem_global *glob, | ||
| 151 | uint64_t amount, bool himem); | ||
| 152 | extern size_t ttm_round_pot(size_t size); | ||
| 153 | #endif | ||
diff --git a/include/drm/ttm/ttm_module.h b/include/drm/ttm/ttm_module.h new file mode 100644 index 000000000000..889a4c7958ae --- /dev/null +++ b/include/drm/ttm/ttm_module.h | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright 2008-2009 VMware, Inc., Palo Alto, CA., USA | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | **************************************************************************/ | ||
| 27 | /* | ||
| 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | ||
| 29 | */ | ||
| 30 | |||
| 31 | #ifndef _TTM_MODULE_H_ | ||
| 32 | #define _TTM_MODULE_H_ | ||
| 33 | |||
| 34 | #include <linux/kernel.h> | ||
| 35 | |||
| 36 | #define TTM_PFX "[TTM]" | ||
| 37 | |||
| 38 | enum ttm_global_types { | ||
| 39 | TTM_GLOBAL_TTM_MEM = 0, | ||
| 40 | TTM_GLOBAL_TTM_BO, | ||
| 41 | TTM_GLOBAL_TTM_OBJECT, | ||
| 42 | TTM_GLOBAL_NUM | ||
| 43 | }; | ||
| 44 | |||
| 45 | struct ttm_global_reference { | ||
| 46 | enum ttm_global_types global_type; | ||
| 47 | size_t size; | ||
| 48 | void *object; | ||
| 49 | int (*init) (struct ttm_global_reference *); | ||
| 50 | void (*release) (struct ttm_global_reference *); | ||
| 51 | }; | ||
| 52 | |||
| 53 | extern void ttm_global_init(void); | ||
| 54 | extern void ttm_global_release(void); | ||
| 55 | extern int ttm_global_item_ref(struct ttm_global_reference *ref); | ||
| 56 | extern void ttm_global_item_unref(struct ttm_global_reference *ref); | ||
| 57 | |||
| 58 | #endif /* _TTM_MODULE_H_ */ | ||
diff --git a/include/drm/ttm/ttm_placement.h b/include/drm/ttm/ttm_placement.h new file mode 100644 index 000000000000..c84ff153a564 --- /dev/null +++ b/include/drm/ttm/ttm_placement.h | |||
| @@ -0,0 +1,92 @@ | |||
| 1 | /************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA | ||
| 4 | * All Rights Reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the | ||
| 8 | * "Software"), to deal in the Software without restriction, including | ||
| 9 | * without limitation the rights to use, copy, modify, merge, publish, | ||
| 10 | * distribute, sub license, and/or sell copies of the Software, and to | ||
| 11 | * permit persons to whom the Software is furnished to do so, subject to | ||
| 12 | * the following conditions: | ||
| 13 | * | ||
| 14 | * The above copyright notice and this permission notice (including the | ||
| 15 | * next paragraph) shall be included in all copies or substantial portions | ||
| 16 | * of the Software. | ||
| 17 | * | ||
| 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
| 21 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
| 22 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 23 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
| 24 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 25 | * | ||
| 26 | **************************************************************************/ | ||
| 27 | /* | ||
| 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | ||
| 29 | */ | ||
| 30 | |||
| 31 | #ifndef _TTM_PLACEMENT_H_ | ||
| 32 | #define _TTM_PLACEMENT_H_ | ||
| 33 | /* | ||
| 34 | * Memory regions for data placement. | ||
| 35 | */ | ||
| 36 | |||
| 37 | #define TTM_PL_SYSTEM 0 | ||
| 38 | #define TTM_PL_TT 1 | ||
| 39 | #define TTM_PL_VRAM 2 | ||
| 40 | #define TTM_PL_PRIV0 3 | ||
| 41 | #define TTM_PL_PRIV1 4 | ||
| 42 | #define TTM_PL_PRIV2 5 | ||
| 43 | #define TTM_PL_PRIV3 6 | ||
| 44 | #define TTM_PL_PRIV4 7 | ||
| 45 | #define TTM_PL_PRIV5 8 | ||
| 46 | #define TTM_PL_SWAPPED 15 | ||
| 47 | |||
| 48 | #define TTM_PL_FLAG_SYSTEM (1 << TTM_PL_SYSTEM) | ||
| 49 | #define TTM_PL_FLAG_TT (1 << TTM_PL_TT) | ||
| 50 | #define TTM_PL_FLAG_VRAM (1 << TTM_PL_VRAM) | ||
| 51 | #define TTM_PL_FLAG_PRIV0 (1 << TTM_PL_PRIV0) | ||
| 52 | #define TTM_PL_FLAG_PRIV1 (1 << TTM_PL_PRIV1) | ||
| 53 | #define TTM_PL_FLAG_PRIV2 (1 << TTM_PL_PRIV2) | ||
| 54 | #define TTM_PL_FLAG_PRIV3 (1 << TTM_PL_PRIV3) | ||
| 55 | #define TTM_PL_FLAG_PRIV4 (1 << TTM_PL_PRIV4) | ||
| 56 | #define TTM_PL_FLAG_PRIV5 (1 << TTM_PL_PRIV5) | ||
| 57 | #define TTM_PL_FLAG_SWAPPED (1 << TTM_PL_SWAPPED) | ||
| 58 | #define TTM_PL_MASK_MEM 0x0000FFFF | ||
| 59 | |||
| 60 | /* | ||
| 61 | * Other flags that affects data placement. | ||
| 62 | * TTM_PL_FLAG_CACHED indicates cache-coherent mappings | ||
| 63 | * if available. | ||
| 64 | * TTM_PL_FLAG_SHARED means that another application may | ||
| 65 | * reference the buffer. | ||
| 66 | * TTM_PL_FLAG_NO_EVICT means that the buffer may never | ||
| 67 | * be evicted to make room for other buffers. | ||
| 68 | */ | ||
| 69 | |||
| 70 | #define TTM_PL_FLAG_CACHED (1 << 16) | ||
| 71 | #define TTM_PL_FLAG_UNCACHED (1 << 17) | ||
| 72 | #define TTM_PL_FLAG_WC (1 << 18) | ||
| 73 | #define TTM_PL_FLAG_SHARED (1 << 20) | ||
| 74 | #define TTM_PL_FLAG_NO_EVICT (1 << 21) | ||
| 75 | |||
| 76 | #define TTM_PL_MASK_CACHING (TTM_PL_FLAG_CACHED | \ | ||
| 77 | TTM_PL_FLAG_UNCACHED | \ | ||
| 78 | TTM_PL_FLAG_WC) | ||
| 79 | |||
| 80 | #define TTM_PL_MASK_MEMTYPE (TTM_PL_MASK_MEM | TTM_PL_MASK_CACHING) | ||
| 81 | |||
| 82 | /* | ||
| 83 | * Access flags to be used for CPU- and GPU- mappings. | ||
| 84 | * The idea is that the TTM synchronization mechanism will | ||
| 85 | * allow concurrent READ access and exclusive write access. | ||
| 86 | * Currently GPU- and CPU accesses are exclusive. | ||
| 87 | */ | ||
| 88 | |||
| 89 | #define TTM_ACCESS_READ (1 << 0) | ||
| 90 | #define TTM_ACCESS_WRITE (1 << 1) | ||
| 91 | |||
| 92 | #endif | ||
