radeon: add initial atombios modesetting and GEM -> TTM translation layer.

This is an initial import of the atom bios parser with modesetting support
for r500 hw using atombios. It also includes a simple memory manager
layer that translates a radeon GEM style interface onto TTM internally.

So far this memory manager has only been used for pinned object allocation
for the DDX to test modesetting.
main
Dave Airlie 2008-07-26 08:56:23 +10:00
parent 31da9492a4
commit df9871064e
41 changed files with 19166 additions and 352 deletions

View File

@ -13,9 +13,9 @@ drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \
drm_sysfs.o drm_pci.o drm_agpsupport.o drm_scatter.o \
drm_memory_debug.o ati_pcigart.o drm_sman.o \
drm_hashtab.o drm_memrange.o drm_object.o drm_compat.o \
drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o drm_crtc.o \
drm_edid.o drm_modes.o drm_bo_lock.o drm_regman.o \
drm_vm_nopage_compat.o drm_crtc_helper.o drm_gem.o
drm_fence.o drm_ttm.o drm_bo.o drm_bo_move.o drm_bo_lock.o \
drm_crtc.o drm_edid.o drm_modes.o drm_crtc_helper.o \
drm_regman.o drm_vm_nopage_compat.o drm_gem.o
tdfx-objs := tdfx_drv.o
r128-objs := r128_drv.o r128_cce.o r128_state.o r128_irq.o
mga-objs := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o
@ -40,15 +40,9 @@ nouveau-objs := nouveau_drv.o nouveau_state.o nouveau_fifo.o nouveau_mem.o \
nv50_crtc.o nv50_cursor.o nv50_lut.o nv50_fb.o nv50_output.o nv50_sor.o nv50_dac.o nv50_connector.o nv50_i2c.o nv50_display.o \
nv50_kms_wrapper.o \
nv50_fbcon.o
radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o
radeon_ms-objs := radeon_ms_drv.o radeon_ms_drm.o radeon_ms_family.o \
radeon_ms_state.o radeon_ms_bo.o radeon_ms_irq.o \
radeon_ms_bus.o radeon_ms_fence.o \
radeon_ms_cp.o radeon_ms_cp_mc.o radeon_ms_i2c.o \
radeon_ms_output.o radeon_ms_crtc.o radeon_ms_fb.o \
radeon_ms_exec.o radeon_ms_gpu.o radeon_ms_dac.o \
radeon_ms_properties.o radeon_ms_rom.o radeon_ms_combios.o \
amd_legacy_cbuffer.o
radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o r300_cmdbuf.o radeon_gem.o \
radeon_buffer.o radeon_fence.o atom.o radeon_display.o radeon_atombios.o radeon_i2c.o radeon_connectors.o \
atombios_crtc.o radeon_encoders.o radeon_fb.o radeon_combios.o
sis-objs := sis_drv.o sis_mm.o
ffb-objs := ffb_drv.o ffb_context.o
savage-objs := savage_drv.o savage_bci.o savage_state.o

484
linux-core/ObjectID.h Normal file
View File

@ -0,0 +1,484 @@
/*
* Copyright 2006-2007 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/* based on stg/asic_reg/drivers/inc/asic_reg/ObjectID.h ver 23 */
#ifndef _OBJECTID_H
#define _OBJECTID_H
#if defined(_X86_)
#pragma pack(1)
#endif
/****************************************************/
/* Graphics Object Type Definition */
/****************************************************/
#define GRAPH_OBJECT_TYPE_NONE 0x0
#define GRAPH_OBJECT_TYPE_GPU 0x1
#define GRAPH_OBJECT_TYPE_ENCODER 0x2
#define GRAPH_OBJECT_TYPE_CONNECTOR 0x3
#define GRAPH_OBJECT_TYPE_ROUTER 0x4
/* deleted */
/****************************************************/
/* Encoder Object ID Definition */
/****************************************************/
#define ENCODER_OBJECT_ID_NONE 0x00
/* Radeon Class Display Hardware */
#define ENCODER_OBJECT_ID_INTERNAL_LVDS 0x01
#define ENCODER_OBJECT_ID_INTERNAL_TMDS1 0x02
#define ENCODER_OBJECT_ID_INTERNAL_TMDS2 0x03
#define ENCODER_OBJECT_ID_INTERNAL_DAC1 0x04
#define ENCODER_OBJECT_ID_INTERNAL_DAC2 0x05 /* TV/CV DAC */
#define ENCODER_OBJECT_ID_INTERNAL_SDVOA 0x06
#define ENCODER_OBJECT_ID_INTERNAL_SDVOB 0x07
/* External Third Party Encoders */
#define ENCODER_OBJECT_ID_SI170B 0x08
#define ENCODER_OBJECT_ID_CH7303 0x09
#define ENCODER_OBJECT_ID_CH7301 0x0A
#define ENCODER_OBJECT_ID_INTERNAL_DVO1 0x0B /* This belongs to Radeon Class Display Hardware */
#define ENCODER_OBJECT_ID_EXTERNAL_SDVOA 0x0C
#define ENCODER_OBJECT_ID_EXTERNAL_SDVOB 0x0D
#define ENCODER_OBJECT_ID_TITFP513 0x0E
#define ENCODER_OBJECT_ID_INTERNAL_LVTM1 0x0F /* not used for Radeon */
#define ENCODER_OBJECT_ID_VT1623 0x10
#define ENCODER_OBJECT_ID_HDMI_SI1930 0x11
#define ENCODER_OBJECT_ID_HDMI_INTERNAL 0x12
/* Kaleidoscope (KLDSCP) Class Display Hardware (internal) */
#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 0x13
#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 0x14
#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1 0x15
#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 0x16 /* Shared with CV/TV and CRT */
#define ENCODER_OBJECT_ID_SI178 0X17 /* External TMDS (dual link, no HDCP.) */
#define ENCODER_OBJECT_ID_MVPU_FPGA 0x18 /* MVPU FPGA chip */
#define ENCODER_OBJECT_ID_INTERNAL_DDI 0x19
#define ENCODER_OBJECT_ID_VT1625 0x1A
#define ENCODER_OBJECT_ID_HDMI_SI1932 0x1B
#define ENCODER_OBJECT_ID_DP_AN9801 0x1C
#define ENCODER_OBJECT_ID_DP_DP501 0x1D
#define ENCODER_OBJECT_ID_INTERNAL_UNIPHY 0x1E
#define ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA 0x1F
/****************************************************/
/* Connector Object ID Definition */
/****************************************************/
#define CONNECTOR_OBJECT_ID_NONE 0x00
#define CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I 0x01
#define CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I 0x02
#define CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D 0x03
#define CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D 0x04
#define CONNECTOR_OBJECT_ID_VGA 0x05
#define CONNECTOR_OBJECT_ID_COMPOSITE 0x06
#define CONNECTOR_OBJECT_ID_SVIDEO 0x07
#define CONNECTOR_OBJECT_ID_YPbPr 0x08
#define CONNECTOR_OBJECT_ID_D_CONNECTOR 0x09
#define CONNECTOR_OBJECT_ID_9PIN_DIN 0x0A /* Supports both CV & TV */
#define CONNECTOR_OBJECT_ID_SCART 0x0B
#define CONNECTOR_OBJECT_ID_HDMI_TYPE_A 0x0C
#define CONNECTOR_OBJECT_ID_HDMI_TYPE_B 0x0D
#define CONNECTOR_OBJECT_ID_LVDS 0x0E
#define CONNECTOR_OBJECT_ID_7PIN_DIN 0x0F
#define CONNECTOR_OBJECT_ID_PCIE_CONNECTOR 0x10
#define CONNECTOR_OBJECT_ID_CROSSFIRE 0x11
#define CONNECTOR_OBJECT_ID_HARDCODE_DVI 0x12
#define CONNECTOR_OBJECT_ID_DISPLAYPORT 0x13
/* deleted */
/****************************************************/
/* Router Object ID Definition */
/****************************************************/
#define ROUTER_OBJECT_ID_NONE 0x00
#define ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL 0x01
/****************************************************/
// Graphics Object ENUM ID Definition */
/****************************************************/
#define GRAPH_OBJECT_ENUM_ID1 0x01
#define GRAPH_OBJECT_ENUM_ID2 0x02
#define GRAPH_OBJECT_ENUM_ID3 0x03
#define GRAPH_OBJECT_ENUM_ID4 0x04
/****************************************************/
/* Graphics Object ID Bit definition */
/****************************************************/
#define OBJECT_ID_MASK 0x00FF
#define ENUM_ID_MASK 0x0700
#define RESERVED1_ID_MASK 0x0800
#define OBJECT_TYPE_MASK 0x7000
#define RESERVED2_ID_MASK 0x8000
#define OBJECT_ID_SHIFT 0x00
#define ENUM_ID_SHIFT 0x08
#define OBJECT_TYPE_SHIFT 0x0C
/****************************************************/
/* Graphics Object family definition */
/****************************************************/
#define CONSTRUCTOBJECTFAMILYID(GRAPHICS_OBJECT_TYPE, GRAPHICS_OBJECT_ID) (GRAPHICS_OBJECT_TYPE << OBJECT_TYPE_SHIFT | \
GRAPHICS_OBJECT_ID << OBJECT_ID_SHIFT)
/****************************************************/
/* GPU Object ID definition - Shared with BIOS */
/****************************************************/
#define GPU_ENUM_ID1 ( GRAPH_OBJECT_TYPE_GPU << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT)
/****************************************************/
/* Encoder Object ID definition - Shared with BIOS */
/****************************************************/
/*
#define ENCODER_INTERNAL_LVDS_ENUM_ID1 0x2101
#define ENCODER_INTERNAL_TMDS1_ENUM_ID1 0x2102
#define ENCODER_INTERNAL_TMDS2_ENUM_ID1 0x2103
#define ENCODER_INTERNAL_DAC1_ENUM_ID1 0x2104
#define ENCODER_INTERNAL_DAC2_ENUM_ID1 0x2105
#define ENCODER_INTERNAL_SDVOA_ENUM_ID1 0x2106
#define ENCODER_INTERNAL_SDVOB_ENUM_ID1 0x2107
#define ENCODER_SIL170B_ENUM_ID1 0x2108
#define ENCODER_CH7303_ENUM_ID1 0x2109
#define ENCODER_CH7301_ENUM_ID1 0x210A
#define ENCODER_INTERNAL_DVO1_ENUM_ID1 0x210B
#define ENCODER_EXTERNAL_SDVOA_ENUM_ID1 0x210C
#define ENCODER_EXTERNAL_SDVOB_ENUM_ID1 0x210D
#define ENCODER_TITFP513_ENUM_ID1 0x210E
#define ENCODER_INTERNAL_LVTM1_ENUM_ID1 0x210F
#define ENCODER_VT1623_ENUM_ID1 0x2110
#define ENCODER_HDMI_SI1930_ENUM_ID1 0x2111
#define ENCODER_HDMI_INTERNAL_ENUM_ID1 0x2112
#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1 0x2113
#define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1 0x2114
#define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1 0x2115
#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1 0x2116
#define ENCODER_SI178_ENUM_ID1 0x2117
#define ENCODER_MVPU_FPGA_ENUM_ID1 0x2118
#define ENCODER_INTERNAL_DDI_ENUM_ID1 0x2119
#define ENCODER_VT1625_ENUM_ID1 0x211A
#define ENCODER_HDMI_SI1932_ENUM_ID1 0x211B
#define ENCODER_ENCODER_DP_AN9801_ENUM_ID1 0x211C
#define ENCODER_DP_DP501_ENUM_ID1 0x211D
#define ENCODER_INTERNAL_UNIPHY_ENUM_ID1 0x211E
*/
#define ENCODER_INTERNAL_LVDS_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_LVDS << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_TMDS1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_TMDS1 << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_TMDS2_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_TMDS2 << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_DAC1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_DAC1 << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_DAC2_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_DAC2 << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_SDVOA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_SDVOA_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_SDVOA << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_SDVOB_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_SDVOB << OBJECT_ID_SHIFT)
#define ENCODER_SIL170B_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_SI170B << OBJECT_ID_SHIFT)
#define ENCODER_CH7303_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_CH7303 << OBJECT_ID_SHIFT)
#define ENCODER_CH7301_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_CH7301 << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_DVO1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_DVO1 << OBJECT_ID_SHIFT)
#define ENCODER_EXTERNAL_SDVOA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT)
#define ENCODER_EXTERNAL_SDVOA_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_EXTERNAL_SDVOA << OBJECT_ID_SHIFT)
#define ENCODER_EXTERNAL_SDVOB_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_EXTERNAL_SDVOB << OBJECT_ID_SHIFT)
#define ENCODER_TITFP513_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_TITFP513 << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_LVTM1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_LVTM1 << OBJECT_ID_SHIFT)
#define ENCODER_VT1623_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_VT1623 << OBJECT_ID_SHIFT)
#define ENCODER_HDMI_SI1930_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_HDMI_SI1930 << OBJECT_ID_SHIFT)
#define ENCODER_HDMI_INTERNAL_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_HDMI_INTERNAL << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_KLDSCP_TMDS1_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1 << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_KLDSCP_DVO1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1 << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_KLDSCP_DAC1_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1 << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_KLDSCP_DAC2_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2 << OBJECT_ID_SHIFT) // Shared with CV/TV and CRT
#define ENCODER_SI178_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_SI178 << OBJECT_ID_SHIFT)
#define ENCODER_MVPU_FPGA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_MVPU_FPGA << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_DDI_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_DDI << OBJECT_ID_SHIFT)
#define ENCODER_VT1625_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_VT1625 << OBJECT_ID_SHIFT)
#define ENCODER_HDMI_SI1932_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_HDMI_SI1932 << OBJECT_ID_SHIFT)
#define ENCODER_DP_DP501_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_DP_DP501 << OBJECT_ID_SHIFT)
#define ENCODER_DP_AN9801_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_DP_AN9801 << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_UNIPHY_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_UNIPHY_ENUM_ID2 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_UNIPHY << OBJECT_ID_SHIFT)
#define ENCODER_INTERNAL_KLDSCP_LVTMA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ENCODER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA << OBJECT_ID_SHIFT)
/****************************************************/
/* Connector Object ID definition - Shared with BIOS */
/****************************************************/
/*
#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID1 0x3101
#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID1 0x3102
#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID1 0x3103
#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 0x3104
#define CONNECTOR_VGA_ENUM_ID1 0x3105
#define CONNECTOR_COMPOSITE_ENUM_ID1 0x3106
#define CONNECTOR_SVIDEO_ENUM_ID1 0x3107
#define CONNECTOR_YPbPr_ENUM_ID1 0x3108
#define CONNECTOR_D_CONNECTORE_ENUM_ID1 0x3109
#define CONNECTOR_9PIN_DIN_ENUM_ID1 0x310A
#define CONNECTOR_SCART_ENUM_ID1 0x310B
#define CONNECTOR_HDMI_TYPE_A_ENUM_ID1 0x310C
#define CONNECTOR_HDMI_TYPE_B_ENUM_ID1 0x310D
#define CONNECTOR_LVDS_ENUM_ID1 0x310E
#define CONNECTOR_7PIN_DIN_ENUM_ID1 0x310F
#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1 0x3110
*/
#define CONNECTOR_LVDS_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_LVDS << OBJECT_ID_SHIFT)
#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT)
#define CONNECTOR_SINGLE_LINK_DVI_I_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I << OBJECT_ID_SHIFT)
#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT)
#define CONNECTOR_DUAL_LINK_DVI_I_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_I << OBJECT_ID_SHIFT)
#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
#define CONNECTOR_SINGLE_LINK_DVI_D_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_D << OBJECT_ID_SHIFT)
#define CONNECTOR_DUAL_LINK_DVI_D_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D << OBJECT_ID_SHIFT)
#define CONNECTOR_VGA_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT)
#define CONNECTOR_VGA_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_VGA << OBJECT_ID_SHIFT)
#define CONNECTOR_COMPOSITE_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_COMPOSITE << OBJECT_ID_SHIFT)
#define CONNECTOR_SVIDEO_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_SVIDEO << OBJECT_ID_SHIFT)
#define CONNECTOR_YPbPr_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_YPbPr << OBJECT_ID_SHIFT)
#define CONNECTOR_D_CONNECTOR_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_D_CONNECTOR << OBJECT_ID_SHIFT)
#define CONNECTOR_9PIN_DIN_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_9PIN_DIN << OBJECT_ID_SHIFT)
#define CONNECTOR_SCART_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_SCART << OBJECT_ID_SHIFT)
#define CONNECTOR_HDMI_TYPE_A_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_HDMI_TYPE_A << OBJECT_ID_SHIFT)
#define CONNECTOR_HDMI_TYPE_B_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_HDMI_TYPE_B << OBJECT_ID_SHIFT)
#define CONNECTOR_7PIN_DIN_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_7PIN_DIN << OBJECT_ID_SHIFT)
#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT)
#define CONNECTOR_PCIE_CONNECTOR_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_PCIE_CONNECTOR << OBJECT_ID_SHIFT)
#define CONNECTOR_CROSSFIRE_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT)
#define CONNECTOR_CROSSFIRE_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_CROSSFIRE << OBJECT_ID_SHIFT)
#define CONNECTOR_HARDCODE_DVI_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT)
#define CONNECTOR_HARDCODE_DVI_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_HARDCODE_DVI << OBJECT_ID_SHIFT)
#define CONNECTOR_DISPLAYPORT_ENUM_ID1 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
#define CONNECTOR_DISPLAYPORT_ENUM_ID2 ( GRAPH_OBJECT_TYPE_CONNECTOR << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID2 << ENUM_ID_SHIFT |\
CONNECTOR_OBJECT_ID_DISPLAYPORT << OBJECT_ID_SHIFT)
/****************************************************/
/* Router Object ID definition - Shared with BIOS */
/****************************************************/
#define ROUTER_I2C_EXTENDER_CNTL_ENUM_ID1 ( GRAPH_OBJECT_TYPE_ROUTER << OBJECT_TYPE_SHIFT |\
GRAPH_OBJECT_ENUM_ID1 << ENUM_ID_SHIFT |\
ROUTER_OBJECT_ID_I2C_EXTENDER_CNTL << OBJECT_ID_SHIFT)
/* deleted */
/****************************************************/
/* Object Cap definition - Shared with BIOS */
/****************************************************/
#define GRAPHICS_OBJECT_CAP_I2C 0x00000001L
#define GRAPHICS_OBJECT_CAP_TABLE_ID 0x00000002L
#define GRAPHICS_OBJECT_I2CCOMMAND_TABLE_ID 0x01
#define GRAPHICS_OBJECT_HOTPLUGDETECTIONINTERUPT_TABLE_ID 0x02
#define GRAPHICS_OBJECT_ENCODER_OUTPUT_PROTECTION_TABLE_ID 0x03
#if defined(_X86_)
#pragma pack()
#endif
#endif /*GRAPHICTYPE */

View File

@ -39,8 +39,50 @@
#define ATI_PCIE_WRITE 0x4
#define ATI_PCIE_READ 0x8
static int drm_ati_alloc_pcigart_table(struct drm_device *dev,
struct drm_ati_pcigart_info *gart_info)
static __inline__ void gart_insert_page_into_table(struct drm_ati_pcigart_info *gart_info, dma_addr_t addr, u32 *pci_gart)
{
u32 page_base;
page_base = (u32)addr & ATI_PCIGART_PAGE_MASK;
switch(gart_info->gart_reg_if) {
case DRM_ATI_GART_IGP:
page_base |= (upper_32_bits(addr) & 0xff) << 4;
page_base |= 0xc;
break;
case DRM_ATI_GART_PCIE:
page_base >>= 8;
page_base |= (upper_32_bits(addr) & 0xff) << 24;
page_base |= ATI_PCIE_READ | ATI_PCIE_WRITE;
break;
default:
case DRM_ATI_GART_PCI:
break;
}
*pci_gart = cpu_to_le32(page_base);
}
static __inline__ dma_addr_t gart_get_page_from_table(struct drm_ati_pcigart_info *gart_info, u32 *pci_gart)
{
dma_addr_t retval;
switch(gart_info->gart_reg_if) {
case DRM_ATI_GART_IGP:
retval = (*pci_gart & ATI_PCIGART_PAGE_MASK);
retval += (((*pci_gart & 0xf0) >> 4) << 16) << 16;
break;
case DRM_ATI_GART_PCIE:
retval = (*pci_gart & ~0xc);
retval <<= 8;
break;
case DRM_ATI_GART_PCI:
retval = *pci_gart;
break;
}
return retval;
}
int drm_ati_alloc_pcigart_table(struct drm_device *dev,
struct drm_ati_pcigart_info *gart_info)
{
gart_info->table_handle = drm_pci_alloc(dev, gart_info->table_size,
PAGE_SIZE,
@ -48,8 +90,10 @@ static int drm_ati_alloc_pcigart_table(struct drm_device *dev,
if (gart_info->table_handle == NULL)
return -ENOMEM;
memset(gart_info->table_handle, 0, gart_info->table_size);
return 0;
}
EXPORT_SYMBOL(drm_ati_alloc_pcigart_table);
static void drm_ati_free_pcigart_table(struct drm_device *dev,
struct drm_ati_pcigart_info *gart_info)
@ -80,7 +124,7 @@ int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info
for (i = 0; i < pages; i++) {
if (!entry->busaddr[i])
break;
pci_unmap_single(dev->pdev, entry->busaddr[i],
pci_unmap_page(dev->pdev, entry->busaddr[i],
PAGE_SIZE, PCI_DMA_TODEVICE);
}
@ -104,18 +148,14 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
struct drm_sg_mem *entry = dev->sg;
void *address = NULL;
unsigned long pages;
u32 *pci_gart, page_base;
u32 *pci_gart;
dma_addr_t bus_address = 0;
int i, j, ret = 0;
int max_pages;
dma_addr_t entry_addr;
if (!entry) {
DRM_ERROR("no scatter/gather memory!\n");
goto done;
}
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN && gart_info->table_handle == NULL) {
DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n");
ret = drm_ati_alloc_pcigart_table(dev, gart_info);
@ -123,14 +163,19 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
DRM_ERROR("cannot allocate PCI GART page!\n");
goto done;
}
}
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
address = gart_info->table_handle->vaddr;
bus_address = gart_info->table_handle->busaddr;
} else {
address = gart_info->addr;
bus_address = gart_info->bus_addr;
DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n",
bus_address, (unsigned long)address);
}
if (!entry) {
DRM_ERROR("no scatter/gather memory!\n");
goto done;
}
pci_gart = (u32 *) address;
@ -139,14 +184,10 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
pages = (entry->pages <= max_pages)
? entry->pages : max_pages;
memset(pci_gart, 0, max_pages * sizeof(u32));
for (i = 0; i < pages; i++) {
/* we need to support large memory configurations */
entry->busaddr[i] = pci_map_single(dev->pdev,
page_address(entry->
pagelist[i]),
PAGE_SIZE, PCI_DMA_TODEVICE);
entry->busaddr[i] = pci_map_page(dev->pdev, entry->pagelist[i],
0, PAGE_SIZE, PCI_DMA_TODEVICE);
if (entry->busaddr[i] == 0) {
DRM_ERROR("unable to map PCIGART pages!\n");
drm_ati_pcigart_cleanup(dev, gart_info);
@ -157,22 +198,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
entry_addr = entry->busaddr[i];
for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
page_base = (u32) entry_addr & ATI_PCIGART_PAGE_MASK;
switch(gart_info->gart_reg_if) {
case DRM_ATI_GART_IGP:
page_base |= (upper_32_bits(entry_addr) & 0xff) << 4;
page_base |= 0xc;
break;
case DRM_ATI_GART_PCIE:
page_base >>= 8;
page_base |= (upper_32_bits(entry_addr) & 0xff) << 24;
page_base |= ATI_PCIE_READ | ATI_PCIE_WRITE;
break;
default:
case DRM_ATI_GART_PCI:
break;
}
*pci_gart = cpu_to_le32(page_base);
gart_insert_page_into_table(gart_info, entry_addr, pci_gart);
pci_gart++;
entry_addr += ATI_PCIGART_PAGE_SIZE;
}
@ -192,3 +218,145 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga
return ret;
}
EXPORT_SYMBOL(drm_ati_pcigart_init);
static int ati_pcigart_needs_unbind_cache_adjust(struct drm_ttm_backend *backend)
{
return ((backend->flags & DRM_BE_FLAG_BOUND_CACHED) ? 0 : 1);
}
static int ati_pcigart_populate(struct drm_ttm_backend *backend,
unsigned long num_pages,
struct page **pages,
struct page *dummy_read_page)
{
struct ati_pcigart_ttm_backend *atipci_be =
container_of(backend, struct ati_pcigart_ttm_backend, backend);
atipci_be->pages = pages;
atipci_be->num_pages = num_pages;
atipci_be->populated = 1;
return 0;
}
static int ati_pcigart_bind_ttm(struct drm_ttm_backend *backend,
struct drm_bo_mem_reg *bo_mem)
{
struct ati_pcigart_ttm_backend *atipci_be =
container_of(backend, struct ati_pcigart_ttm_backend, backend);
off_t j;
int i;
struct drm_ati_pcigart_info *info = atipci_be->gart_info;
u32 *pci_gart;
dma_addr_t offset = bo_mem->mm_node->start;
dma_addr_t page_base;
pci_gart = info->addr;
j = offset;
while (j < (offset + atipci_be->num_pages)) {
if (gart_get_page_from_table(info, pci_gart+j))
return -EBUSY;
j++;
}
for (i = 0, j = offset; i < atipci_be->num_pages; i++, j++) {
struct page *cur_page = atipci_be->pages[i];
/* write value */
page_base = page_to_phys(cur_page);
gart_insert_page_into_table(info, page_base, pci_gart + j);
}
#if defined(__i386__) || defined(__x86_64__)
wbinvd();
#else
mb();
#endif
atipci_be->gart_flush_fn(atipci_be->dev);
atipci_be->bound = 1;
atipci_be->offset = offset;
/* need to traverse table and add entries */
DRM_DEBUG("\n");
return 0;
}
static int ati_pcigart_unbind_ttm(struct drm_ttm_backend *backend)
{
struct ati_pcigart_ttm_backend *atipci_be =
container_of(backend, struct ati_pcigart_ttm_backend, backend);
struct drm_ati_pcigart_info *info = atipci_be->gart_info;
unsigned long offset = atipci_be->offset;
int i;
off_t j;
u32 *pci_gart = info->addr;
if (atipci_be->bound != 1)
return -EINVAL;
for (i = 0, j = offset; i < atipci_be->num_pages; i++, j++) {
*(pci_gart + j) = 0;
}
atipci_be->gart_flush_fn(atipci_be->dev);
atipci_be->bound = 0;
atipci_be->offset = 0;
return 0;
}
static void ati_pcigart_clear_ttm(struct drm_ttm_backend *backend)
{
struct ati_pcigart_ttm_backend *atipci_be =
container_of(backend, struct ati_pcigart_ttm_backend, backend);
DRM_DEBUG("\n");
if (atipci_be->pages) {
backend->func->unbind(backend);
atipci_be->pages = NULL;
}
atipci_be->num_pages = 0;
}
static void ati_pcigart_destroy_ttm(struct drm_ttm_backend *backend)
{
struct ati_pcigart_ttm_backend *atipci_be;
if (backend) {
DRM_DEBUG("\n");
atipci_be = container_of(backend, struct ati_pcigart_ttm_backend, backend);
if (atipci_be) {
if (atipci_be->pages) {
backend->func->clear(backend);
}
drm_ctl_free(atipci_be, sizeof(*atipci_be), DRM_MEM_TTM);
}
}
}
static struct drm_ttm_backend_func ati_pcigart_ttm_backend =
{
.needs_ub_cache_adjust = ati_pcigart_needs_unbind_cache_adjust,
.populate = ati_pcigart_populate,
.clear = ati_pcigart_clear_ttm,
.bind = ati_pcigart_bind_ttm,
.unbind = ati_pcigart_unbind_ttm,
.destroy = ati_pcigart_destroy_ttm,
};
struct drm_ttm_backend *ati_pcigart_init_ttm(struct drm_device *dev, struct drm_ati_pcigart_info *info, void (*gart_flush_fn)(struct drm_device *dev))
{
struct ati_pcigart_ttm_backend *atipci_be;
atipci_be = drm_ctl_calloc(1, sizeof (*atipci_be), DRM_MEM_TTM);
if (!atipci_be)
return NULL;
atipci_be->populated = 0;
atipci_be->backend.func = &ati_pcigart_ttm_backend;
// atipci_be->backend.mem_type = DRM_BO_MEM_TT;
atipci_be->gart_info = info;
atipci_be->gart_flush_fn = gart_flush_fn;
atipci_be->dev = dev;
return &atipci_be->backend;
}
EXPORT_SYMBOL(ati_pcigart_init_ttm);

48
linux-core/atom-bits.h Normal file
View File

@ -0,0 +1,48 @@
/*
* Copyright 2008 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Author: Stanislaw Skowronek
*/
#ifndef ATOM_BITS_H
#define ATOM_BITS_H
static inline uint8_t get_u8(void *bios, int ptr)
{
return ((unsigned char *)bios)[ptr];
}
#define U8(ptr) get_u8(ctx->ctx->bios,(ptr))
#define CU8(ptr) get_u8(ctx->bios,(ptr))
static inline uint16_t get_u16(void *bios, int ptr)
{
return get_u8(bios,ptr)|(((uint16_t)get_u8(bios,ptr+1))<<8);
}
#define U16(ptr) get_u16(ctx->ctx->bios,(ptr))
#define CU16(ptr) get_u16(ctx->bios,(ptr))
static inline uint32_t get_u32(void *bios, int ptr)
{
return get_u16(bios,ptr)|(((uint32_t)get_u16(bios,ptr+2))<<16);
}
#define U32(ptr) get_u32(ctx->ctx->bios,(ptr))
#define CU32(ptr) get_u32(ctx->bios,(ptr))
#define CSTR(ptr) (((char *)(ctx->bios))+(ptr))
#endif

100
linux-core/atom-names.h Normal file
View File

@ -0,0 +1,100 @@
/*
* Copyright 2008 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Author: Stanislaw Skowronek
*/
#ifndef ATOM_NAMES_H
#define ATOM_NAMES_H
#include "atom.h"
#ifdef ATOM_DEBUG
#define ATOM_OP_NAMES_CNT 123
static char *atom_op_names[ATOM_OP_NAMES_CNT]={
"RESERVED", "MOVE_REG", "MOVE_PS", "MOVE_WS", "MOVE_FB", "MOVE_PLL",
"MOVE_MC", "AND_REG", "AND_PS", "AND_WS", "AND_FB", "AND_PLL", "AND_MC",
"OR_REG", "OR_PS", "OR_WS", "OR_FB", "OR_PLL", "OR_MC", "SHIFT_LEFT_REG",
"SHIFT_LEFT_PS", "SHIFT_LEFT_WS", "SHIFT_LEFT_FB", "SHIFT_LEFT_PLL",
"SHIFT_LEFT_MC", "SHIFT_RIGHT_REG", "SHIFT_RIGHT_PS", "SHIFT_RIGHT_WS",
"SHIFT_RIGHT_FB", "SHIFT_RIGHT_PLL", "SHIFT_RIGHT_MC", "MUL_REG",
"MUL_PS", "MUL_WS", "MUL_FB", "MUL_PLL", "MUL_MC", "DIV_REG", "DIV_PS",
"DIV_WS", "DIV_FB", "DIV_PLL", "DIV_MC", "ADD_REG", "ADD_PS", "ADD_WS",
"ADD_FB", "ADD_PLL", "ADD_MC", "SUB_REG", "SUB_PS", "SUB_WS", "SUB_FB",
"SUB_PLL", "SUB_MC", "SET_ATI_PORT", "SET_PCI_PORT", "SET_SYS_IO_PORT",
"SET_REG_BLOCK", "SET_FB_BASE", "COMPARE_REG", "COMPARE_PS",
"COMPARE_WS", "COMPARE_FB", "COMPARE_PLL", "COMPARE_MC", "SWITCH",
"JUMP", "JUMP_EQUAL", "JUMP_BELOW", "JUMP_ABOVE", "JUMP_BELOW_OR_EQUAL",
"JUMP_ABOVE_OR_EQUAL", "JUMP_NOT_EQUAL", "TEST_REG", "TEST_PS", "TEST_WS",
"TEST_FB", "TEST_PLL", "TEST_MC", "DELAY_MILLISEC", "DELAY_MICROSEC",
"CALL_TABLE", "REPEAT", "CLEAR_REG", "CLEAR_PS", "CLEAR_WS", "CLEAR_FB",
"CLEAR_PLL", "CLEAR_MC", "NOP", "EOT", "MASK_REG", "MASK_PS", "MASK_WS",
"MASK_FB", "MASK_PLL", "MASK_MC", "POST_CARD", "BEEP", "SAVE_REG",
"RESTORE_REG", "SET_DATA_BLOCK", "XOR_REG", "XOR_PS", "XOR_WS", "XOR_FB",
"XOR_PLL", "XOR_MC", "SHL_REG", "SHL_PS", "SHL_WS", "SHL_FB", "SHL_PLL",
"SHL_MC", "SHR_REG", "SHR_PS", "SHR_WS", "SHR_FB", "SHR_PLL", "SHR_MC",
"DEBUG", "CTB_DS",
};
#define ATOM_TABLE_NAMES_CNT 74
static char *atom_table_names[ATOM_TABLE_NAMES_CNT]={
"ASIC_Init", "GetDisplaySurfaceSize", "ASIC_RegistersInit",
"VRAM_BlockVenderDetection", "SetClocksRatio", "MemoryControllerInit",
"GPIO_PinInit", "MemoryParamAdjust", "DVOEncoderControl",
"GPIOPinControl", "SetEngineClock", "SetMemoryClock", "SetPixelClock",
"DynamicClockGating", "ResetMemoryDLL", "ResetMemoryDevice",
"MemoryPLLInit", "EnableMemorySelfRefresh", "AdjustMemoryController",
"EnableASIC_StaticPwrMgt", "ASIC_StaticPwrMgtStatusChange",
"DAC_LoadDetection", "TMDS2EncoderControl", "LCD1OutputControl",
"DAC1EncoderControl", "DAC2EncoderControl", "DVOOutputControl",
"CV1OutputControl", "SetCRTC_DPM_State", "TVEncoderControl",
"TMDS1EncoderControl", "LVDSEncoderControl", "TV1OutputControl",
"EnableScaler", "BlankCRTC", "EnableCRTC", "GetPixelClock",
"EnableVGA_Render", "EnableVGA_Access", "SetCRTC_Timing",
"SetCRTC_OverScan", "SetCRTC_Replication", "SelectCRTC_Source",
"EnableGraphSurfaces", "UpdateCRTC_DoubleBufferRegisters",
"LUT_AutoFill", "EnableHW_IconCursor", "GetMemoryClock",
"GetEngineClock", "SetCRTC_UsingDTDTiming", "TVBootUpStdPinDetection",
"DFP2OutputControl", "VRAM_BlockDetectionByStrap", "MemoryCleanUp",
"ReadEDIDFromHWAssistedI2C", "WriteOneByteToHWAssistedI2C",
"ReadHWAssistedI2CStatus", "SpeedFanControl", "PowerConnectorDetection",
"MC_Synchronization", "ComputeMemoryEnginePLL", "MemoryRefreshConversion",
"VRAM_GetCurrentInfoBlock", "DynamicMemorySettings", "MemoryTraining",
"EnableLVDS_SS", "DFP1OutputControl", "SetVoltage", "CRT1OutputControl",
"CRT2OutputControl", "SetupHWAssistedI2CStatus", "ClockSource",
"MemoryDeviceInit", "EnableYUV",
};
#define ATOM_IO_NAMES_CNT 5
static char *atom_io_names[ATOM_IO_NAMES_CNT]={
"MM", "PLL", "MC", "PCIE", "PCIE PORT",
};
#else
#define ATOM_OP_NAMES_CNT 0
#define ATOM_TABLE_NAMES_CNT 0
#define ATOM_IO_NAMES_CNT 0
#endif
#endif

42
linux-core/atom-types.h Normal file
View File

@ -0,0 +1,42 @@
/*
* Copyright 2008 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Author: Dave Airlie
*/
#ifndef ATOM_TYPES_H
#define ATOM_TYPES_H
/* sync atom types to kernel types */
typedef uint16_t USHORT;
typedef uint32_t ULONG;
typedef uint8_t UCHAR;
#ifndef ATOM_BIG_ENDIAN
#if defined(__BIG_ENDIAN)
#define ATOM_BIG_ENDIAN 1
#else
#define ATOM_BIG_ENDIAN 0
#endif
#endif
#endif

1145
linux-core/atom.c Normal file

File diff suppressed because it is too large Load Diff

148
linux-core/atom.h Normal file
View File

@ -0,0 +1,148 @@
/*
* Copyright 2008 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Author: Stanislaw Skowronek
*/
#ifndef ATOM_H
#define ATOM_H
#include <linux/types.h>
#include "drmP.h"
#define ATOM_BIOS_MAGIC 0xAA55
#define ATOM_ATI_MAGIC_PTR 0x30
#define ATOM_ATI_MAGIC " 761295520"
#define ATOM_ROM_TABLE_PTR 0x48
#define ATOM_ROM_MAGIC "ATOM"
#define ATOM_ROM_MAGIC_PTR 4
#define ATOM_ROM_MSG_PTR 0x10
#define ATOM_ROM_CMD_PTR 0x1E
#define ATOM_ROM_DATA_PTR 0x20
#define ATOM_CMD_INIT 0
#define ATOM_CMD_SETSCLK 0x0A
#define ATOM_CMD_SETMCLK 0x0B
#define ATOM_CMD_SETPCLK 0x0C
#define ATOM_DATA_FWI_PTR 0xC
#define ATOM_DATA_IIO_PTR 0x32
#define ATOM_FWI_DEFSCLK_PTR 8
#define ATOM_FWI_DEFMCLK_PTR 0xC
#define ATOM_FWI_MAXSCLK_PTR 0x24
#define ATOM_FWI_MAXMCLK_PTR 0x28
#define ATOM_CT_SIZE_PTR 0
#define ATOM_CT_WS_PTR 4
#define ATOM_CT_PS_PTR 5
#define ATOM_CT_PS_MASK 0x7F
#define ATOM_CT_CODE_PTR 6
#define ATOM_OP_CNT 123
#define ATOM_OP_EOT 91
#define ATOM_CASE_MAGIC 0x63
#define ATOM_CASE_END 0x5A5A
#define ATOM_ARG_REG 0
#define ATOM_ARG_PS 1
#define ATOM_ARG_WS 2
#define ATOM_ARG_ID 4
#define ATOM_ARG_FB 3
#define ATOM_ARG_IMM 5
#define ATOM_ARG_PLL 6
#define ATOM_ARG_MC 7
#define ATOM_SRC_DWORD 0
#define ATOM_SRC_WORD0 1
#define ATOM_SRC_WORD8 2
#define ATOM_SRC_WORD16 3
#define ATOM_SRC_BYTE0 4
#define ATOM_SRC_BYTE8 5
#define ATOM_SRC_BYTE16 6
#define ATOM_SRC_BYTE24 7
#define ATOM_WS_QUOTIENT 0x40
#define ATOM_WS_REMAINDER 0x41
#define ATOM_WS_DATAPTR 0x42
#define ATOM_WS_SHIFT 0x43
#define ATOM_WS_OR_MASK 0x44
#define ATOM_WS_AND_MASK 0x45
#define ATOM_WS_FB_WINDOW 0x46
#define ATOM_WS_ATTRIBUTES 0x47
#define ATOM_IIO_NOP 0
#define ATOM_IIO_START 1
#define ATOM_IIO_READ 2
#define ATOM_IIO_WRITE 3
#define ATOM_IIO_CLEAR 4
#define ATOM_IIO_SET 5
#define ATOM_IIO_MOVE_INDEX 6
#define ATOM_IIO_MOVE_ATTR 7
#define ATOM_IIO_MOVE_DATA 8
#define ATOM_IIO_END 9
#define ATOM_IO_MM 0
#define ATOM_IO_PCI 1
#define ATOM_IO_SYSIO 2
#define ATOM_IO_IIO 0x80
struct card_info {
struct drm_device *dev;
void (* reg_write)(struct card_info *, uint32_t, uint32_t); // filled by driver
uint32_t (* reg_read)(struct card_info *, uint32_t); // filled by driver
void (* mc_write)(struct card_info *, uint32_t, uint32_t); // filled by driver
uint32_t (* mc_read)(struct card_info *, uint32_t); // filled by driver
// int (* read_rom)(struct card_info *, uint8_t *); // filled by driver
};
struct atom_context {
struct card_info *card;
void *bios;
uint32_t cmd_table, data_table;
uint16_t *iio;
uint16_t data_block;
uint32_t fb_base;
uint32_t divmul[2];
uint16_t io_attr;
uint16_t reg_block;
uint8_t shift;
int cs_equal, cs_above;
int io_mode;
};
extern int atom_debug;
struct atom_context *atom_parse(struct card_info *, void *);
void atom_execute_table(struct atom_context *, int, uint32_t *);
int atom_asic_init(struct atom_context *);
void atom_destroy(struct atom_context *);
void atom_parse_data_header(struct atom_context *ctx, int index, uint16_t *size, uint8_t *frev, uint8_t *crev, uint16_t *data_start);
void atom_parse_cmd_header(struct atom_context *ctx, int index, uint8_t *frev, uint8_t *crev);
#include "atom-types.h"
#include "atombios.h"
#include "ObjectID.h"
#endif

4498
linux-core/atombios.h Normal file

File diff suppressed because it is too large Load Diff

382
linux-core/atombios_crtc.c Normal file
View File

@ -0,0 +1,382 @@
/*
* Copyright 2007-8 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Dave Airlie
* Alex Deucher
*/
#include "drmP.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
#include "drm_crtc_helper.h"
#include "atom.h"
#include "atom-bits.h"
static void atombios_enable_crtc(struct drm_crtc *crtc, int state)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
int index = GetIndexIntoMasterTable(COMMAND, EnableCRTC);
ENABLE_CRTC_PS_ALLOCATION args;
memset(&args, 0, sizeof(args));
args.ucCRTC = radeon_crtc->crtc_id;
args.ucEnable = state;
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
}
static void atombios_enable_crtc_memreq(struct drm_crtc *crtc, int state)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
int index = GetIndexIntoMasterTable(COMMAND, EnableCRTCMemReq);
ENABLE_CRTC_PS_ALLOCATION args;
memset(&args, 0, sizeof(args));
args.ucCRTC = radeon_crtc->crtc_id;
args.ucEnable = state;
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
}
static void atombios_blank_crtc(struct drm_crtc *crtc, int state)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC);
BLANK_CRTC_PS_ALLOCATION args;
memset(&args, 0, sizeof(args));
args.ucCRTC = radeon_crtc->crtc_id;
args.ucBlanking = state;
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
}
void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
switch(mode) {
case DRM_MODE_DPMS_ON:
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
if (radeon_is_dce3(dev_priv))
atombios_enable_crtc_memreq(crtc, 1);
atombios_enable_crtc(crtc, 1);
atombios_blank_crtc(crtc, 0);
radeon_crtc_load_lut(crtc);
break;
case DRM_MODE_DPMS_OFF:
atombios_blank_crtc(crtc, 1);
atombios_enable_crtc(crtc, 0);
if (radeon_is_dce3(dev_priv))
atombios_enable_crtc_memreq(crtc, 0);
break;
}
}
void atombios_crtc_set_timing(struct drm_crtc *crtc, SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_param)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION conv_param;
int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_Timing);
conv_param.usH_Total = cpu_to_le16(crtc_param->usH_Total);
conv_param.usH_Disp = cpu_to_le16(crtc_param->usH_Disp);
conv_param.usH_SyncStart = cpu_to_le16(crtc_param->usH_SyncStart);
conv_param.usH_SyncWidth = cpu_to_le16(crtc_param->usH_SyncWidth);
conv_param.usV_Total = cpu_to_le16(crtc_param->usV_Total);
conv_param.usV_Disp = cpu_to_le16(crtc_param->usV_Disp);
conv_param.usV_SyncStart = cpu_to_le16(crtc_param->usV_SyncStart);
conv_param.usV_SyncWidth = cpu_to_le16(crtc_param->usV_SyncWidth);
conv_param.susModeMiscInfo.usAccess = cpu_to_le16(crtc_param->susModeMiscInfo.usAccess);
conv_param.ucCRTC = crtc_param->ucCRTC;
conv_param.ucOverscanRight = crtc_param->ucOverscanRight;
conv_param.ucOverscanLeft = crtc_param->ucOverscanLeft;
conv_param.ucOverscanBottom = crtc_param->ucOverscanBottom;
conv_param.ucOverscanTop = crtc_param->ucOverscanTop;
conv_param.ucReserved = crtc_param->ucReserved;
printk("executing set crtc timing\n");
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&conv_param);
}
void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode,
int pll_flags)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
uint8_t frev, crev;
int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock);
SET_PIXEL_CLOCK_PS_ALLOCATION spc_param;
PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr;
PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr;
uint32_t sclock = mode->clock;
uint32_t ref_div = 0, fb_div = 0, post_div = 0;
memset(&spc_param, 0, sizeof(SET_PIXEL_CLOCK_PS_ALLOCATION));
if (radeon_is_avivo(dev_priv)) {
uint32_t temp;
pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
radeon_compute_pll(&dev_priv->mode_info.pll, mode->clock,
&temp, &fb_div, &ref_div, &post_div, pll_flags);
sclock = temp;
if (radeon_crtc->crtc_id == 0) {
temp = RADEON_READ(AVIVO_P1PLL_INT_SS_CNTL);
RADEON_WRITE(AVIVO_P1PLL_INT_SS_CNTL, temp & ~1);
} else {
temp = RADEON_READ(AVIVO_P2PLL_INT_SS_CNTL);
RADEON_WRITE(AVIVO_P2PLL_INT_SS_CNTL, temp & ~1);
}
} else {
#if 0 // TODO r400
sclock = save->dot_clock_freq;
fb_div = save->feedback_div;
post_div = save->post_div;
ref_div = save->ppll_ref_div;
#endif
}
/* */
atom_parse_cmd_header(dev_priv->mode_info.atom_context, index, &frev, &crev);
switch(frev) {
case 1:
switch(crev) {
case 1:
case 2:
spc2_ptr = (PIXEL_CLOCK_PARAMETERS_V2*)&spc_param.sPCLKInput;
spc2_ptr->usPixelClock = cpu_to_le16(sclock);
spc2_ptr->usRefDiv = cpu_to_le16(ref_div);
spc2_ptr->usFbDiv = cpu_to_le16(fb_div);
spc2_ptr->ucPostDiv = post_div;
spc2_ptr->ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
spc2_ptr->ucCRTC = radeon_crtc->crtc_id;
spc2_ptr->ucRefDivSrc = 1;
break;
case 3:
spc3_ptr = (PIXEL_CLOCK_PARAMETERS_V3*)&spc_param.sPCLKInput;
spc3_ptr->usPixelClock = cpu_to_le16(sclock);
spc3_ptr->usRefDiv = cpu_to_le16(ref_div);
spc3_ptr->usFbDiv = cpu_to_le16(fb_div);
spc3_ptr->ucPostDiv = post_div;
spc3_ptr->ucPpll = radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2);
/* TODO insert output encoder object stuff herre for r600 */
break;
default:
DRM_ERROR("Unknown table version %d %d\n", frev, crev);
return;
}
break;
default:
DRM_ERROR("Unknown table version %d %d\n", frev, crev);
return;
}
printk("executing set pll\n");
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&spc_param);
}
void atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_framebuffer *radeon_fb;
struct drm_radeon_gem_object *obj_priv;
uint32_t fb_location, fb_format, fb_pitch_pixels;
if (!crtc->fb)
return;
radeon_fb = to_radeon_framebuffer(crtc->fb);
obj_priv = radeon_fb->obj->driver_private;
fb_location = obj_priv->bo->offset + dev_priv->fb_location;
switch(crtc->fb->bits_per_pixel) {
case 15:
fb_format = AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | AVIVO_D1GRPH_CONTROL_16BPP_ARGB1555;
break;
case 16:
fb_format = AVIVO_D1GRPH_CONTROL_DEPTH_16BPP | AVIVO_D1GRPH_CONTROL_16BPP_RGB565;
break;
case 24:
case 32:
fb_format = AVIVO_D1GRPH_CONTROL_DEPTH_32BPP | AVIVO_D1GRPH_CONTROL_32BPP_ARGB8888;
break;
default:
DRM_ERROR("Unsupported screen depth %d\n", crtc->fb->bits_per_pixel);
return;
}
/* TODO tiling */
if (radeon_crtc->crtc_id == 0)
RADEON_WRITE(AVIVO_D1VGA_CONTROL, 0);
else
RADEON_WRITE(AVIVO_D2VGA_CONTROL, 0);
RADEON_WRITE(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, AVIVO_D1GRPH_UPDATE_LOCK);
RADEON_WRITE(AVIVO_D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, fb_location);
RADEON_WRITE(AVIVO_D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, fb_location);
RADEON_WRITE(AVIVO_D1GRPH_CONTROL + radeon_crtc->crtc_offset, fb_format);
RADEON_WRITE(AVIVO_D1GRPH_SURFACE_OFFSET_X + radeon_crtc->crtc_offset, 0);
RADEON_WRITE(AVIVO_D1GRPH_SURFACE_OFFSET_Y + radeon_crtc->crtc_offset, 0);
RADEON_WRITE(AVIVO_D1GRPH_X_START + radeon_crtc->crtc_offset, x);
RADEON_WRITE(AVIVO_D1GRPH_Y_START + radeon_crtc->crtc_offset, y);
RADEON_WRITE(AVIVO_D1GRPH_X_END + radeon_crtc->crtc_offset, x + crtc->mode.hdisplay);
RADEON_WRITE(AVIVO_D1GRPH_Y_END + radeon_crtc->crtc_offset, y + crtc->mode.vdisplay);
fb_pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8);
RADEON_WRITE(AVIVO_D1GRPH_PITCH + radeon_crtc->crtc_offset, fb_pitch_pixels);
RADEON_WRITE(AVIVO_D1GRPH_ENABLE + radeon_crtc->crtc_offset, 1);
/* unlock the grph regs */
RADEON_WRITE(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, 0);
/* lock the mode regs */
RADEON_WRITE(AVIVO_D1SCL_UPDATE + radeon_crtc->crtc_offset, AVIVO_D1SCL_UPDATE_LOCK);
RADEON_WRITE(AVIVO_D1MODE_DESKTOP_HEIGHT + radeon_crtc->crtc_offset,
crtc->mode.vdisplay);
RADEON_WRITE(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset, (x << 16) | y);
RADEON_WRITE(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
(crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
/* unlock the mode regs */
RADEON_WRITE(AVIVO_D1SCL_UPDATE + radeon_crtc->crtc_offset, 0);
}
void atombios_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
int x, int y)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
struct drm_encoder *encoder;
SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing;
int pll_flags = 0;
/* TODO color tiling */
memset(&crtc_timing, 0, sizeof(crtc_timing));
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
}
crtc_timing.ucCRTC = radeon_crtc->crtc_id;
crtc_timing.usH_Total = adjusted_mode->crtc_htotal;
crtc_timing.usH_Disp = adjusted_mode->crtc_hdisplay;
crtc_timing.usH_SyncStart = adjusted_mode->crtc_hsync_start;
crtc_timing.usH_SyncWidth = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
crtc_timing.usV_Total = adjusted_mode->crtc_vtotal;
crtc_timing.usV_Disp = adjusted_mode->crtc_vdisplay;
crtc_timing.usV_SyncStart = adjusted_mode->crtc_vsync_start;
crtc_timing.usV_SyncWidth = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
crtc_timing.susModeMiscInfo.usAccess |= ATOM_VSYNC_POLARITY;
if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
crtc_timing.susModeMiscInfo.usAccess |= ATOM_HSYNC_POLARITY;
if (adjusted_mode->flags & DRM_MODE_FLAG_CSYNC)
crtc_timing.susModeMiscInfo.usAccess |= ATOM_COMPOSITESYNC;
if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
crtc_timing.susModeMiscInfo.usAccess |= ATOM_INTERLACE;
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE;
if (radeon_is_avivo(dev_priv)) {
atombios_crtc_set_base(crtc, x, y);
}
atombios_crtc_set_pll(crtc, adjusted_mode, pll_flags);
atombios_crtc_set_timing(crtc, &crtc_timing);
}
static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
}
static void atombios_crtc_prepare(struct drm_crtc *crtc)
{
atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
}
static void atombios_crtc_commit(struct drm_crtc *crtc)
{
atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
}
static const struct drm_crtc_helper_funcs atombios_helper_funcs = {
.dpms = atombios_crtc_dpms,
.mode_fixup = atombios_crtc_mode_fixup,
.mode_set = atombios_crtc_mode_set,
.mode_set_base = atombios_crtc_set_base,
.prepare = atombios_crtc_prepare,
.commit = atombios_crtc_commit,
};
void radeon_atombios_init_crtc(struct drm_device *dev,
struct radeon_crtc *radeon_crtc)
{
if (radeon_crtc->crtc_id == 1)
radeon_crtc->crtc_offset = AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
}

View File

@ -1046,8 +1046,7 @@ struct drm_agp_ttm_backend {
int populated;
};
#endif
typedef struct ati_pcigart_ttm_backend {
struct ati_pcigart_ttm_backend {
struct drm_ttm_backend backend;
int populated;
void (*gart_flush_fn)(struct drm_device *dev);
@ -1057,7 +1056,8 @@ typedef struct ati_pcigart_ttm_backend {
int num_pages;
int bound;
struct drm_device *dev;
} ati_pcigart_ttm_backend_t;
};
extern struct drm_ttm_backend *ati_pcigart_init_ttm(struct drm_device *dev, struct drm_ati_pcigart_info *info, void (*gart_flush_fn)(struct drm_device *dev));
static __inline__ int drm_core_check_feature(struct drm_device *dev,
int feature)
@ -1396,6 +1396,8 @@ extern int drm_sg_free(struct drm_device *dev, void *data,
/* ATI PCIGART support (ati_pcigart.h) */
extern int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info);
extern int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info);
extern int drm_ati_alloc_pcigart_table(struct drm_device *dev,
struct drm_ati_pcigart_info *gart_info);
extern drm_dma_handle_t *drm_pci_alloc(struct drm_device *dev, size_t size,
size_t align, dma_addr_t maxaddr);

View File

@ -51,7 +51,6 @@
static void drm_bo_destroy_locked(struct drm_buffer_object *bo);
static int drm_bo_setup_vm_locked(struct drm_buffer_object *bo);
static void drm_bo_takedown_vm_locked(struct drm_buffer_object *bo);
static void drm_bo_unmap_virtual(struct drm_buffer_object *bo);
static inline uint64_t drm_bo_type_flags(unsigned type)
@ -458,6 +457,7 @@ static void drm_bo_destroy_locked(struct drm_buffer_object *bo)
DRM_ASSERT_LOCKED(&dev->struct_mutex);
DRM_DEBUG("freeing %p\n", bo);
if (list_empty(&bo->lru) && bo->mem.mm_node == NULL &&
list_empty(&bo->pinned_lru) && bo->pinned_node == NULL &&
list_empty(&bo->ddestroy) && atomic_read(&bo->usage) == 0) {
@ -1838,8 +1838,8 @@ out_err_unlocked:
EXPORT_SYMBOL(drm_buffer_object_create);
static int drm_bo_add_user_object(struct drm_file *file_priv,
struct drm_buffer_object *bo, int shareable)
int drm_bo_add_user_object(struct drm_file *file_priv,
struct drm_buffer_object *bo, int shareable)
{
struct drm_device *dev = file_priv->minor->dev;
int ret;
@ -1858,6 +1858,7 @@ out:
mutex_unlock(&dev->struct_mutex);
return ret;
}
EXPORT_SYMBOL(drm_bo_add_user_object);
int drm_bo_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
@ -2705,7 +2706,7 @@ void drm_bo_unmap_virtual(struct drm_buffer_object *bo)
* Remove any associated vm mapping on the drm device node that
* would have been created for a drm_bo_type_device buffer
*/
static void drm_bo_takedown_vm_locked(struct drm_buffer_object *bo)
void drm_bo_takedown_vm_locked(struct drm_buffer_object *bo)
{
struct drm_map_list *list;
drm_local_map_t *map;
@ -2734,6 +2735,7 @@ static void drm_bo_takedown_vm_locked(struct drm_buffer_object *bo)
list->user_token = 0ULL;
drm_bo_usage_deref_locked(&bo);
}
EXPORT_SYMBOL(drm_bo_takedown_vm_locked);
/**
* drm_bo_setup_vm_locked:

View File

@ -781,19 +781,17 @@ EXPORT_SYMBOL(pci_get_bus_and_slot);
#endif
#if defined(DRM_KMAP_ATOMIC_PROT_PFN)
#define drm_kmap_get_fixmap_pte(vaddr) \
pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), vaddr), (vaddr)), (vaddr))
void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type,
pgprot_t protection)
{
enum fixed_addresses idx;
unsigned long vaddr;
static pte_t *km_pte;
int level;
static int initialized = 0;
if (unlikely(!initialized)) {
km_pte = drm_kmap_get_fixmap_pte(__fix_to_virt(FIX_KMAP_BEGIN));
km_pte = lookup_address(__fix_to_virt(FIX_KMAP_BEGIN), &level);
initialized = 1;
}

View File

@ -122,24 +122,31 @@ char *drm_get_subconnector_name(int val)
return "unknown";
}
struct drm_conn_prop_enum_list {
int type;
char *name;
int count;
};
/*
* Connector and encoder types.
*/
static struct drm_prop_enum_list drm_connector_enum_list[] =
{ { DRM_MODE_CONNECTOR_Unknown, "Unknown" },
{ DRM_MODE_CONNECTOR_VGA, "VGA" },
{ DRM_MODE_CONNECTOR_DVII, "DVI-I" },
{ DRM_MODE_CONNECTOR_DVID, "DVI-D" },
{ DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
{ DRM_MODE_CONNECTOR_Composite, "Composite" },
{ DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" },
{ DRM_MODE_CONNECTOR_LVDS, "LVDS" },
{ DRM_MODE_CONNECTOR_Component, "Component" },
{ DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" },
{ DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort" },
{ DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A" },
{ DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B" },
static struct drm_conn_prop_enum_list drm_connector_enum_list[] =
{ { DRM_MODE_CONNECTOR_Unknown, "Unknown", 0 },
{ DRM_MODE_CONNECTOR_VGA, "VGA", 0 },
{ DRM_MODE_CONNECTOR_DVII, "DVI-I", 0 },
{ DRM_MODE_CONNECTOR_DVID, "DVI-D", 0 },
{ DRM_MODE_CONNECTOR_DVIA, "DVI-A", 0 },
{ DRM_MODE_CONNECTOR_Composite, "Composite", 0 },
{ DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO", 0 },
{ DRM_MODE_CONNECTOR_LVDS, "LVDS", 0 },
{ DRM_MODE_CONNECTOR_Component, "Component", 0 },
{ DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN", 0 },
{ DRM_MODE_CONNECTOR_DisplayPort, "DisplayPort", 0 },
{ DRM_MODE_CONNECTOR_HDMIA, "HDMI Type A", 0 },
{ DRM_MODE_CONNECTOR_HDMIB, "HDMI Type B", 0 },
};
static struct drm_prop_enum_list drm_encoder_enum_list[] =
{ { DRM_MODE_ENCODER_NONE, "None" },
{ DRM_MODE_ENCODER_DAC, "DAC" },
@ -226,7 +233,7 @@ static void drm_mode_object_put(struct drm_device *dev, struct drm_mode_object *
idr_remove(&dev->mode_config.crtc_idr, object->id);
}
static void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type)
void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type)
{
struct drm_mode_object *obj;
@ -236,6 +243,7 @@ static void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t
return obj;
}
EXPORT_SYMBOL(drm_mode_object_find);
/**
* drm_crtc_from_fb - find the CRTC structure associated with an fb
@ -419,7 +427,7 @@ void drm_connector_init(struct drm_device *dev,
connector->funcs = funcs;
drm_mode_object_get(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR);
connector->connector_type = connector_type;
connector->connector_type_id = 1; /* TODO */
connector->connector_type_id = ++drm_connector_enum_list[connector_type].count; /* TODO */
INIT_LIST_HEAD(&connector->user_modes);
INIT_LIST_HEAD(&connector->probed_modes);
INIT_LIST_HEAD(&connector->modes);
@ -756,6 +764,9 @@ int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
total_objects += dev->mode_config.num_connector;
total_objects += dev->mode_config.num_encoder;
if (total_objects == 0)
return -EINVAL;
group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL);
if (!group->id_list)
return -ENOMEM;
@ -771,9 +782,10 @@ int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_gro
struct drm_crtc *crtc;
struct drm_encoder *encoder;
struct drm_connector *connector;
int ret;
if (drm_mode_group_init(dev, group))
return -ENOMEM;
if ((ret = drm_mode_group_init(dev, group)))
return ret;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
group->id_list[group->num_crtcs++] = crtc->base.id;

View File

@ -664,6 +664,7 @@ extern void drm_mode_connector_detach_encoder(struct drm_connector *connector,
struct drm_encoder *encoder);
extern bool drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
int gamma_size);
extern void *drm_mode_object_find(struct drm_device *dev, uint32_t id, uint32_t type);
/* IOCTLs */
extern int drm_mode_getresources(struct drm_device *dev,
void *data, struct drm_file *file_priv);

View File

@ -500,7 +500,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
crtc_funcs = set->crtc->helper_private;
DRM_DEBUG("crtc: %p fb: %p connectors: %p num_connectors: %i (x, y) (%i, %i)\n", set->crtc, set->fb, set->connectors, set->num_connectors, set->x, set->y);
DRM_DEBUG("crtc: %p %d fb: %p connectors: %p num_connectors: %i (x, y) (%i, %i)\n", set->crtc, set->crtc->base.id, set->fb, set->connectors, set->num_connectors, set->x, set->y);
dev = set->crtc->dev;

View File

@ -54,6 +54,8 @@ struct drm_encoder_helper_funcs {
void (*mode_set)(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
/* detect for DAC style encoders */
enum drm_connector_status (*detect)(struct drm_encoder *encoder, struct drm_connector *connector);
};
struct drm_connector_helper_funcs {

View File

@ -100,7 +100,6 @@ drm_gem_object_alloc(struct drm_device *dev, size_t size)
kfree(obj);
return NULL;
}
kref_init(&obj->refcount);
kref_init(&obj->handlecount);
obj->size = size;

View File

@ -546,6 +546,7 @@ void drm_mode_connector_list_update(struct drm_connector *connector)
struct drm_display_mode *mode;
struct drm_display_mode *pmode, *pt;
int found_it;
list_for_each_entry_safe(pmode, pt, &connector->probed_modes,
head) {
found_it = 0;

View File

@ -680,6 +680,8 @@ extern int drm_bo_pci_offset(struct drm_device *dev,
unsigned long *bus_size);
extern int drm_mem_reg_is_pci(struct drm_device *dev, struct drm_bo_mem_reg *mem);
extern int drm_bo_add_user_object(struct drm_file *file_priv,
struct drm_buffer_object *bo, int shareable);
extern void drm_bo_usage_deref_locked(struct drm_buffer_object **bo);
extern void drm_bo_usage_deref_unlocked(struct drm_buffer_object **bo);
extern void drm_putback_buffer_objects(struct drm_device *dev);
@ -718,6 +720,8 @@ extern int drm_bo_do_validate(struct drm_buffer_object *bo,
uint32_t fence_class,
struct drm_bo_info_rep *rep);
extern int drm_bo_evict_cached(struct drm_buffer_object *bo);
extern void drm_bo_takedown_vm_locked(struct drm_buffer_object *bo);
/*
* Buffer object memory move- and map helpers.
* drm_bo_move.c

View File

@ -544,14 +544,14 @@ static void intelfb_on(struct fb_info *info)
if (crtc->base.id == par->crtc_ids[i])
break;
crtc_funcs->dpms(crtc, DPMSModeOn);
crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
/* Found a CRTC on this fb, now find encoders */
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (encoder->crtc == crtc) {
struct drm_encoder_helper_funcs *encoder_funcs;
encoder_funcs = encoder->helper_private;
encoder_funcs->dpms(encoder, DPMSModeOn);
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
}
}
}
@ -584,7 +584,7 @@ static void intelfb_off(struct fb_info *info, int dpms_mode)
encoder_funcs->dpms(encoder, dpms_mode);
}
}
if (dpms_mode == DPMSModeOff)
if (dpms_mode == DRM_MODE_DPMS_OFF)
crtc_funcs->dpms(crtc, dpms_mode);
}
}
@ -596,16 +596,16 @@ int intelfb_blank(int blank, struct fb_info *info)
intelfb_on(info);
break;
case FB_BLANK_NORMAL:
intelfb_off(info, DPMSModeStandby);
intelfb_off(info, DRM_MODE_DPMS_STANDBY);
break;
case FB_BLANK_HSYNC_SUSPEND:
intelfb_off(info, DPMSModeStandby);
intelfb_off(info, DRM_MODE_DPMS_STANDBY);
break;
case FB_BLANK_VSYNC_SUSPEND:
intelfb_off(info, DPMSModeSuspend);
intelfb_off(info, DRM_MODE_DPMS_SUSPEND);
break;
case FB_BLANK_POWERDOWN:
intelfb_off(info, DPMSModeOff);
intelfb_off(info, DRM_MODE_DPMS_OFF);
break;
}
return 0;

View File

@ -0,0 +1,361 @@
/*
* Copyright 2007-8 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Dave Airlie
* Alex Deucher
*/
#include "drmP.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
#include "atom.h"
#include "atom-bits.h"
union atom_supported_devices {
struct _ATOM_SUPPORTED_DEVICES_INFO info;
struct _ATOM_SUPPORTED_DEVICES_INFO_2 info_2;
struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1;
};
static inline struct radeon_i2c_bus_rec radeon_lookup_gpio_for_ddc(struct drm_device *dev, uint8_t id)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct atom_context *ctx = dev_priv->mode_info.atom_context;
ATOM_GPIO_I2C_ASSIGMENT gpio;
struct radeon_i2c_bus_rec i2c;
int index = GetIndexIntoMasterTable(DATA, GPIO_I2C_Info);
struct _ATOM_GPIO_I2C_INFO *i2c_info;
uint16_t data_offset;
memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
i2c.valid = false;
atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset);
i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
gpio = i2c_info->asGPIO_Info[id];
i2c.mask_clk_reg = le16_to_cpu(gpio.usClkMaskRegisterIndex) * 4;
i2c.mask_data_reg = le16_to_cpu(gpio.usDataMaskRegisterIndex) * 4;
i2c.put_clk_reg = le16_to_cpu(gpio.usClkEnRegisterIndex) * 4;
i2c.put_data_reg = le16_to_cpu(gpio.usDataEnRegisterIndex) * 4;
i2c.get_clk_reg = le16_to_cpu(gpio.usClkY_RegisterIndex) * 4;
i2c.get_data_reg = le16_to_cpu(gpio.usDataY_RegisterIndex) * 4;
i2c.mask_clk_mask = (1 << gpio.ucClkMaskShift);
i2c.mask_data_mask = (1 << gpio.ucDataMaskShift);
i2c.put_clk_mask = (1 << gpio.ucClkEnShift);
i2c.put_data_mask = (1 << gpio.ucDataEnShift);
i2c.get_clk_mask = (1 << gpio.ucClkY_Shift);
i2c.get_data_mask = (1 << gpio.ucDataY_Shift);
i2c.valid = true;
return i2c;
}
static void radeon_atom_apply_quirks(struct drm_device *dev, int index)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_mode_info *mode_info = &dev_priv->mode_info;
if ((dev->pdev->device == 0x791e) &&
(dev->pdev->subsystem_vendor == 0x1043) &&
(dev->pdev->subsystem_device == 0x826d)) {
if ((mode_info->bios_connector[index].connector_type == CONNECTOR_HDMI_TYPE_A) &&
(mode_info->bios_connector[index].tmds_type == TMDS_LVTMA)) {
mode_info->bios_connector[index].connector_type = CONNECTOR_DVI_D;
}
}
if ((dev->pdev->device == 0x5653) &&
(dev->pdev->subsystem_vendor == 0x1462) &&
(dev->pdev->subsystem_device == 0x0291)) {
if (mode_info->bios_connector[index].connector_type == CONNECTOR_LVDS) {
mode_info->bios_connector[index].ddc_i2c.valid = false;
}
}
}
bool radeon_get_atom_connector_info_from_bios_connector_table(struct drm_device *dev)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_mode_info *mode_info = &dev_priv->mode_info;
struct atom_context *ctx = mode_info->atom_context;
int index = GetIndexIntoMasterTable(DATA, SupportedDevicesInfo);
uint16_t size, data_offset;
uint8_t frev, crev;
uint16_t device_support;
union atom_supported_devices *supported_devices;
int i,j;
atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset);
supported_devices = (union atom_supported_devices *)(ctx->bios + data_offset);
device_support = le16_to_cpu(supported_devices->info.usDeviceSupport);
for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
ATOM_CONNECTOR_INFO_I2C ci = supported_devices->info.asConnInfo[i];
if (!(device_support & (1 << i))) {
mode_info->bios_connector[i].valid = false;
continue;
}
if (i == ATOM_DEVICE_CV_INDEX) {
DRM_DEBUG("Skipping Component Video\n");
mode_info->bios_connector[i].valid = false;
continue;
}
if (i == ATOM_DEVICE_TV1_INDEX) {
DRM_DEBUG("Skipping TV Out\n");
mode_info->bios_connector[i].valid = false;
continue;
}
mode_info->bios_connector[i].valid = true;
mode_info->bios_connector[i].output_id = ci.sucI2cId.sbfAccess.bfI2C_LineMux;
mode_info->bios_connector[i].devices = 1 << i;
mode_info->bios_connector[i].connector_type = ci.sucConnectorInfo.sbfAccess.bfConnectorType;
if (mode_info->bios_connector[i].connector_type == CONNECTOR_NONE) {
mode_info->bios_connector[i].valid = false;
continue;
}
mode_info->bios_connector[i].dac_type = ci.sucConnectorInfo.sbfAccess.bfAssociatedDAC;
if ((i == ATOM_DEVICE_TV1_INDEX) ||
(i == ATOM_DEVICE_TV2_INDEX) ||
(i == ATOM_DEVICE_TV1_INDEX))
mode_info->bios_connector[i].ddc_i2c.valid = false;
else if ((dev_priv->chip_family == CHIP_RS600) ||
(dev_priv->chip_family == CHIP_RS690) ||
(dev_priv->chip_family == CHIP_RS740)) {
if ((i == ATOM_DEVICE_DFP2_INDEX) || (i == ATOM_DEVICE_DFP3_INDEX))
mode_info->bios_connector[i].ddc_i2c =
radeon_lookup_gpio_for_ddc(dev, ci.sucI2cId.sbfAccess.bfI2C_LineMux + 1);
else
mode_info->bios_connector[i].ddc_i2c =
radeon_lookup_gpio_for_ddc(dev, ci.sucI2cId.sbfAccess.bfI2C_LineMux);
} else
mode_info->bios_connector[i].ddc_i2c =
radeon_lookup_gpio_for_ddc(dev, ci.sucI2cId.sbfAccess.bfI2C_LineMux);
if (i == ATOM_DEVICE_DFP1_INDEX)
mode_info->bios_connector[i].tmds_type = TMDS_INT;
else if (i == ATOM_DEVICE_DFP2_INDEX) {
if ((dev_priv->chip_family == CHIP_RS600) ||
(dev_priv->chip_family == CHIP_RS690) ||
(dev_priv->chip_family == CHIP_RS740))
mode_info->bios_connector[i].tmds_type = TMDS_DDIA;
else
mode_info->bios_connector[i].tmds_type = TMDS_EXT;
} else if (i == ATOM_DEVICE_DFP3_INDEX)
mode_info->bios_connector[i].tmds_type = TMDS_LVTMA;
else
mode_info->bios_connector[i].tmds_type = TMDS_NONE;
/* Always set the connector type to VGA for CRT1/CRT2. if they are
* shared with a DVI port, we'll pick up the DVI connector below when we
* merge the outputs
*/
if ((i == ATOM_DEVICE_CRT1_INDEX || i == ATOM_DEVICE_CRT2_INDEX) &&
(mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_I ||
mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_D ||
mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_A)) {
mode_info->bios_connector[i].connector_type = CONNECTOR_VGA;
}
if (crev > 1) {
ATOM_CONNECTOR_INC_SRC_BITMAP isb = supported_devices->info_2.asIntSrcInfo[i];
switch(isb.ucIntSrcBitmap) {
case 0x4:
mode_info->bios_connector[i].hpd_mask = 0x1;
break;
case 0xa:
mode_info->bios_connector[i].hpd_mask = 0x100;
break;
default:
mode_info->bios_connector[i].hpd_mask = 0;
break;
}
} else {
mode_info->bios_connector[i].hpd_mask = 0;
}
radeon_atom_apply_quirks(dev, i);
}
/* CRTs/DFPs may share a port */
for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
if (!mode_info->bios_connector[i].valid)
continue;
for (j = 0; j < ATOM_MAX_SUPPORTED_DEVICE; j++) {
if (mode_info->bios_connector[j].valid && (i != j)) {
if (mode_info->bios_connector[i].output_id ==
mode_info->bios_connector[j].output_id) {
if (((i == ATOM_DEVICE_DFP1_INDEX) ||
(i == ATOM_DEVICE_DFP2_INDEX) ||
(i == ATOM_DEVICE_DFP3_INDEX)) &&
((j == ATOM_DEVICE_CRT1_INDEX) ||
(j == ATOM_DEVICE_CRT2_INDEX))) {
mode_info->bios_connector[i].dac_type = mode_info->bios_connector[j].dac_type;
mode_info->bios_connector[i].devices |= mode_info->bios_connector[j].devices;
mode_info->bios_connector[i].hpd_mask = mode_info->bios_connector[j].hpd_mask;
mode_info->bios_connector[j].valid = false;
} else if (((j == ATOM_DEVICE_DFP1_INDEX) ||
(j == ATOM_DEVICE_DFP2_INDEX) ||
(j == ATOM_DEVICE_DFP3_INDEX)) &&
((i == ATOM_DEVICE_CRT1_INDEX) ||
(i == ATOM_DEVICE_CRT2_INDEX))) {
mode_info->bios_connector[j].dac_type = mode_info->bios_connector[i].dac_type;
mode_info->bios_connector[j].devices |= mode_info->bios_connector[i].devices;
mode_info->bios_connector[j].hpd_mask = mode_info->bios_connector[i].hpd_mask;
mode_info->bios_connector[i].valid = false;
}
}
}
}
}
DRM_DEBUG("BIOS Connector table\n");
for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
if (!mode_info->bios_connector[i].valid)
continue;
DRM_DEBUG("Port %d: ddc_type 0x%x, dac_type %d, tmds_type %d, connector type %d, hpd_mask %d\n",
i, mode_info->bios_connector[i].ddc_i2c.mask_clk_reg,
mode_info->bios_connector[i].dac_type,
mode_info->bios_connector[i].tmds_type,
mode_info->bios_connector[i].connector_type,
mode_info->bios_connector[i].hpd_mask);
}
return true;
}
union firmware_info {
ATOM_FIRMWARE_INFO info;
ATOM_FIRMWARE_INFO_V1_2 info_12;
ATOM_FIRMWARE_INFO_V1_3 info_13;
ATOM_FIRMWARE_INFO_V1_4 info_14;
};
bool radeon_atom_get_clock_info(struct drm_device *dev)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_mode_info *mode_info = &dev_priv->mode_info;
int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
union firmware_info *firmware_info;
uint8_t frev, crev;
struct radeon_pll *pll = &mode_info->pll;
uint16_t data_offset;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
firmware_info = (union firmware_info *)(mode_info->atom_context->bios + data_offset);
pll->reference_freq = le16_to_cpu(firmware_info->info.usReferenceClock);
pll->reference_div = 0;
pll->pll_out_min = le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Output);
pll->pll_out_max = le32_to_cpu(firmware_info->info.ulMaxPixelClockPLL_Output);
if (pll->pll_out_min == 0) {
if (radeon_is_avivo(dev_priv))
pll->pll_out_min = 64800;
else
pll->pll_out_min = 20000;
}
pll->pll_in_min = le16_to_cpu(firmware_info->info.usMinPixelClockPLL_Input);
pll->pll_in_max = le16_to_cpu(firmware_info->info.usMaxPixelClockPLL_Input);
pll->xclk = le16_to_cpu(firmware_info->info.usMaxPixelClock);
return true;
}
union lvds_info {
struct _ATOM_LVDS_INFO info;
struct _ATOM_LVDS_INFO_V12 info_12;
};
void radeon_get_lvds_info(struct radeon_encoder *encoder)
{
struct drm_device *dev = encoder->base.dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_mode_info *mode_info = &dev_priv->mode_info;
int index = GetIndexIntoMasterTable(DATA, LVDS_Info);
uint16_t data_offset;
union lvds_info *lvds_info;
uint8_t frev, crev;
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset);
lvds_info = (union lvds_info *)(mode_info->atom_context->bios + data_offset);
encoder->dotclock = le16_to_cpu(lvds_info->info.sLCDTiming.usPixClk) * 10;
encoder->panel_xres = le16_to_cpu(lvds_info->info.sLCDTiming.usHActive);
encoder->panel_yres = le16_to_cpu(lvds_info->info.sLCDTiming.usVActive);
encoder->hblank = le16_to_cpu(lvds_info->info.sLCDTiming.usHBlanking_Time);
encoder->hoverplus = le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncOffset);
encoder->hsync_width = le16_to_cpu(lvds_info->info.sLCDTiming.usHSyncWidth);
encoder->vblank = le16_to_cpu(lvds_info->info.sLCDTiming.usVBlanking_Time);
encoder->hoverplus = le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncOffset);
encoder->hsync_width = le16_to_cpu(lvds_info->info.sLCDTiming.usVSyncWidth);
encoder->panel_pwr_delay = le16_to_cpu(lvds_info->info.usOffDelayInMs);
}
void radeon_atom_dyn_clk_setup(struct drm_device *dev, int enable)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_mode_info *mode_info = &dev_priv->mode_info;
struct atom_context *ctx = mode_info->atom_context;
DYNAMIC_CLOCK_GATING_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, DynamicClockGating);
args.ucEnable = enable;
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
}
void radeon_atom_static_pwrmgt_setup(struct drm_device *dev, int enable)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_mode_info *mode_info = &dev_priv->mode_info;
struct atom_context *ctx = mode_info->atom_context;
ENABLE_ASIC_STATIC_PWR_MGT_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, EnableASIC_StaticPwrMgt);
args.ucEnable = enable;
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
}

266
linux-core/radeon_buffer.c Normal file
View File

@ -0,0 +1,266 @@
/**************************************************************************
*
* Copyright 2007 Dave Airlie
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
*
**************************************************************************/
/*
* Authors: Dave Airlie <airlied@linux.ie>
*/
#include "drmP.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
struct drm_ttm_backend *radeon_create_ttm_backend_entry(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
if(dev_priv->flags & RADEON_IS_AGP)
return drm_agp_init_ttm(dev);
else
return ati_pcigart_init_ttm(dev, &dev_priv->gart_info, radeon_gart_flush);
}
int radeon_fence_types(struct drm_buffer_object *bo, uint32_t * class, uint32_t * type)
{
*class = 0;
*type = 1;
return 0;
}
int radeon_invalidate_caches(struct drm_device * dev, uint64_t flags)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
BEGIN_RING(4);
RADEON_FLUSH_CACHE();
RADEON_FLUSH_ZCACHE();
ADVANCE_RING();
return 0;
}
int radeon_init_mem_type(struct drm_device * dev, uint32_t type,
struct drm_mem_type_manager * man)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
switch (type) {
case DRM_BO_MEM_LOCAL:
man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
_DRM_FLAG_MEMTYPE_CACHED;
man->drm_bus_maptype = 0;
break;
case DRM_BO_MEM_VRAM:
man->flags = _DRM_FLAG_MEMTYPE_FIXED | _DRM_FLAG_MEMTYPE_MAPPABLE | _DRM_FLAG_NEEDS_IOREMAP;
man->io_addr = NULL;
man->drm_bus_maptype = _DRM_FRAME_BUFFER;
man->io_offset = drm_get_resource_start(dev, 0);
man->io_size = drm_get_resource_len(dev, 0);
break;
case DRM_BO_MEM_TT:
if (dev_priv->flags & RADEON_IS_AGP) {
if (!(drm_core_has_AGP(dev) && dev->agp)) {
DRM_ERROR("AGP is not enabled for memory type %u\n",
(unsigned)type);
return -EINVAL;
}
man->io_offset = dev->agp->agp_info.aper_base;
man->io_size = dev->agp->agp_info.aper_size * 1024 * 1024;
man->io_addr = NULL;
man->flags = _DRM_FLAG_MEMTYPE_MAPPABLE |
_DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_NEEDS_IOREMAP;
man->drm_bus_maptype = _DRM_AGP;
} else {
man->io_offset = dev_priv->gart_vm_start;
man->io_size = dev_priv->gart_size;
man->io_addr = NULL;
man->flags = _DRM_FLAG_MEMTYPE_CSELECT | _DRM_FLAG_MEMTYPE_MAPPABLE | _DRM_FLAG_MEMTYPE_CMA;
man->drm_bus_maptype = _DRM_SCATTER_GATHER;
}
break;
default:
DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
return -EINVAL;
}
return 0;
}
static void radeon_emit_copy_blit(struct drm_device * dev,
uint32_t src_offset,
uint32_t dst_offset,
uint32_t pages, int direction)
{
uint32_t cur_pages;
uint32_t stride = PAGE_SIZE;
drm_radeon_private_t *dev_priv = dev->dev_private;
uint32_t format, height;
RING_LOCALS;
if (!dev_priv)
return;
/* 32-bit copy format */
format = RADEON_COLOR_FORMAT_ARGB8888;
/* radeon limited to 16k stride */
stride &= 0x3fff;
while(pages > 0) {
cur_pages = pages;
if (cur_pages > 2048)
cur_pages = 2048;
pages -= cur_pages;
/* needs verification */
BEGIN_RING(7);
OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5));
OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
RADEON_GMC_DST_PITCH_OFFSET_CNTL |
RADEON_GMC_BRUSH_NONE |
(format << 8) |
RADEON_GMC_SRC_DATATYPE_COLOR |
RADEON_ROP3_S |
RADEON_DP_SRC_SOURCE_MEMORY |
RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS);
if (direction) {
OUT_RING((stride << 22) | (src_offset >> 10));
OUT_RING((stride << 22) | (dst_offset >> 10));
} else {
OUT_RING((stride << 22) | (dst_offset >> 10));
OUT_RING((stride << 22) | (src_offset >> 10));
}
OUT_RING(0);
OUT_RING(pages); /* x - y */
OUT_RING((stride << 16) | cur_pages);
ADVANCE_RING();
}
BEGIN_RING(2);
RADEON_WAIT_UNTIL_2D_IDLE();
ADVANCE_RING();
return;
}
static int radeon_move_blit(struct drm_buffer_object * bo,
int evict, int no_wait, struct drm_bo_mem_reg *new_mem)
{
struct drm_bo_mem_reg *old_mem = &bo->mem;
int dir = 0;
if ((old_mem->mem_type == new_mem->mem_type) &&
(new_mem->mm_node->start <
old_mem->mm_node->start + old_mem->mm_node->size)) {
dir = 1;
}
radeon_emit_copy_blit(bo->dev,
old_mem->mm_node->start << PAGE_SHIFT,
new_mem->mm_node->start << PAGE_SHIFT,
new_mem->num_pages, dir);
return drm_bo_move_accel_cleanup(bo, evict, no_wait, 0,
DRM_FENCE_TYPE_EXE, 0,
new_mem);
}
static int radeon_move_flip(struct drm_buffer_object * bo,
int evict, int no_wait, struct drm_bo_mem_reg * new_mem)
{
struct drm_device *dev = bo->dev;
struct drm_bo_mem_reg tmp_mem;
int ret;
tmp_mem = *new_mem;
tmp_mem.mm_node = NULL;
// tmp_mem.mask = DRM_BO_FLAG_MEM_TT |
// DRM_BO_FLAG_CACHED | DRM_BO_FLAG_FORCE_CACHING;
ret = drm_bo_mem_space(bo, &tmp_mem, no_wait);
if (ret)
return ret;
ret = drm_ttm_bind(bo->ttm, &tmp_mem);
if (ret)
goto out_cleanup;
ret = radeon_move_blit(bo, 1, no_wait, &tmp_mem);
if (ret)
goto out_cleanup;
ret = drm_bo_move_ttm(bo, evict, no_wait, new_mem);
out_cleanup:
if (tmp_mem.mm_node) {
mutex_lock(&dev->struct_mutex);
if (tmp_mem.mm_node != bo->pinned_node)
drm_memrange_put_block(tmp_mem.mm_node);
tmp_mem.mm_node = NULL;
mutex_unlock(&dev->struct_mutex);
}
return ret;
}
int radeon_move(struct drm_buffer_object * bo,
int evict, int no_wait, struct drm_bo_mem_reg * new_mem)
{
struct drm_bo_mem_reg *old_mem = &bo->mem;
return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
#if 0
DRM_DEBUG("\n");
if (old_mem->mem_type == DRM_BO_MEM_LOCAL) {
return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
} else if (new_mem->mem_type == DRM_BO_MEM_LOCAL) {
if (radeon_move_flip(bo, evict, no_wait, new_mem))
return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
} else {
if (radeon_move_blit(bo, evict, no_wait, new_mem))
return drm_bo_move_memcpy(bo, evict, no_wait, new_mem);
}
return 0;
#endif
}
/*
* i915_evict_flags:
*
* @bo: the buffer object to be evicted
*
* Return the bo flags for a buffer which is not mapped to the hardware.
* These will be placed in proposed_flags so that when the move is
* finished, they'll end up in bo->mem.flags
*/
uint64_t radeon_evict_flags(struct drm_buffer_object *bo)
{
switch (bo->mem.mem_type) {
case DRM_BO_MEM_LOCAL:
case DRM_BO_MEM_TT:
return DRM_BO_FLAG_MEM_LOCAL;
default:
return DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_CACHED;
}
}

381
linux-core/radeon_combios.c Normal file
View File

@ -0,0 +1,381 @@
/*
* Copyright 2004 ATI Technologies Inc., Markham, Ontario
* Copyright 2007-8 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Dave Airlie
* Alex Deucher
*/
#include "drmP.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
/* old legacy ATI BIOS routines */
enum radeon_combios_ddc
{
DDC_NONE_DETECTED,
DDC_MONID,
DDC_DVI,
DDC_VGA,
DDC_CRT2,
DDC_LCD,
DDC_GPIO,
};
enum radeon_combios_connector
{
CONNECTOR_NONE_LEGACY,
CONNECTOR_PROPRIETARY_LEGACY,
CONNECTOR_CRT_LEGACY,
CONNECTOR_DVI_I_LEGACY,
CONNECTOR_DVI_D_LEGACY,
CONNECTOR_CTV_LEGACY,
CONNECTOR_STV_LEGACY,
CONNECTOR_UNSUPPORTED_LEGACY
};
struct radeon_i2c_bus_rec combios_setup_i2c_bus(int ddc_line)
{
struct radeon_i2c_bus_rec i2c;
i2c.mask_clk_mask = RADEON_GPIO_EN_1 | RADEON_GPIO_Y_1;
i2c.mask_data_mask = RADEON_GPIO_EN_0 | RADEON_GPIO_Y_0;
i2c.put_clk_mask = RADEON_GPIO_EN_1;
i2c.put_data_mask = RADEON_GPIO_EN_0;
i2c.get_clk_mask = RADEON_GPIO_Y_1;
i2c.get_data_mask = RADEON_GPIO_Y_0;
if ((ddc_line == RADEON_LCD_GPIO_MASK) ||
(ddc_line == RADEON_MDGPIO_EN_REG)) {
i2c.mask_clk_reg = ddc_line;
i2c.mask_data_reg = ddc_line;
i2c.put_clk_reg = ddc_line;
i2c.put_data_reg = ddc_line;
i2c.get_clk_reg = ddc_line + 4;
i2c.get_data_reg = ddc_line + 4;
} else {
i2c.mask_clk_reg = ddc_line;
i2c.mask_data_reg = ddc_line;
i2c.put_clk_reg = ddc_line;
i2c.put_data_reg = ddc_line;
i2c.get_clk_reg = ddc_line;
i2c.get_data_reg = ddc_line;
}
if (ddc_line)
i2c.valid = true;
else
i2c.valid = false;
return i2c;
}
bool radeon_combios_get_clock_info(struct drm_device *dev)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_mode_info *mode_info = &dev_priv->mode_info;
uint16_t pll_info_block;
struct radeon_pll *pll = &mode_info->pll;
int rev;
pll_info_block = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x30);
rev = radeon_bios8(dev_priv, pll_info_block);
pll->reference_freq = radeon_bios16(dev_priv, pll_info_block + 0xe);
pll->reference_div = radeon_bios16(dev_priv, pll_info_block + 0x10);
pll->pll_out_min = radeon_bios32(dev_priv, pll_info_block + 0x12);
pll->pll_out_max = radeon_bios32(dev_priv, pll_info_block + 0x16);
if (rev > 9) {
pll->pll_in_min = radeon_bios32(dev_priv, pll_info_block + 0x36);
pll->pll_in_max = radeon_bios32(dev_priv, pll_info_block + 0x3a);
} else {
pll->pll_in_min = 40;
pll->pll_in_max = 500;
}
pll->xclk = radeon_bios16(dev_priv, pll_info_block + 0x08);
// sclk/mclk use fixed point
return true;
}
bool radeon_combios_get_lvds_info(struct radeon_encoder *encoder)
{
struct drm_device *dev = encoder->base.dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
uint16_t tmp;
char stmp[30];
int tmp0;
int i;
tmp = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x40);
if (!tmp) {
DRM_INFO("No panel info found in BIOS\n");
return false;
}
for (i = 0; i < 24; i++)
stmp[i] = radeon_bios8(dev_priv, tmp + i + 1);
stmp[24] = 0;
DRM_INFO("Panel ID String: %s\n", stmp);
encoder->panel_xres = radeon_bios16(dev_priv, tmp + 25);
encoder->panel_yres = radeon_bios16(dev_priv, tmp + 27);
DRM_INFO("Panel Size %dx%d\n", encoder->panel_xres, encoder->panel_yres);
encoder->panel_pwr_delay = radeon_bios16(dev_priv, tmp + 44);
if (encoder->panel_pwr_delay > 2000 || encoder->panel_pwr_delay < 0)
encoder->panel_pwr_delay = 2000;
for (i = 0; i < 32; i++) {
tmp0 = radeon_bios16(dev_priv, tmp + 64 + i * 2);
if (tmp0 == 0) break;
if ((radeon_bios16(dev_priv, tmp0) == encoder->panel_xres) &&
(radeon_bios16(dev_priv, tmp0 + 2) == encoder->panel_yres)) {
encoder->hblank = (radeon_bios16(dev_priv, tmp0 + 17) -
radeon_bios16(dev_priv, tmp0 + 19)) * 8;
encoder->hoverplus = (radeon_bios16(dev_priv, tmp0 + 21) -
radeon_bios16(dev_priv, tmp0 + 19) - 1) * 8;
encoder->hsync_width = radeon_bios8(dev_priv, tmp0 + 23) * 8;
encoder->vblank = (radeon_bios16(dev_priv, tmp0 + 24) -
radeon_bios16(dev_priv, tmp0 + 26));
encoder->voverplus = ((radeon_bios16(dev_priv, tmp0 + 28) & 0x7fff) -
radeon_bios16(dev_priv, tmp0 + 26));
encoder->vsync_width = ((radeon_bios16(dev_priv, tmp0 + 28) & 0xf800) >> 11);
encoder->dotclock = radeon_bios16(dev_priv, tmp0 + 9) * 10;
encoder->flags = 0;
}
}
return true;
}
static void radeon_apply_legacy_quirks(struct drm_device *dev, int bios_index)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_mode_info *mode_info = &dev_priv->mode_info;
/* on XPRESS chips, CRT2_DDC and MONID_DCC both use the
* MONID gpio, but use different pins.
* CRT2_DDC uses the standard pinout, MONID_DDC uses
* something else.
*/
if ((dev_priv->chip_family == CHIP_RS400 ||
dev_priv->chip_family == CHIP_RS480) &&
mode_info->bios_connector[bios_index].connector_type == CONNECTOR_VGA &&
mode_info->bios_connector[bios_index].ddc_i2c.mask_clk_reg == RADEON_GPIO_CRT2_DDC) {
mode_info->bios_connector[bios_index].ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID);
}
/* XPRESS desktop chips seem to have a proprietary connector listed for
* DVI-D, try and do the right thing here.
*/
if ((dev_priv->flags & RADEON_IS_MOBILITY) &&
(mode_info->bios_connector[bios_index].connector_type == CONNECTOR_LVDS)) {
DRM_INFO("proprietary connector found. assuming DVI-D\n");
mode_info->bios_connector[bios_index].dac_type = DAC_NONE;
mode_info->bios_connector[bios_index].tmds_type = TMDS_EXT;
mode_info->bios_connector[bios_index].connector_type = CONNECTOR_DVI_D;
}
/* Certain IBM chipset RN50s have a BIOS reporting two VGAs,
one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */
if (dev->pdev->device == 0x515e &&
dev->pdev->subsystem_vendor == 0x1014) {
if (mode_info->bios_connector[bios_index].connector_type == CONNECTOR_VGA &&
mode_info->bios_connector[bios_index].ddc_i2c.mask_clk_reg == RADEON_GPIO_CRT2_DDC) {
mode_info->bios_connector[bios_index].valid = false;
}
}
/* Some RV100 cards with 2 VGA ports show up with DVI+VGA */
if (dev->pdev->device == 0x5159 &&
dev->pdev->subsystem_vendor == 0x1002 &&
dev->pdev->subsystem_device == 0x013a) {
if (mode_info->bios_connector[bios_index].connector_type == CONNECTOR_DVI_I)
mode_info->bios_connector[bios_index].connector_type = CONNECTOR_VGA;
}
}
bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_mode_info *mode_info = &dev_priv->mode_info;
uint32_t offset, entry;
uint16_t tmp0, tmp1, tmp;
enum radeon_combios_ddc ddctype;
enum radeon_combios_connector connector_type;
int i;
DRM_DEBUG("\n");
offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x50);
if (offset) {
for (i = 0; i < 4; i++) {
entry = offset + 2 + i * 2;
if (!radeon_bios16(dev_priv, entry))
break;
mode_info->bios_connector[i].valid = true;
tmp = radeon_bios16(dev_priv, entry);
connector_type = (tmp >> 12) & 0xf;
mode_info->bios_connector[i].connector_type = connector_type;
switch(connector_type) {
case CONNECTOR_PROPRIETARY_LEGACY:
mode_info->bios_connector[i].connector_type = CONNECTOR_LVDS;
break;
case CONNECTOR_CRT_LEGACY:
mode_info->bios_connector[i].connector_type = CONNECTOR_VGA;
break;
case CONNECTOR_DVI_I_LEGACY:
mode_info->bios_connector[i].connector_type = CONNECTOR_DVI_I;
break;
case CONNECTOR_DVI_D_LEGACY:
mode_info->bios_connector[i].connector_type = CONNECTOR_DVI_D;
break;
case CONNECTOR_CTV_LEGACY:
mode_info->bios_connector[i].connector_type = CONNECTOR_CTV;
break;
case CONNECTOR_STV_LEGACY:
mode_info->bios_connector[i].connector_type = CONNECTOR_STV;
break;
default:
DRM_ERROR("Unknown connector type: %d\n", connector_type);
mode_info->bios_connector[i].valid = false;
break;
}
mode_info->bios_connector[i].ddc_i2c.valid = false;
ddctype = (tmp >> 8) & 0xf;
switch (ddctype) {
case DDC_MONID:
mode_info->bios_connector[i].ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_MONID);
break;
case DDC_DVI:
mode_info->bios_connector[i].ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
break;
case DDC_VGA:
mode_info->bios_connector[i].ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
break;
case DDC_CRT2:
mode_info->bios_connector[i].ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
break;
default:
break;
}
if (tmp & 0x1)
mode_info->bios_connector[i].dac_type = DAC_TVDAC;
else
mode_info->bios_connector[i].dac_type = DAC_PRIMARY;
if ((dev_priv->chip_family == CHIP_RS300) ||
(dev_priv->chip_family == CHIP_RS400) ||
(dev_priv->chip_family == CHIP_RS480))
mode_info->bios_connector[i].dac_type = DAC_TVDAC;
if ((tmp >> 4) & 0x1)
mode_info->bios_connector[i].tmds_type = TMDS_EXT;
else
mode_info->bios_connector[i].tmds_type = TMDS_INT;
radeon_apply_legacy_quirks(dev, i);
}
} else {
DRM_INFO("no connector table found in BIOS\n");
offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x34);
if (offset) {
DRM_DEBUG("Found DFP table, assuming DVI connector\n");
mode_info->bios_connector[0].valid = true;
mode_info->bios_connector[0].connector_type = CONNECTOR_DVI_I;
mode_info->bios_connector[0].dac_type = DAC_PRIMARY;
mode_info->bios_connector[0].tmds_type = TMDS_INT;
mode_info->bios_connector[0].ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
} else {
DRM_DEBUG("No table found\n");
return false;
}
}
if (dev_priv->flags & RADEON_IS_MOBILITY) {
offset = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x40);
if (offset) {
mode_info->bios_connector[4].valid = true;
mode_info->bios_connector[4].connector_type = CONNECTOR_LVDS;
mode_info->bios_connector[4].dac_type = DAC_NONE;
mode_info->bios_connector[4].tmds_type = TMDS_NONE;
mode_info->bios_connector[4].ddc_i2c.valid = false;
tmp = radeon_bios16(dev_priv, dev_priv->bios_header_start + 0x42);
if (tmp) {
tmp0 = radeon_bios16(dev_priv, tmp + 0x15);
if (tmp0) {
tmp1 = radeon_bios8(dev_priv, tmp0 + 2) & 0x07;
if (tmp1) {
ddctype = tmp1;
switch(ddctype) {
case DDC_MONID:
case DDC_DVI:
case DDC_CRT2:
case DDC_LCD:
case DDC_GPIO:
default:
break;
}
DRM_DEBUG("LCD DDC Info Table found!\n");
}
}
} else
mode_info->bios_connector[4].ddc_i2c.valid = false;
}
}
DRM_DEBUG("BIOS Connector table\n");
for (i = 0; i < ATOM_MAX_SUPPORTED_DEVICE; i++) {
if (!mode_info->bios_connector[i].valid)
continue;
DRM_DEBUG("Port %d: ddc_type 0x%x, dac_type %d, tmds_type %d, connector type %d, hpd_mask %d\n",
i, mode_info->bios_connector[i].ddc_i2c.mask_clk_reg,
mode_info->bios_connector[i].dac_type,
mode_info->bios_connector[i].tmds_type,
mode_info->bios_connector[i].connector_type,
mode_info->bios_connector[i].hpd_mask);
}
return true;
}

View File

@ -0,0 +1,344 @@
/*
* Copyright 2007-8 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Dave Airlie
* Alex Deucher
*/
#include "drmP.h"
#include "drm_edid.h"
#include "drm_crtc_helper.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
static int radeon_lvds_get_modes(struct drm_connector *connector)
{
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct drm_encoder *lvds_encoder;
int ret = 0;
struct edid *edid;
avivo_i2c_do_lock(radeon_connector, 1);
edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
avivo_i2c_do_lock(radeon_connector, 0);
if (edid) {
drm_mode_connector_update_edid_property(&radeon_connector->base, edid);
ret = drm_add_edid_modes(&radeon_connector->base, edid);
kfree(edid);
return 0;
}
#if 0
lvds_encoder = radeon_best_single_encoder(connector);
if (!lvds_encoder)
return ret;
radeon_encoder_update_panel_size(lvds_encoder, connector);
#endif
return ret;
}
static int radeon_lvds_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
return MODE_OK;
}
static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector)
{
return connector_status_connected;
}
struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
{
int enc_id = connector->encoder_ids[0];
struct drm_mode_object *obj;
struct drm_encoder *encoder;
/* pick the encoder ids */
if (enc_id) {
obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
if (!obj)
return NULL;
encoder = obj_to_encoder(obj);
return encoder;
}
return NULL;
}
static void radeon_connector_destroy(struct drm_connector *connector)
{
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
if (radeon_connector->ddc_bus)
radeon_i2c_destroy(radeon_connector->ddc_bus);
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
kfree(connector);
}
struct drm_connector_helper_funcs radeon_lvds_connector_helper_funcs = {
.get_modes = radeon_lvds_get_modes,
.mode_valid = radeon_lvds_mode_valid,
.best_encoder = radeon_best_single_encoder,
};
struct drm_connector_funcs radeon_lvds_connector_funcs = {
.detect = radeon_lvds_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = radeon_connector_destroy,
};
static int radeon_atom_vga_get_modes(struct drm_connector *connector)
{
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
int ret;
ret = radeon_ddc_get_modes(radeon_connector);
return ret;
}
static int radeon_atom_vga_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
return MODE_OK;
}
static enum drm_connector_status radeon_atom_vga_detect(struct drm_connector *connector)
{
struct edid *edid;
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct drm_encoder *encoder;
struct drm_encoder_helper_funcs *encoder_funcs;
avivo_i2c_do_lock(radeon_connector, 1);
edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
avivo_i2c_do_lock(radeon_connector, 0);
if (edid) {
kfree(edid);
return connector_status_connected;
}
/* if EDID fails to a load detect */
encoder = radeon_best_single_encoder(connector);
if (!encoder)
return connector_status_disconnected;
encoder_funcs = encoder->helper_private;
return encoder_funcs->detect(encoder, connector);
}
struct drm_connector_helper_funcs radeon_atom_vga_connector_helper_funcs = {
.get_modes = radeon_atom_vga_get_modes,
.mode_valid = radeon_atom_vga_mode_valid,
.best_encoder = radeon_best_single_encoder,
};
struct drm_connector_funcs radeon_atom_vga_connector_funcs = {
.detect = radeon_atom_vga_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = radeon_connector_destroy,
};
static enum drm_connector_status radeon_atom_dvi_detect(struct drm_connector *connector)
{
struct edid *edid;
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct drm_encoder *encoder;
struct drm_encoder_helper_funcs *encoder_funcs;
struct drm_mode_object *obj;
int i;
enum drm_connector_status ret;
avivo_i2c_do_lock(radeon_connector, 1);
edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
avivo_i2c_do_lock(radeon_connector, 0);
if (edid) {
/* if the monitor is digital - set the bits */
if (edid->digital)
radeon_connector->use_digital = 1;
else
radeon_connector->use_digital = 0;
kfree(edid);
return connector_status_connected;
}
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
if (connector->encoder_ids[i] == 0)
break;
obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
if (!obj)
continue;
encoder = obj_to_encoder(obj);
encoder_funcs = encoder->helper_private;
if (encoder_funcs->detect) {
ret = encoder_funcs->detect(encoder, connector);
if (ret == connector_status_connected) {
radeon_connector->use_digital = 0;
return ret;
}
}
}
return connector_status_disconnected;
}
/* okay need to be smart in here about which encoder to pick */
struct drm_encoder *radeon_atom_dvi_encoder(struct drm_connector *connector)
{
int enc_id = connector->encoder_ids[0];
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct drm_mode_object *obj;
struct drm_encoder *encoder;
int i;
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
if (connector->encoder_ids[i] == 0)
break;
obj = drm_mode_object_find(connector->dev, connector->encoder_ids[i], DRM_MODE_OBJECT_ENCODER);
if (!obj)
continue;
encoder = obj_to_encoder(obj);
if (radeon_connector->use_digital) {
if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
return encoder;
} else {
if (encoder->encoder_type == DRM_MODE_ENCODER_DAC ||
encoder->encoder_type == DRM_MODE_ENCODER_TVDAC)
return encoder;
}
}
/* see if we have a default encoder TODO */
/* then check use digitial */
/* pick the first one */
if (enc_id) {
obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
if (!obj)
return NULL;
encoder = obj_to_encoder(obj);
return encoder;
}
return NULL;
}
struct drm_connector_helper_funcs radeon_atom_dvi_connector_helper_funcs = {
.get_modes = radeon_atom_vga_get_modes,
.mode_valid = radeon_atom_vga_mode_valid,
.best_encoder = radeon_atom_dvi_encoder,
};
struct drm_connector_funcs radeon_atom_dvi_connector_funcs = {
.detect = radeon_atom_dvi_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = radeon_connector_destroy,
};
static struct connector_funcs {
int conn_id;
struct drm_connector_funcs *connector_funcs;
struct drm_connector_helper_funcs *helper_funcs;
int conn_type;
char *i2c_id;
} connector_fns[] = {
{ CONNECTOR_NONE, NULL, NULL, DRM_MODE_CONNECTOR_Unknown },
{ CONNECTOR_VGA, &radeon_atom_vga_connector_funcs, &radeon_atom_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA , "VGA"},
{ CONNECTOR_LVDS, &radeon_lvds_connector_funcs, &radeon_lvds_connector_helper_funcs, DRM_MODE_CONNECTOR_LVDS, "LVDS" },
{ CONNECTOR_DVI_A, &radeon_atom_vga_connector_funcs, &radeon_atom_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_DVIA, "DVI" },
{ CONNECTOR_DVI_I, &radeon_atom_dvi_connector_funcs, &radeon_atom_dvi_connector_helper_funcs, DRM_MODE_CONNECTOR_DVII, "DVI" },
#if 0
{ CONNECTOR_DVI_D, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
{ CONNECTOR_STV, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
{ CONNECTOR_CTV, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
{ CONNECTOR_DIGITAL, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
{ CONNECTOR_SCART, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
{ CONNECTOR_HDMI_TYPE_A, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
{ CONNECTOR_HDMI_TYPE_B, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
{ CONNECTOR_HDMI_TYPE_B, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
{ CONNECTOR_HDMI_TYPE_B, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
{ CONNECTOR_DIN, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
{ CONNECTOR_DISPLAY_PORT, radeon_vga_connector_funcs, radeon_vga_connector_helper_funcs, DRM_MODE_CONNECTOR_VGA },
#endif
};
struct drm_connector *radeon_connector_add(struct drm_device *dev, int bios_index)
{
struct radeon_connector *radeon_connector;
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_mode_info *mode_info = &dev_priv->mode_info;
struct drm_connector *connector;
int table_idx;
for (table_idx = 0; table_idx < ARRAY_SIZE(connector_fns); table_idx++) {
if (connector_fns[table_idx].conn_id == mode_info->bios_connector[bios_index].connector_type)
break;
}
if (table_idx == ARRAY_SIZE(connector_fns))
return NULL;
radeon_connector = kzalloc(sizeof(struct radeon_connector), GFP_KERNEL);
if (!radeon_connector) {
return NULL;
}
connector = &radeon_connector->base;
drm_connector_init(dev, &radeon_connector->base, connector_fns[table_idx].connector_funcs,
connector_fns[table_idx].conn_type);
drm_connector_helper_add(&radeon_connector->base, connector_fns[table_idx].helper_funcs);
if (mode_info->bios_connector[bios_index].ddc_i2c.valid) {
radeon_connector->ddc_bus = radeon_i2c_create(dev, &mode_info->bios_connector[bios_index].ddc_i2c,
connector_fns[table_idx].i2c_id);
if (!radeon_connector->ddc_bus)
goto failed;
}
drm_sysfs_connector_add(connector);
return connector;
failed:
if (radeon_connector->ddc_bus)
radeon_i2c_destroy(radeon_connector->ddc_bus);
drm_connector_cleanup(connector);
kfree(connector);
return NULL;
}

725
linux-core/radeon_display.c Normal file
View File

@ -0,0 +1,725 @@
/*
* Copyright 2007-8 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Dave Airlie
* Alex Deucher
*/
#include "drmP.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
#include "atom.h"
#include <asm/div64.h>
#include "drm_crtc_helper.h"
#define CURSOR_WIDTH 64
#define CURSOR_HEIGHT 64
int radeon_ddc_dump(struct drm_connector *connector);
static void avivo_crtc_load_lut(struct drm_crtc *crtc)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
int i;
DRM_DEBUG("%d\n", radeon_crtc->crtc_id);
RADEON_WRITE(AVIVO_DC_LUTA_CONTROL + radeon_crtc->crtc_offset, 0);
RADEON_WRITE(AVIVO_DC_LUTA_BLACK_OFFSET_BLUE + radeon_crtc->crtc_offset, 0);
RADEON_WRITE(AVIVO_DC_LUTA_BLACK_OFFSET_GREEN + radeon_crtc->crtc_offset, 0);
RADEON_WRITE(AVIVO_DC_LUTA_BLACK_OFFSET_RED + radeon_crtc->crtc_offset, 0);
RADEON_WRITE(AVIVO_DC_LUTA_WHITE_OFFSET_BLUE + radeon_crtc->crtc_offset, 0xffff);
RADEON_WRITE(AVIVO_DC_LUTA_WHITE_OFFSET_GREEN + radeon_crtc->crtc_offset, 0xffff);
RADEON_WRITE(AVIVO_DC_LUTA_WHITE_OFFSET_RED + radeon_crtc->crtc_offset, 0xffff);
RADEON_WRITE(AVIVO_DC_LUT_RW_SELECT, radeon_crtc->crtc_id);
RADEON_WRITE(AVIVO_DC_LUT_RW_MODE, 0);
RADEON_WRITE(AVIVO_DC_LUT_WRITE_EN_MASK, 0x0000003f);
for (i = 0; i < 256; i++) {
RADEON_WRITE8(AVIVO_DC_LUT_RW_INDEX, i);
RADEON_WRITE(AVIVO_DC_LUT_30_COLOR,
(radeon_crtc->lut_r[i] << 22) |
(radeon_crtc->lut_g[i] << 12) |
(radeon_crtc->lut_b[i] << 2));
}
RADEON_WRITE(AVIVO_D1GRPH_LUT_SEL + radeon_crtc->crtc_offset, radeon_crtc->crtc_id);
}
void radeon_crtc_load_lut(struct drm_crtc *crtc)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
u32 temp;
int i;
if (!crtc->enabled)
return;
if (radeon_is_avivo(dev_priv)) {
avivo_crtc_load_lut(crtc);
return;
}
temp = RADEON_READ(RADEON_DAC_CNTL2);
if (radeon_crtc->crtc_id == 0)
temp &= (uint32_t)~RADEON_DAC2_PALETTE_ACC_CTL;
else
temp |= RADEON_DAC2_PALETTE_ACC_CTL;
RADEON_WRITE(RADEON_DAC_CNTL2, temp);
for (i = 0; i < 256; i++) {
// OUTPAL(i, radeon_crtc->lut_r[i], radeon_crtc->lut_g[i], radeon_crtc->lut_b[i]);
}
}
/** Sets the color ramps on behalf of RandR */
void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
if (regno==0)
DRM_DEBUG("gamma set %d\n", radeon_crtc->crtc_id);
radeon_crtc->lut_r[regno] = red >> 8;
radeon_crtc->lut_g[regno] = green >> 8;
radeon_crtc->lut_b[regno] = blue >> 8;
}
void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
{
}
static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
}
static void radeon_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
int x, int y)
{
}
void radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y)
{
}
static void radeon_crtc_prepare(struct drm_crtc *crtc)
{
}
static void radeon_crtc_commit(struct drm_crtc *crtc)
{
}
static void avivo_lock_cursor(struct drm_crtc *crtc, bool lock)
{
struct drm_radeon_private *dev_priv = crtc->dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
uint32_t tmp;
tmp = RADEON_READ(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset);
if (lock)
tmp |= AVIVO_D1CURSOR_UPDATE_LOCK;
else
tmp &= ~AVIVO_D1CURSOR_UPDATE_LOCK;
RADEON_WRITE(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, tmp);
}
static int radeon_crtc_cursor_set(struct drm_crtc *crtc,
struct drm_file *file_priv,
uint32_t handle,
uint32_t width,
uint32_t height)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_radeon_private *dev_priv = crtc->dev->dev_private;
struct drm_gem_object *obj;
struct drm_radeon_gem_object *obj_priv;
if (!handle) {
RADEON_WRITE(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, 0);
return 0;
/* turn off cursor */
}
obj = drm_gem_object_lookup(crtc->dev, file_priv, handle);
if (!obj) {
DRM_ERROR("Cannot find cursor object %x for crtc %d\n", handle, radeon_crtc->crtc_id);
return -EINVAL;
}
obj_priv = obj->driver_private;
RADEON_WRITE(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, 0);
if (radeon_is_avivo(dev_priv)) {
RADEON_WRITE(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
dev_priv->fb_location + obj_priv->bo->offset);
RADEON_WRITE(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
(CURSOR_WIDTH - 1) << 16 | (CURSOR_HEIGHT - 1));
RADEON_WRITE(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset,
AVIVO_D1CURSOR_EN | (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
}
mutex_lock(&crtc->dev->struct_mutex);
drm_gem_object_unreference(obj);
mutex_unlock(&crtc->dev->struct_mutex);
return 0;
}
static int radeon_crtc_cursor_move(struct drm_crtc *crtc,
int x, int y)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_radeon_private *dev_priv = crtc->dev->dev_private;
int xorigin = 0, yorigin = 0;
if (x < 0) xorigin = -x+1;
if (y < 0) yorigin = -x+1;
if (xorigin >= CURSOR_WIDTH) xorigin = CURSOR_WIDTH - 1;
if (yorigin >= CURSOR_WIDTH) yorigin = CURSOR_WIDTH - 1;
if (crtc->mode.flags & DRM_MODE_FLAG_INTERLACE)
y /= 2;
else if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
y *= 2;
if (radeon_is_avivo(dev_priv)) {
avivo_lock_cursor(crtc, true);
RADEON_WRITE(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset,
((xorigin ? 0: x) << 16) |
(yorigin ? 0 : y));
RADEON_WRITE(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
avivo_lock_cursor(crtc, false);
}
return 0;
}
static void radeon_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
u16 *blue, uint32_t size)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
int i;
if (size != 256)
return;
for (i = 0; i < 256; i++) {
radeon_crtc->lut_r[i] = red[i] >> 8;
radeon_crtc->lut_g[i] = green[i] >> 8;
radeon_crtc->lut_b[i] = blue[i] >> 8;
}
radeon_crtc_load_lut(crtc);
}
static void radeon_crtc_destroy(struct drm_crtc *crtc)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
drm_crtc_cleanup(crtc);
kfree(radeon_crtc);
}
static const struct drm_crtc_helper_funcs radeon_helper_funcs = {
.dpms = radeon_crtc_dpms,
.mode_fixup = radeon_crtc_mode_fixup,
.mode_set = radeon_crtc_mode_set,
.mode_set_base = radeon_crtc_set_base,
.prepare = radeon_crtc_prepare,
.commit = radeon_crtc_commit,
};
static const struct drm_crtc_funcs radeon_crtc_funcs = {
.cursor_set = radeon_crtc_cursor_set,
.cursor_move = radeon_crtc_cursor_move,
.gamma_set = radeon_crtc_gamma_set,
.set_config = drm_crtc_helper_set_config,
.destroy = radeon_crtc_destroy,
};
static void radeon_crtc_init(struct drm_device *dev, int index)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_crtc *radeon_crtc;
int i;
radeon_crtc = kzalloc(sizeof(struct radeon_crtc) + (RADEONFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
// radeon_crtc = kzalloc(sizeof(struct radeon_crtc), GFP_KERNEL);
if (radeon_crtc == NULL)
return;
drm_crtc_init(dev, &radeon_crtc->base, &radeon_crtc_funcs);
drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256);
radeon_crtc->crtc_id = index;
radeon_crtc->mode_set.crtc = &radeon_crtc->base;
radeon_crtc->mode_set.connectors = (struct drm_connector **)(radeon_crtc + 1);
radeon_crtc->mode_set.num_connectors = 0;
for (i = 0; i < 256; i++) {
radeon_crtc->lut_r[i] = i;
radeon_crtc->lut_g[i] = i;
radeon_crtc->lut_b[i] = i;
}
if (dev_priv->is_atom_bios && dev_priv->chip_family > CHIP_RS690)
radeon_atombios_init_crtc(dev, radeon_crtc);
else
drm_crtc_helper_add(&radeon_crtc->base, &radeon_helper_funcs);
}
bool radeon_legacy_setup_enc_conn(struct drm_device *dev)
{
radeon_get_legacy_connector_info_from_bios(dev);
return false;
}
bool radeon_setup_enc_conn(struct drm_device *dev)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_mode_info *mode_info = &dev_priv->mode_info;
/* do all the mac and stuff */
struct drm_connector *connector;
struct drm_encoder *encoder;
int i;
if (dev_priv->is_atom_bios)
radeon_get_atom_connector_info_from_bios_connector_table(dev);
else
radeon_get_legacy_connector_info_from_bios(dev);
for (i = 0; i < RADEON_MAX_BIOS_CONNECTOR; i++) {
if (!mode_info->bios_connector[i].valid)
continue;
/* add a connector for this */
if (mode_info->bios_connector[i].connector_type == CONNECTOR_NONE)
continue;
connector = radeon_connector_add(dev, i);
if (!connector)
continue;
encoder = NULL;
/* if we find an LVDS connector */
if (mode_info->bios_connector[i].connector_type == CONNECTOR_LVDS) {
if (radeon_is_avivo(dev_priv))
encoder = radeon_encoder_lvtma_add(dev, i);
else
encoder = radeon_encoder_legacy_lvds_add(dev, i);
if (encoder)
drm_mode_connector_attach_encoder(connector, encoder);
}
/* DAC on DVI or VGA */
if ((mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_I) ||
(mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_A) ||
(mode_info->bios_connector[i].connector_type == CONNECTOR_VGA)) {
if (radeon_is_avivo(dev_priv))
encoder = radeon_encoder_atom_dac_add(dev, i, mode_info->bios_connector[i].dac_type, 0);
if (encoder)
drm_mode_connector_attach_encoder(connector, encoder);
}
/* TMDS on DVI */
if ((mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_I) ||
(mode_info->bios_connector[i].connector_type == CONNECTOR_DVI_D)) {
if (radeon_is_avivo(dev_priv))
encoder = radeon_encoder_atom_tmds_add(dev, i, mode_info->bios_connector[i].dac_type);
if (encoder)
drm_mode_connector_attach_encoder(connector, encoder);
}
/* TVDAC on DIN */
if (mode_info->bios_connector[i].connector_type == CONNECTOR_DIN) {
if (radeon_is_avivo(dev_priv))
encoder = radeon_encoder_atom_dac_add(dev, i, mode_info->bios_connector[i].dac_type, 1);
if (encoder)
drm_mode_connector_attach_encoder(connector, encoder);
}
}
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
radeon_ddc_dump(connector);
return true;
}
void avivo_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state)
{
struct drm_radeon_private *dev_priv = radeon_connector->base.dev->dev_private;
uint32_t temp;
struct radeon_i2c_bus_rec *rec = &radeon_connector->ddc_bus->rec;
temp = RADEON_READ(rec->mask_clk_reg);
if (lock_state)
temp |= rec->put_clk_mask;
else
temp &= ~rec->put_clk_mask;
RADEON_WRITE(rec->mask_clk_reg, temp);
temp = RADEON_READ(rec->mask_clk_reg);
temp = RADEON_READ(rec->mask_data_reg);
if (lock_state)
temp |= rec->put_data_mask;
else
temp &= ~rec->put_data_mask;
RADEON_WRITE(rec->mask_data_reg, temp);
temp = RADEON_READ(rec->mask_data_reg);
}
int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
{
struct drm_radeon_private *dev_priv = radeon_connector->base.dev->dev_private;
struct edid *edid;
int ret = 0;
if (!radeon_connector->ddc_bus)
return -1;
if (radeon_is_avivo(dev_priv))
avivo_i2c_do_lock(radeon_connector, 1);
edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
if (radeon_is_avivo(dev_priv))
avivo_i2c_do_lock(radeon_connector, 0);
if (edid) {
drm_mode_connector_update_edid_property(&radeon_connector->base, edid);
ret = drm_add_edid_modes(&radeon_connector->base, edid);
kfree(edid);
return ret;
}
return -1;
}
int radeon_ddc_dump(struct drm_connector *connector)
{
struct edid *edid;
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
int ret = 0;
if (!radeon_connector->ddc_bus)
return -1;
edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
if (edid) {
kfree(edid);
}
return ret;
}
static inline uint32_t radeon_div(uint64_t n, uint32_t d)
{
uint64_t x, y, result;
uint64_t mod;
n += d / 2;
mod = do_div(n, d);
return n;
}
void radeon_compute_pll(struct radeon_pll *pll,
uint64_t freq,
uint32_t *dot_clock_p,
uint32_t *fb_div_p,
uint32_t *ref_div_p,
uint32_t *post_div_p,
int flags)
{
uint32_t min_ref_div = pll->min_ref_div;
uint32_t max_ref_div = pll->max_ref_div;
uint32_t best_vco = pll->best_vco;
uint32_t best_post_div = 1;
uint32_t best_ref_div = 1;
uint32_t best_feedback_div = 1;
uint32_t best_freq = -1;
uint32_t best_error = 0xffffffff;
uint32_t best_vco_diff = 1;
uint32_t post_div;
DRM_DEBUG("PLL freq %llu\n", freq);
freq = freq * 1000;
if (flags & RADEON_PLL_USE_REF_DIV)
min_ref_div = max_ref_div = pll->reference_div;
else {
while (min_ref_div < max_ref_div-1) {
uint32_t mid=(min_ref_div+max_ref_div)/2;
uint32_t pll_in = pll->reference_freq / mid;
if (pll_in < pll->pll_in_min)
max_ref_div = mid;
else if (pll_in > pll->pll_in_max)
min_ref_div = mid;
else
break;
}
}
for (post_div = pll->min_post_div; post_div <= pll->max_post_div; ++post_div) {
uint32_t ref_div;
if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1))
continue;
/* legacy radeons only have a few post_divs */
if (flags & RADEON_PLL_LEGACY) {
if ((post_div == 5) ||
(post_div == 7) ||
(post_div == 9) ||
(post_div == 10) ||
(post_div == 11))
continue;
}
for (ref_div = min_ref_div; ref_div <= max_ref_div; ++ref_div) {
uint32_t feedback_div, current_freq, error, vco_diff;
uint32_t pll_in = pll->reference_freq / ref_div;
uint32_t min_feed_div = pll->min_feedback_div;
uint32_t max_feed_div = pll->max_feedback_div+1;
if (pll_in < pll->pll_in_min || pll_in > pll->pll_in_max)
continue;
while (min_feed_div < max_feed_div) {
uint32_t vco;
feedback_div = (min_feed_div+max_feed_div)/2;
vco = radeon_div((uint64_t)pll->reference_freq * feedback_div,
ref_div);
if (vco < pll->pll_out_min) {
min_feed_div = feedback_div+1;
continue;
} else if(vco > pll->pll_out_max) {
max_feed_div = feedback_div;
continue;
}
current_freq = radeon_div((uint64_t)pll->reference_freq * 10000 * feedback_div,
ref_div * post_div);
error = abs(current_freq - freq);
vco_diff = abs(vco - best_vco);
if ((best_vco == 0 && error < best_error) ||
(best_vco != 0 &&
(error < best_error - 100 ||
(abs(error - best_error) < 100 && vco_diff < best_vco_diff )))) {
best_post_div = post_div;
best_ref_div = ref_div;
best_feedback_div = feedback_div;
best_freq = current_freq;
best_error = error;
best_vco_diff = vco_diff;
} else if (current_freq == freq) {
if (best_freq == -1) {
best_post_div = post_div;
best_ref_div = ref_div;
best_feedback_div = feedback_div;
best_freq = current_freq;
best_error = error;
best_vco_diff = vco_diff;
} else if ((flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) {
best_post_div = post_div;
best_ref_div = ref_div;
best_feedback_div = feedback_div;
best_freq = current_freq;
best_error = error;
best_vco_diff = vco_diff;
}
}
if (current_freq < freq)
min_feed_div = feedback_div+1;
else
max_feed_div = feedback_div;
}
}
}
*dot_clock_p = best_freq / 10000;
*fb_div_p = best_feedback_div;
*ref_div_p = best_ref_div;
*post_div_p = best_post_div;
}
void radeon_get_clock_info(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
struct radeon_pll *pll = &dev_priv->mode_info.pll;
int ret;
if (dev_priv->is_atom_bios)
ret = radeon_atom_get_clock_info(dev);
else
ret = radeon_combios_get_clock_info(dev);
if (ret) {
if (pll->reference_div < 2) pll->reference_div = 12;
} else {
// TODO FALLBACK
}
if (radeon_is_avivo(dev_priv)) {
pll->min_post_div = 2;
pll->max_post_div = 0x7f;
} else {
pll->min_post_div = 1;
pll->max_post_div = 12; // 16 on crtc 0??
}
pll->min_ref_div = 2;
pll->max_ref_div = 0x3ff;
pll->min_feedback_div = 4;
pll->max_feedback_div = 0x7ff;
pll->best_vco = 0;
}
static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb)
{
struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb);
struct drm_device *dev = fb->dev;
if (fb->fbdev)
radeonfb_remove(dev, fb);
drm_framebuffer_cleanup(fb);
kfree(radeon_fb);
}
static const struct drm_framebuffer_funcs radeon_fb_funcs = {
.destroy = radeon_user_framebuffer_destroy,
};
struct drm_framebuffer *radeon_user_framebuffer_create(struct drm_device *dev,
struct drm_file *filp,
struct drm_mode_fb_cmd *mode_cmd)
{
struct radeon_framebuffer *radeon_fb;
radeon_fb = kzalloc(sizeof(*radeon_fb), GFP_KERNEL);
if (!radeon_fb)
return NULL;
drm_framebuffer_init(dev, &radeon_fb->base, &radeon_fb_funcs);
drm_helper_mode_fill_fb_struct(&radeon_fb->base, mode_cmd);
if (filp) {
radeon_fb->obj = drm_gem_object_lookup(dev, filp,
mode_cmd->handle);
if (!radeon_fb->obj) {
kfree(radeon_fb);
return NULL;
}
drm_gem_object_unreference(radeon_fb->obj);
}
return &radeon_fb->base;
}
static const struct drm_mode_config_funcs radeon_mode_funcs = {
.fb_create = radeon_user_framebuffer_create,
.fb_changed = radeonfb_probe,
};
int radeon_modeset_init(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
static struct card_info card;
size_t size;
int num_crtc = 2, i;
int ret;
drm_mode_config_init(dev);
dev->mode_config.funcs = (void *)&radeon_mode_funcs;
if (radeon_is_avivo(dev_priv)) {
dev->mode_config.max_width = 8192;
dev->mode_config.max_height = 8192;
} else {
dev->mode_config.max_width = 4096;
dev->mode_config.max_height = 4096;
}
dev->mode_config.fb_base = dev_priv->fb_aper_offset;
/* allocate crtcs - TODO single crtc */
for (i = 0; i < num_crtc; i++) {
radeon_crtc_init(dev, i);
}
/* okay we should have all the bios connectors */
ret = radeon_setup_enc_conn(dev);
if (!ret)
return ret;
drm_helper_initial_config(dev, false);
return 0;
}
int radeon_load_modeset_init(struct drm_device *dev)
{
int ret;
ret = radeon_modeset_init(dev);
return ret;
}
void radeon_modeset_cleanup(struct drm_device *dev)
{
drm_mode_config_cleanup(dev);
}

View File

@ -37,10 +37,17 @@
#include "drm_pciids.h"
int radeon_no_wb;
int radeon_dynclks = 1;
MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers\n");
module_param_named(no_wb, radeon_no_wb, int, 0444);
unsigned int radeon_modeset = 0;
module_param_named(modeset, radeon_modeset, int, 0400);
MODULE_PARM_DESC(dynclks, "Disable/Enable dynamic clocks");
module_param_named(dynclks, radeon_dynclks, int, 0444);
static int dri_library_name(struct drm_device * dev, char * buf)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
@ -56,11 +63,29 @@ static struct pci_device_id pciidlist[] = {
radeon_PCI_IDS
};
extern struct drm_fence_driver radeon_fence_driver;
static uint32_t radeon_mem_prios[] = {DRM_BO_MEM_VRAM, DRM_BO_MEM_TT, DRM_BO_MEM_LOCAL};
static uint32_t radeon_busy_prios[] = {DRM_BO_MEM_TT, DRM_BO_MEM_VRAM, DRM_BO_MEM_LOCAL};
static struct drm_bo_driver radeon_bo_driver = {
.mem_type_prio = radeon_mem_prios,
.mem_busy_prio = radeon_busy_prios,
.num_mem_type_prio = sizeof(radeon_mem_prios)/sizeof(uint32_t),
.num_mem_busy_prio = sizeof(radeon_busy_prios)/sizeof(uint32_t),
.create_ttm_backend_entry = radeon_create_ttm_backend_entry,
.fence_type = radeon_fence_types,
.invalidate_caches = radeon_invalidate_caches,
.init_mem_type = radeon_init_mem_type,
.move = radeon_move,
.evict_flags = radeon_evict_flags,
};
static int probe(struct pci_dev *pdev, const struct pci_device_id *ent);
static struct drm_driver driver = {
.driver_features =
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED,
DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | DRIVER_GEM,
.dev_priv_size = sizeof(drm_radeon_buf_priv_t),
.load = radeon_driver_load,
.firstopen = radeon_driver_firstopen,
@ -81,7 +106,11 @@ static struct drm_driver driver = {
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
.ioctls = radeon_ioctls,
.gem_init_object = radeon_gem_init_object,
.gem_free_object = radeon_gem_free_object,
.dma_ioctl = radeon_cp_buffers,
.master_create = radeon_master_create,
.master_destroy = radeon_master_destroy,
.fops = {
.owner = THIS_MODULE,
.open = drm_open,
@ -101,6 +130,9 @@ static struct drm_driver driver = {
.remove = __devexit_p(drm_cleanup_pci),
},
.fence_driver = &radeon_fence_driver,
.bo_driver = &radeon_bo_driver,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
.date = DRIVER_DATE,
@ -117,6 +149,10 @@ static int probe(struct pci_dev *pdev, const struct pci_device_id *ent)
static int __init radeon_init(void)
{
driver.num_ioctls = radeon_max_ioctl;
if (radeon_modeset == 1)
driver.driver_features |= DRIVER_MODESET;
return drm_init(&driver, pciidlist);
}

View File

@ -0,0 +1,962 @@
/*
* Copyright 2007-8 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Dave Airlie
* Alex Deucher
*/
#include "drmP.h"
#include "drm_crtc_helper.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
extern int atom_debug;
static void radeon_rmx_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
if (mode->hdisplay < radeon_encoder->panel_xres ||
mode->vdisplay < radeon_encoder->panel_yres) {
radeon_encoder->flags |= RADEON_USE_RMX;
adjusted_mode->hdisplay = radeon_encoder->panel_xres;
adjusted_mode->vdisplay = radeon_encoder->panel_yres;
adjusted_mode->htotal = radeon_encoder->panel_xres + radeon_encoder->hblank;
adjusted_mode->hsync_start = radeon_encoder->panel_xres + radeon_encoder->hoverplus;
adjusted_mode->hsync_end = adjusted_mode->hsync_start + radeon_encoder->hsync_width;
adjusted_mode->vtotal = radeon_encoder->panel_yres + radeon_encoder->vblank;
adjusted_mode->vsync_start = radeon_encoder->panel_yres + radeon_encoder->voverplus;
adjusted_mode->vsync_end = adjusted_mode->vsync_start + radeon_encoder->vsync_width;
/* update crtc values */
drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
/* adjust crtc values */
adjusted_mode->crtc_hdisplay = radeon_encoder->panel_xres;
adjusted_mode->crtc_vdisplay = radeon_encoder->panel_yres;
adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + radeon_encoder->hblank;
adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + radeon_encoder->hoverplus;
adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + radeon_encoder->hsync_width;
adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + radeon_encoder->vblank;
adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + radeon_encoder->voverplus;
adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + radeon_encoder->vsync_width;
} else {
adjusted_mode->htotal = radeon_encoder->panel_xres + radeon_encoder->hblank;
adjusted_mode->hsync_start = radeon_encoder->panel_xres + radeon_encoder->hoverplus;
adjusted_mode->hsync_end = adjusted_mode->hsync_start + radeon_encoder->hsync_width;
adjusted_mode->vtotal = radeon_encoder->panel_yres + radeon_encoder->vblank;
adjusted_mode->vsync_start = radeon_encoder->panel_yres + radeon_encoder->voverplus;
adjusted_mode->vsync_end = adjusted_mode->vsync_start + radeon_encoder->vsync_width;
/* update crtc values */
drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
/* adjust crtc values */
adjusted_mode->crtc_htotal = adjusted_mode->crtc_hdisplay + radeon_encoder->hblank;
adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hdisplay + radeon_encoder->hoverplus;
adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + radeon_encoder->hsync_width;
adjusted_mode->crtc_vtotal = adjusted_mode->crtc_vdisplay + radeon_encoder->vblank;
adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + radeon_encoder->voverplus;
adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + radeon_encoder->vsync_width;
}
adjusted_mode->clock = radeon_encoder->dotclock;
adjusted_mode->flags = radeon_encoder->flags;
}
static int atom_dac_find_atom_type(struct radeon_encoder *radeon_encoder, struct drm_connector *connector)
{
struct drm_device *dev = radeon_encoder->base.dev;
struct drm_connector *connector_find;
int atom_type = -1;
if (!connector) {
list_for_each_entry(connector_find, &dev->mode_config.connector_list, head) {
if (connector_find->encoder == &radeon_encoder->base)
connector = connector_find;
}
}
if (connector) {
/* look for the encoder in the connector list -
check if we the DAC is enabled on a VGA or STV/CTV or CV connector */
/* work out the ATOM_DEVICE bits */
switch (connector->connector_type) {
case CONNECTOR_VGA:
case CONNECTOR_DVI_I:
case CONNECTOR_DVI_A:
if (radeon_encoder->atom_device & ATOM_DEVICE_CRT1_SUPPORT)
atom_type = ATOM_DEVICE_CRT1_INDEX;
else if (radeon_encoder->atom_device & ATOM_DEVICE_CRT2_SUPPORT)
atom_type = ATOM_DEVICE_CRT2_INDEX;
break;
case CONNECTOR_STV:
case CONNECTOR_CTV:
if (radeon_encoder->atom_device & ATOM_DEVICE_TV1_SUPPORT)
atom_type = ATOM_DEVICE_TV1_INDEX;
break;
case CONNECTOR_DIN:
if (radeon_encoder->atom_device & ATOM_DEVICE_TV1_SUPPORT)
atom_type = ATOM_DEVICE_TV1_INDEX;
if (radeon_encoder->atom_device & ATOM_DEVICE_CV_SUPPORT)
atom_type = ATOM_DEVICE_CV_INDEX;
break;
}
}
return atom_type;
}
/* LVTMA encoder for LVDS usage */
static void atombios_display_device_control(struct drm_encoder *encoder, int index, uint8_t state)
{
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
memset(&args, 0, sizeof(args));
args.ucAction = state;
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
}
static void atombios_scaler_setup(struct drm_encoder *encoder, struct drm_display_mode *mode)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
ENABLE_SCALER_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
memset(&args, 0, sizeof(args));
args.ucScaler = radeon_crtc->crtc_id;
if (radeon_encoder->flags & RADEON_USE_RMX) {
if (radeon_encoder->rmx_type == RMX_FULL)
args.ucEnable = ATOM_SCALER_EXPANSION;
else if (radeon_encoder->rmx_type == RMX_CENTER)
args.ucEnable = ATOM_SCALER_CENTER;
} else
args.ucEnable = ATOM_SCALER_DISABLE;
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
}
void atombios_set_crtc_source(struct drm_encoder *encoder, int source)
{
int index = GetIndexIntoMasterTable(COMMAND, SelectCRTC_Source);
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
struct drm_radeon_private *dev_priv = encoder->dev->dev_private;
uint8_t frev, crev;
SELECT_CRTC_SOURCE_PS_ALLOCATION crtc_src_param;
SELECT_CRTC_SOURCE_PARAMETERS_V2 crtc_src_param2;
uint32_t *param = NULL;
atom_parse_cmd_header(dev_priv->mode_info.atom_context, index, &frev, &crev);
switch (frev) {
case 1: {
switch (crev) {
case 0:
case 1:
default:
memset(&crtc_src_param, 0, sizeof(crtc_src_param));
crtc_src_param.ucCRTC = radeon_crtc->crtc_id;
crtc_src_param.ucDevice = source;
param = (uint32_t *)&crtc_src_param;
break;
case 2:
memset(&crtc_src_param2, 0, sizeof(crtc_src_param2));
crtc_src_param2.ucCRTC = radeon_crtc->crtc_id;
crtc_src_param2.ucEncoderID = source;
switch (source) {
case ATOM_DEVICE_CRT1_INDEX:
case ATOM_DEVICE_CRT2_INDEX:
crtc_src_param2.ucEncodeMode = ATOM_ENCODER_MODE_CRT;
break;
case ATOM_DEVICE_DFP1_INDEX:
case ATOM_DEVICE_DFP2_INDEX:
case ATOM_DEVICE_DFP3_INDEX:
crtc_src_param2.ucEncodeMode = ATOM_ENCODER_MODE_DVI;
// TODO ENCODER MODE
break;
case ATOM_DEVICE_LCD1_INDEX:
crtc_src_param2.ucEncodeMode = ATOM_ENCODER_MODE_LVDS;
break;
case ATOM_DEVICE_TV1_INDEX:
crtc_src_param2.ucEncodeMode = ATOM_ENCODER_MODE_TV;
break;
case ATOM_DEVICE_CV_INDEX:
crtc_src_param2.ucEncodeMode = ATOM_ENCODER_MODE_CV;
break;
}
param = (uint32_t *)&crtc_src_param2;
break;
}
}
break;
default:
return;
}
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)param);
}
static void radeon_dfp_disable_dither(struct drm_encoder *encoder, int device)
{
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
switch (device) {
case ATOM_DEVICE_DFP1_INDEX:
RADEON_WRITE(AVIVO_TMDSA_BIT_DEPTH_CONTROL, 0); /* TMDSA */
break;
case ATOM_DEVICE_DFP2_INDEX:
if ((dev_priv->chip_family == CHIP_RS600) ||
(dev_priv->chip_family == CHIP_RS690) ||
(dev_priv->chip_family == CHIP_RS740))
RADEON_WRITE(AVIVO_DDIA_BIT_DEPTH_CONTROL, 0); /* DDIA */
else
RADEON_WRITE(AVIVO_DVOA_BIT_DEPTH_CONTROL, 0); /* DVO */
break;
/*case ATOM_DEVICE_LCD1_INDEX:*/ /* LVDS panels need dither enabled */
case ATOM_DEVICE_DFP3_INDEX:
RADEON_WRITE(AVIVO_LVTMA_BIT_DEPTH_CONTROL, 0); /* LVTMA */
break;
default:
break;
}
}
static void radeon_lvtma_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
LVDS_ENCODER_CONTROL_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, LVDSEncoderControl);
memset(&args, 0, sizeof(args));
atombios_scaler_setup(encoder, mode);
atombios_set_crtc_source(encoder, ATOM_DEVICE_LCD1_INDEX);
args.ucAction = 1;
if (adjusted_mode->clock > 165000)
args.ucMisc = 1;
else
args.ucMisc = 0;
args.usPixelClock = cpu_to_le16(adjusted_mode->clock / 10);
printk("executing set LVDS encoder\n");
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
}
static void radeon_lvtma_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
int index = GetIndexIntoMasterTable(COMMAND, LCD1OutputControl);
switch(mode) {
case DRM_MODE_DPMS_ON:
atombios_display_device_control(encoder, index, ATOM_ENABLE);
break;
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
atombios_display_device_control(encoder, index, ATOM_DISABLE);
break;
}
}
static bool radeon_lvtma_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
radeon_encoder->flags &= ~RADEON_USE_RMX;
if (radeon_encoder->rmx_type != RMX_OFF)
radeon_rmx_mode_fixup(encoder, mode, adjusted_mode);
return true;
}
static void radeon_lvtma_prepare(struct drm_encoder *encoder)
{
radeon_lvtma_dpms(encoder, DRM_MODE_DPMS_OFF);
}
static void radeon_lvtma_commit(struct drm_encoder *encoder)
{
radeon_lvtma_dpms(encoder, DRM_MODE_DPMS_ON);
}
static const struct drm_encoder_helper_funcs radeon_atom_lvtma_helper_funcs = {
.dpms = radeon_lvtma_dpms,
.mode_fixup = radeon_lvtma_mode_fixup,
.prepare = radeon_lvtma_prepare,
.mode_set = radeon_lvtma_mode_set,
.commit = radeon_lvtma_commit,
};
static void radeon_enc_destroy(struct drm_encoder *encoder)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
drm_encoder_cleanup(encoder);
kfree(radeon_encoder);
}
static const struct drm_encoder_funcs radeon_atom_lvtma_enc_funcs = {
.destroy = radeon_enc_destroy,
};
struct drm_encoder *radeon_encoder_lvtma_add(struct drm_device *dev, int bios_index)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_mode_info *mode_info = &dev_priv->mode_info;
struct radeon_encoder *radeon_encoder;
struct drm_encoder *encoder;
radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
if (!radeon_encoder) {
return NULL;
}
encoder = &radeon_encoder->base;
encoder->possible_crtcs = 0x3;
encoder->possible_clones = 0;
drm_encoder_init(dev, encoder, &radeon_atom_lvtma_enc_funcs,
DRM_MODE_ENCODER_LVDS);
drm_encoder_helper_add(encoder, &radeon_atom_lvtma_helper_funcs);
radeon_encoder->atom_device = mode_info->bios_connector[bios_index].devices;
/* TODO get the LVDS info from the BIOS for panel size etc. */
/* get the lvds info from the bios */
radeon_get_lvds_info(radeon_encoder);
/* LVDS gets default RMX full scaling */
radeon_encoder->rmx_type = RMX_FULL;
return encoder;
}
static void radeon_atom_dac_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
int atom_type = -1;
int index;
atom_type = atom_dac_find_atom_type(radeon_encoder, NULL);
if (atom_type == -1)
return;
switch(atom_type) {
case ATOM_DEVICE_CRT1_INDEX:
index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
break;
case ATOM_DEVICE_CRT2_INDEX:
index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
break;
case ATOM_DEVICE_TV1_INDEX:
index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
break;
case ATOM_DEVICE_CV_INDEX:
index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
break;
default:
return;
}
switch(mode) {
case DRM_MODE_DPMS_ON:
atombios_display_device_control(encoder, index, ATOM_ENABLE);
break;
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
atombios_display_device_control(encoder, index, ATOM_DISABLE);
break;
}
}
static bool radeon_atom_dac_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
}
static void radeon_atom_dac_prepare(struct drm_encoder *encoder)
{
radeon_atom_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
}
static void radeon_atom_dac_commit(struct drm_encoder *encoder)
{
radeon_atom_dac_dpms(encoder, DRM_MODE_DPMS_ON);
}
static int atombios_dac_setup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
int atom_type)
{
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
DAC_ENCODER_CONTROL_PS_ALLOCATION args;
int id = (radeon_encoder->type.dac == DAC_TVDAC);
int index;
memset(&args, 0, sizeof(args));
if (id == 0)
index = GetIndexIntoMasterTable(COMMAND, DAC1EncoderControl);
else
index = GetIndexIntoMasterTable(COMMAND, DAC2EncoderControl);
args.ucAction = 1;
args.usPixelClock = cpu_to_le16(mode->clock / 10);
if ((atom_type == ATOM_DEVICE_CRT1_INDEX) ||
(atom_type == ATOM_DEVICE_CRT2_INDEX))
args.ucDacStandard = id ? ATOM_DAC2_PS2 : ATOM_DAC1_PS2;
else if (atom_type == ATOM_DEVICE_CV_INDEX)
args.ucDacStandard = id ? ATOM_DAC2_CV : ATOM_DAC1_CV;
else if (atom_type == ATOM_DEVICE_TV1_INDEX)
args.ucDacStandard = id ? ATOM_DAC2_NTSC : ATOM_DAC1_NTSC;
/* TODO PAL */
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
return 0;
}
static int atombios_tv1_setup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
int atom_type)
{
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
TV_ENCODER_CONTROL_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
memset(&args, 0, sizeof(args));
args.sTVEncoder.ucAction = 1;
if (atom_type == ATOM_DEVICE_CV_INDEX)
args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
else {
// TODO PAL
args.sTVEncoder.ucTvStandard = ATOM_TV_NTSC;
}
args.sTVEncoder.usPixelClock = cpu_to_le16(mode->clock / 10);
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
return 0;
}
static void radeon_atom_dac_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
int atom_type = -1;
atom_type = atom_dac_find_atom_type(radeon_encoder, NULL);
if (atom_type == -1)
return;
atombios_scaler_setup(encoder, mode);
atombios_set_crtc_source(encoder, atom_type);
atombios_dac_setup(encoder, adjusted_mode, atom_type);
if ((atom_type == ATOM_DEVICE_TV1_INDEX) ||
(atom_type == ATOM_DEVICE_CV_INDEX))
atombios_tv1_setup(encoder, adjusted_mode, atom_type);
}
static bool atom_dac_load_detect(struct drm_encoder *encoder, int atom_devices)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
DAC_LOAD_DETECTION_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, DAC_LoadDetection);
memset(&args, 0, sizeof(args));
args.sDacload.ucMisc = 0;
args.sDacload.ucDacType = (radeon_encoder->type.dac == DAC_PRIMARY) ? ATOM_DAC_A : ATOM_DAC_B;
if (atom_devices & ATOM_DEVICE_CRT1_SUPPORT)
args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
else if (atom_devices & ATOM_DEVICE_CRT2_SUPPORT)
args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
else if (atom_devices & ATOM_DEVICE_CV_SUPPORT) {
args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
if (radeon_is_dce3(dev_priv))
args.sDacload.ucMisc = 1;
} else if (atom_devices & ATOM_DEVICE_TV1_SUPPORT) {
args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
if (radeon_is_dce3(dev_priv))
args.sDacload.ucMisc = 1;
} else
return false;
DRM_DEBUG("writing %x %x\n", args.sDacload.usDeviceID, args.sDacload.ucDacType);
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
return true;
}
static enum drm_connector_status radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
{
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
int atom_type = -1;
uint32_t bios_0_scratch;
atom_type = atom_dac_find_atom_type(radeon_encoder, connector);
if (atom_type == -1) {
DRM_DEBUG("exit after find \n");
return connector_status_unknown;
}
if(!atom_dac_load_detect(encoder, (1 << atom_type))) {
DRM_DEBUG("detect returned false \n");
return connector_status_unknown;
}
if (dev_priv->chip_family >= CHIP_R600)
bios_0_scratch = RADEON_READ(R600_BIOS_0_SCRATCH);
else
bios_0_scratch = RADEON_READ(RADEON_BIOS_0_SCRATCH);
DRM_DEBUG("Bios 0 scratch %x\n", bios_0_scratch);
if (radeon_encoder->atom_device & ATOM_DEVICE_CRT1_SUPPORT) {
if (bios_0_scratch & ATOM_S0_CRT1_MASK)
return connector_status_connected;
} else if (radeon_encoder->atom_device & ATOM_DEVICE_CRT2_SUPPORT) {
if (bios_0_scratch & ATOM_S0_CRT2_MASK)
return connector_status_connected;
} else if (radeon_encoder->atom_device & ATOM_DEVICE_CV_SUPPORT) {
if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
return connector_status_connected;
} else if (radeon_encoder->atom_device & ATOM_DEVICE_TV1_SUPPORT) {
if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
return connector_status_connected; // CTV
else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
return connector_status_connected; // STV
}
return connector_status_disconnected;
}
static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
.dpms = radeon_atom_dac_dpms,
.mode_fixup = radeon_atom_dac_mode_fixup,
.prepare = radeon_atom_dac_prepare,
.mode_set = radeon_atom_dac_mode_set,
.commit = radeon_atom_dac_commit,
.detect = radeon_atom_dac_detect,
};
static const struct drm_encoder_funcs radeon_atom_dac_enc_funcs = {
. destroy = radeon_enc_destroy,
};
static void atombios_tmds1_setup(struct drm_encoder *encoder,
struct drm_display_mode *mode)
{
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
TMDS1_ENCODER_CONTROL_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, TMDS1EncoderControl);
memset(&args, 0, sizeof(args));
args.ucAction = 1;
if (mode->clock > 165000)
args.ucMisc = 1;
else
args.ucMisc = 0;
args.usPixelClock = cpu_to_le16(mode->clock / 10);
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
}
static void atombios_tmds2_setup(struct drm_encoder *encoder,
struct drm_display_mode *mode)
{
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
TMDS2_ENCODER_CONTROL_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, TMDS2EncoderControl);
memset(&args, 0, sizeof(args));
args.ucAction = 1;
if (mode->clock > 165000)
args.ucMisc = 1;
else
args.ucMisc = 0;
args.usPixelClock = cpu_to_le16(mode->clock / 10);
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
}
static void atombios_ext_tmds_setup(struct drm_encoder *encoder,
struct drm_display_mode *mode)
{
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
ENABLE_EXTERNAL_TMDS_ENCODER_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
memset(&args, 0, sizeof(args));
args.sXTmdsEncoder.ucEnable = 1;
if (mode->clock > 165000)
args.sXTmdsEncoder.ucMisc = 1;
else
args.sXTmdsEncoder.ucMisc = 0;
// TODO 6-bit DAC
// args.usPixelClock = cpu_to_le16(mode->clock / 10);
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
}
static void atombios_dig1_setup(struct drm_encoder *encoder,
struct drm_display_mode *mode)
{
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
DIG_ENCODER_CONTROL_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, DIG1EncoderControl);
args.ucAction = 1;
args.usPixelClock = mode->clock / 10;
args.ucConfig = ATOM_ENCODER_CONFIG_TRANSMITTER1;
// TODO coherent mode
// if (encoder->coherent_mode)
// args.ucConfig |= ATOM_TRANSMITTER_CONFIG_COHERENT;
if (mode->clock > 165000) {
args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA_B;
args.ucLaneNum = 8;
} else {
args.ucConfig |= ATOM_ENCODER_CONFIG_LINKA;
args.ucLaneNum = 4;
}
// TODO Encoder MODE
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
}
static void atombios_ddia_setup(struct drm_encoder *encoder,
struct drm_display_mode *mode)
{
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
DVO_ENCODER_CONTROL_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl);
args.sDVOEncoder.ucAction = ATOM_ENABLE;
args.sDVOEncoder.usPixelClock = mode->clock / 10;
if (mode->clock > 165000)
args.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = PANEL_ENCODER_MISC_DUAL;
else
args.sDVOEncoder.usDevAttr.sDigAttrib.ucAttribute = 0;
atom_execute_table(dev_priv->mode_info.atom_context, index, (uint32_t *)&args);
}
struct drm_encoder *radeon_encoder_atom_dac_add(struct drm_device *dev, int bios_index, int dac_type, int with_tv)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_mode_info *mode_info = &dev_priv->mode_info;
struct radeon_encoder *radeon_encoder = NULL;
struct drm_encoder *encoder;
int type = with_tv ? DRM_MODE_ENCODER_TVDAC : DRM_MODE_ENCODER_DAC;
int found = 0;
int digital_enc_mask = ~(ATOM_DEVICE_DFP1_SUPPORT | ATOM_DEVICE_DFP2_SUPPORT | ATOM_DEVICE_DFP3_SUPPORT |
ATOM_DEVICE_LCD1_SUPPORT);
/* we may already have added this encoder */
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (encoder->encoder_type != DRM_MODE_ENCODER_DAC ||
encoder->encoder_type != DRM_MODE_ENCODER_TVDAC)
continue;
radeon_encoder = to_radeon_encoder(encoder);
if (radeon_encoder->type.dac == dac_type) {
found = 1;
break;
}
}
if (found) {
/* upgrade to a TV controlling DAC */
if (type == DRM_MODE_ENCODER_TVDAC)
encoder->encoder_type = type;
radeon_encoder->atom_device |= mode_info->bios_connector[bios_index].devices;
radeon_encoder->atom_device &= digital_enc_mask;
return encoder;
}
radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
if (!radeon_encoder) {
return NULL;
}
encoder = &radeon_encoder->base;
encoder->possible_crtcs = 0x3;
encoder->possible_clones = 0;
drm_encoder_init(dev, encoder, &radeon_atom_dac_enc_funcs,
type);
drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
radeon_encoder->type.dac = dac_type;
radeon_encoder->atom_device = mode_info->bios_connector[bios_index].devices;
/* mask off any digital encoders */
radeon_encoder->atom_device &= digital_enc_mask;
return encoder;
}
static void radeon_atom_tmds_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
int atom_type = -1;
int index = -1;
if (radeon_encoder->atom_device & ATOM_DEVICE_DFP1_SUPPORT)
atom_type = ATOM_DEVICE_DFP1_INDEX;
if (radeon_encoder->atom_device & ATOM_DEVICE_DFP2_SUPPORT)
atom_type = ATOM_DEVICE_DFP2_INDEX;
if (radeon_encoder->atom_device & ATOM_DEVICE_DFP3_SUPPORT)
atom_type = ATOM_DEVICE_DFP3_INDEX;
if (atom_type == -1)
return;
switch(atom_type) {
case ATOM_DEVICE_DFP1_INDEX:
index = GetIndexIntoMasterTable(COMMAND, TMDSAOutputControl);
break;
case ATOM_DEVICE_DFP2_INDEX:
index = GetIndexIntoMasterTable(COMMAND, DVOOutputControl);
break;
case ATOM_DEVICE_DFP3_INDEX:
index = GetIndexIntoMasterTable(COMMAND, LVTMAOutputControl);
break;
}
if (index == -1)
return;
switch(mode) {
case DRM_MODE_DPMS_ON:
atombios_display_device_control(encoder, index, ATOM_ENABLE);
break;
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
atombios_display_device_control(encoder, index, ATOM_DISABLE);
break;
}
}
static bool radeon_atom_tmds_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
}
static void radeon_atom_tmds_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
int atom_type;
if (radeon_encoder->atom_device & ATOM_DEVICE_DFP1_SUPPORT)
atom_type = ATOM_DEVICE_DFP1_INDEX;
if (radeon_encoder->atom_device & ATOM_DEVICE_DFP2_SUPPORT)
atom_type = ATOM_DEVICE_DFP2_INDEX;
if (radeon_encoder->atom_device & ATOM_DEVICE_DFP3_SUPPORT)
atom_type = ATOM_DEVICE_DFP3_INDEX;
atombios_scaler_setup(encoder, mode);
atombios_set_crtc_source(encoder, atom_type);
if (atom_type == ATOM_DEVICE_DFP1_INDEX)
atombios_tmds1_setup(encoder, adjusted_mode);
if (atom_type == ATOM_DEVICE_DFP2_INDEX) {
if ((dev_priv->chip_family == CHIP_RS600) ||
(dev_priv->chip_family == CHIP_RS690) ||
(dev_priv->chip_family == CHIP_RS740))
atombios_ddia_setup(encoder, adjusted_mode);
else
atombios_ext_tmds_setup(encoder, adjusted_mode);
}
if (atom_type == ATOM_DEVICE_DFP3_INDEX)
atombios_tmds2_setup(encoder, adjusted_mode);
radeon_dfp_disable_dither(encoder, atom_type);
}
static void radeon_atom_tmds_prepare(struct drm_encoder *encoder)
{
radeon_atom_tmds_dpms(encoder, DRM_MODE_DPMS_OFF);
}
static void radeon_atom_tmds_commit(struct drm_encoder *encoder)
{
radeon_atom_tmds_dpms(encoder, DRM_MODE_DPMS_ON);
}
static const struct drm_encoder_helper_funcs radeon_atom_tmds_helper_funcs = {
.dpms = radeon_atom_tmds_dpms,
.mode_fixup = radeon_atom_tmds_mode_fixup,
.prepare = radeon_atom_tmds_prepare,
.mode_set = radeon_atom_tmds_mode_set,
.commit = radeon_atom_tmds_commit,
/* no detect for TMDS */
};
static const struct drm_encoder_funcs radeon_atom_tmds_enc_funcs = {
. destroy = radeon_enc_destroy,
};
struct drm_encoder *radeon_encoder_atom_tmds_add(struct drm_device *dev, int bios_index, int tmds_type)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_mode_info *mode_info = &dev_priv->mode_info;
struct radeon_encoder *radeon_encoder = NULL;
struct drm_encoder *encoder;
int analog_enc_mask = ~(ATOM_DEVICE_CRT1_SUPPORT | ATOM_DEVICE_CRT2_SUPPORT);
radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
if (!radeon_encoder) {
return NULL;
}
encoder = &radeon_encoder->base;
encoder->possible_crtcs = 0x3;
encoder->possible_clones = 0;
drm_encoder_init(dev, encoder, &radeon_atom_tmds_enc_funcs,
DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(encoder, &radeon_atom_tmds_helper_funcs);
radeon_encoder->atom_device = mode_info->bios_connector[bios_index].devices;
/* mask off any analog encoders */
radeon_encoder->atom_device &= analog_enc_mask;
return encoder;
}
static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
}
static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
{
radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF);
}
static void radeon_legacy_lvds_commit(struct drm_encoder *encoder)
{
radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_ON);
}
static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
}
static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
.dpms = radeon_legacy_lvds_dpms,
.mode_fixup = radeon_lvtma_mode_fixup,
.prepare = radeon_legacy_lvds_prepare,
.mode_set = radeon_legacy_lvds_mode_set,
.commit = radeon_legacy_lvds_commit,
};
static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = {
.destroy = radeon_enc_destroy,
};
struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct radeon_mode_info *mode_info = &dev_priv->mode_info;
struct radeon_encoder *radeon_encoder;
struct drm_encoder *encoder;
radeon_encoder = kzalloc(sizeof(struct radeon_encoder), GFP_KERNEL);
if (!radeon_encoder) {
return NULL;
}
encoder = &radeon_encoder->base;
encoder->possible_crtcs = 0x3;
encoder->possible_clones = 0;
drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs,
DRM_MODE_ENCODER_LVDS);
drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs);
/* TODO get the LVDS info from the BIOS for panel size etc. */
/* get the lvds info from the bios */
radeon_combios_get_lvds_info(radeon_encoder);
/* LVDS gets default RMX full scaling */
radeon_encoder->rmx_type = RMX_FULL;
return encoder;
}

1163
linux-core/radeon_fb.c Normal file

File diff suppressed because it is too large Load Diff

96
linux-core/radeon_fence.c Normal file
View File

@ -0,0 +1,96 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
*
**************************************************************************/
/*
* Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
#include "drmP.h"
#include "drm.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
int radeon_fence_emit_sequence(struct drm_device *dev, uint32_t class,
uint32_t flags, uint32_t *sequence,
uint32_t *native_type)
{
struct drm_radeon_private *dev_priv = (struct drm_radeon_private *) dev->dev_private;
RING_LOCALS;
if (!dev_priv)
return -EINVAL;
radeon_emit_irq(dev);
*sequence = (uint32_t) dev_priv->counter;
*native_type = DRM_FENCE_TYPE_EXE;
return 0;
}
static void radeon_fence_poll(struct drm_device *dev, uint32_t fence_class,
uint32_t waiting_types)
{
struct drm_radeon_private *dev_priv = (struct drm_radeon_private *) dev->dev_private;
uint32_t sequence;
if (waiting_types & DRM_FENCE_TYPE_EXE) {
sequence = READ_BREADCRUMB(dev_priv);
drm_fence_handler(dev, 0, sequence,
DRM_FENCE_TYPE_EXE, 0);
}
}
void radeon_fence_handler(struct drm_device * dev)
{
struct drm_fence_manager *fm = &dev->fm;
struct drm_fence_class_manager *fc = &fm->fence_class[0];
write_lock(&fm->lock);
radeon_fence_poll(dev, 0, fc->waiting_types);
write_unlock(&fm->lock);
}
int radeon_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t flags)
{
/*
* We have an irq that tells us when we have a new breadcrumb.
*/
return 1;
}
struct drm_fence_driver radeon_fence_driver = {
.num_classes = 1,
.wrap_diff = (1U << (BREADCRUMB_BITS -1)),
.flush_diff = (1U << (BREADCRUMB_BITS - 2)),
.sequence_mask = BREADCRUMB_MASK,
.emit = radeon_fence_emit_sequence,
.has_irq = radeon_fence_has_irq,
.poll = radeon_fence_poll,
};

687
linux-core/radeon_gem.c Normal file
View File

@ -0,0 +1,687 @@
/*
* Copyright 2008 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Author: Dave Airlie
*/
#include "drmP.h"
#include "drm.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
int radeon_gem_init_object(struct drm_gem_object *obj)
{
struct drm_radeon_gem_object *obj_priv;
obj_priv = drm_calloc(1, sizeof(*obj_priv), DRM_MEM_DRIVER);
if (!obj_priv) {
return -ENOMEM;
}
obj->driver_private = obj_priv;
obj_priv->obj = obj;
return 0;
}
void radeon_gem_free_object(struct drm_gem_object *obj)
{
struct drm_radeon_gem_object *obj_priv = obj->driver_private;
/* tear down the buffer object - gem holds struct mutex */
drm_bo_takedown_vm_locked(obj_priv->bo);
drm_bo_usage_deref_locked(&obj_priv->bo);
drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
}
int radeon_gem_info_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct drm_radeon_gem_info *args = data;
args->vram_start = dev_priv->mm.vram_offset;
args->vram_size = dev_priv->mm.vram_size;
args->vram_visible = dev_priv->mm.vram_visible;
args->gart_start = dev_priv->mm.gart_start;
args->gart_size = dev_priv->mm.gart_size;
return 0;
}
struct drm_gem_object *radeon_gem_object_alloc(struct drm_device *dev, int size, int alignment,
int initial_domain)
{
struct drm_gem_object *obj;
struct drm_radeon_gem_object *obj_priv;
int ret;
uint32_t flags;
DRM_DEBUG("size 0x%x, alignment %d, initial_domain %d\n", size, alignment, initial_domain);
obj = drm_gem_object_alloc(dev, size);
if (!obj)
return NULL;;
obj_priv = obj->driver_private;
if (initial_domain == RADEON_GEM_DOMAIN_VRAM)
flags = DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MAPPABLE;
else
flags = DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MAPPABLE;
flags |= DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_EXE;
/* create a TTM BO */
ret = drm_buffer_object_create(dev,
size, drm_bo_type_device,
flags, 0, alignment,
0, &obj_priv->bo);
if (ret)
goto fail;
return obj;
fail:
return NULL;
}
int radeon_gem_create_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_radeon_gem_create *args = data;
struct drm_radeon_gem_object *obj_priv;
struct drm_gem_object *obj;
int ret = 0;
uint32_t flags;
int handle;
/* create a gem object to contain this object in */
args->size = roundup(args->size, PAGE_SIZE);
obj = radeon_gem_object_alloc(dev, args->size, args->alignment, args->initial_domain);
if (!obj)
return -EINVAL;
obj_priv = obj->driver_private;
DRM_DEBUG("obj is %p bo is %p, %d\n", obj, obj_priv->bo, obj_priv->bo->num_pages);
ret = drm_gem_handle_create(file_priv, obj, &handle);
mutex_lock(&dev->struct_mutex);
drm_gem_object_handle_unreference(obj);
mutex_unlock(&dev->struct_mutex);
if (ret)
goto fail;
args->handle = handle;
return 0;
fail:
drm_gem_object_unreference(obj);
return ret;
}
int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
/* transition the BO to a domain - just validate the BO into a certain domain */
struct drm_radeon_gem_set_domain *args = data;
struct drm_gem_object *obj;
struct drm_radeon_gem_object *obj_priv;
int ret;
/* for now if someone requests domain CPU - just make sure the buffer is finished with */
/* just do a BO wait for now */
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL)
return -EINVAL;
obj_priv = obj->driver_private;
mutex_lock(&obj_priv->bo->mutex);
ret = drm_bo_wait(obj_priv->bo, 0, 1, 0, 0);
mutex_unlock(&obj_priv->bo->mutex);
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return ret;
}
int radeon_gem_pread_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
return -ENOSYS;
}
int radeon_gem_pwrite_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
return -ENOSYS;
}
int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_radeon_gem_mmap *args = data;
struct drm_gem_object *obj;
struct drm_radeon_gem_object *obj_priv;
loff_t offset;
unsigned long addr;
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL)
return -EINVAL;
offset = args->offset;
DRM_DEBUG("got here %p\n", obj);
obj_priv = obj->driver_private;
DRM_DEBUG("got here %p %p %lld %ld\n", obj, obj_priv->bo, args->size, obj_priv->bo->num_pages);
if (!obj_priv->bo) {
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
down_write(&current->mm->mmap_sem);
addr = do_mmap_pgoff(file_priv->filp, 0, args->size,
PROT_READ | PROT_WRITE, MAP_SHARED,
obj_priv->bo->map_list.hash.key);
up_write(&current->mm->mmap_sem);
DRM_DEBUG("got here %p\n", obj);
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
if (IS_ERR((void *)addr))
return addr;
args->addr_ptr = (uint64_t) addr;
return 0;
}
int radeon_gem_pin_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_radeon_gem_pin *args = data;
struct drm_gem_object *obj;
struct drm_radeon_gem_object *obj_priv;
int ret;
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL)
return -EINVAL;
obj_priv = obj->driver_private;
DRM_DEBUG("got here %p %p %d\n", obj, obj_priv->bo, atomic_read(&obj_priv->bo->usage));
/* validate into a pin with no fence */
ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT,
DRM_BO_HINT_DONT_FENCE,
0, NULL);
args->offset = obj_priv->bo->offset;
DRM_DEBUG("got here %p %p\n", obj, obj_priv->bo);
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return ret;
}
int radeon_gem_unpin_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_radeon_gem_unpin *args = data;
struct drm_gem_object *obj;
struct drm_radeon_gem_object *obj_priv;
int ret;
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL)
return -EINVAL;
obj_priv = obj->driver_private;
/* validate into a pin with no fence */
ret = drm_bo_do_validate(obj_priv->bo, DRM_BO_FLAG_NO_EVICT, DRM_BO_FLAG_NO_EVICT,
DRM_BO_HINT_DONT_FENCE,
0, NULL);
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return ret;
}
int radeon_gem_busy(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
return 0;
}
int radeon_gem_execbuffer(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
return -ENOSYS;
}
int radeon_gem_indirect_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_radeon_gem_indirect *args = data;
struct drm_radeon_private *dev_priv = dev->dev_private;
struct drm_gem_object *obj;
struct drm_radeon_gem_object *obj_priv;
uint32_t start, end;
int ret;
RING_LOCALS;
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL)
return -EINVAL;
obj_priv = obj->driver_private;
DRM_DEBUG("got here %p %d\n", obj, args->used);
//RING_SPACE_TEST_WITH_RETURN(dev_priv);
//VB_AGE_TEST_WITH_RETURN(dev_priv);
ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT,
0 , 0, NULL);
if (ret)
return ret;
/* Wait for the 3D stream to idle before the indirect buffer
* containing 2D acceleration commands is processed.
*/
BEGIN_RING(2);
RADEON_WAIT_UNTIL_3D_IDLE();
ADVANCE_RING();
start = 0;
end = args->used;
if (start != end) {
int offset = (dev_priv->gart_vm_start +
+ obj_priv->bo->offset + start);
int dwords = (end - start + 3) / sizeof(u32);
#if 0
/* Indirect buffer data must be an even number of
* dwords, so if we've been given an odd number we must
* pad the data with a Type-2 CP packet.
*/
if (dwords & 1) {
u32 *data = (u32 *)
((char *)dev->agp_buffer_map->handle
+ buf->offset + start);
data[dwords++] = RADEON_CP_PACKET2;
}
#endif
/* Fire off the indirect buffer */
BEGIN_RING(3);
OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1));
OUT_RING(offset);
OUT_RING(dwords);
ADVANCE_RING();
}
COMMIT_RING();
/* we need to fence the buffer */
ret = drm_fence_buffer_objects(dev, NULL, 0, NULL, &obj_priv->fence);
if (ret) {
drm_putback_buffer_objects(dev);
ret = 0;
goto fail;
}
/* dereference he fence object */
drm_fence_usage_deref_unlocked(&obj_priv->fence);
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
ret = 0;
fail:
return ret;
}
/*
* Depending on card genertation, chipset bugs, etc... the amount of vram
* accessible to the CPU can vary. This function is our best shot at figuring
* it out. Returns a value in KB.
*/
static uint32_t radeon_get_accessible_vram(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
uint32_t aper_size;
u8 byte;
if (dev_priv->chip_family >= CHIP_R600)
aper_size = RADEON_READ(R600_CONFIG_APER_SIZE) / 1024;
else
aper_size = RADEON_READ(RADEON_CONFIG_APER_SIZE) / 1024;
/* Set HDP_APER_CNTL only on cards that are known not to be broken,
* that is has the 2nd generation multifunction PCI interface
*/
if (dev_priv->chip_family == CHIP_RV280 ||
dev_priv->chip_family == CHIP_RV350 ||
dev_priv->chip_family == CHIP_RV380 ||
dev_priv->chip_family == CHIP_R420 ||
dev_priv->chip_family == CHIP_RV410 ||
dev_priv->chip_family >= CHIP_RS600) {
uint32_t temp = RADEON_READ(RADEON_HOST_PATH_CNTL);
temp |= RADEON_HDP_APER_CNTL;
RADEON_WRITE(RADEON_HOST_PATH_CNTL, temp);
return aper_size * 2;
}
/* Older cards have all sorts of funny issues to deal with. First
* check if it's a multifunction card by reading the PCI config
* header type... Limit those to one aperture size
*/
pci_read_config_byte(dev->pdev, 0xe, &byte);
if (byte & 0x80)
return aper_size;
/* Single function older card. We read HDP_APER_CNTL to see how the BIOS
* have set it up. We don't write this as it's broken on some ASICs but
* we expect the BIOS to have done the right thing (might be too optimistic...)
*/
if (RADEON_READ(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL)
return aper_size * 2;
return aper_size;
}
/* code from the DDX - do memory sizing */
void radeon_vram_setup(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
uint32_t vram;
uint32_t accessible, bar_size;
if ((dev_priv->chip_family <= CHIP_RV515) && (dev_priv->flags & RADEON_IS_IGP)) {
uint32_t tom = RADEON_READ(RADEON_NB_TOM);
vram = (((tom >> 16) - (tom & 0xffff) + 1) << 6);
RADEON_WRITE(RADEON_CONFIG_MEMSIZE, vram * 1024);
} else {
if (dev_priv->chip_family >= CHIP_R600)
vram = RADEON_READ(R600_CONFIG_MEMSIZE) / 1024;
else {
vram = RADEON_READ(RADEON_CONFIG_MEMSIZE) / 1024;
/* Some production boards of m6 will return 0 if it's 8 MB */
if (vram == 0) {
vram = 8192;
RADEON_WRITE(RADEON_CONFIG_MEMSIZE, 0x800000);
}
}
}
accessible = radeon_get_accessible_vram(dev);
bar_size = drm_get_resource_len(dev, 0) / 1024;
if (bar_size == 0)
bar_size = 0x20000;
if (accessible > bar_size)
accessible = bar_size;
DRM_INFO("Detected VRAM RAM=%dK, accessible=%uK, BAR=%uK\n",
vram, accessible, bar_size);
dev_priv->mm.vram_offset = dev_priv->fb_aper_offset;
dev_priv->mm.vram_size = vram * 1024;
dev_priv->mm.vram_visible = accessible * 1024;
}
static int radeon_gart_init(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
int ret;
u32 base = 0;
/* setup a 32MB GART */
dev_priv->gart_size = dev_priv->mm.gart_size;
#if __OS_HAS_AGP
/* setup VRAM vs GART here */
if (dev_priv->flags & RADEON_IS_AGP) {
base = dev->agp->base;
if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location &&
base < (dev_priv->fb_location + dev_priv->fb_size - 1)) {
DRM_INFO("Can't use agp base @0x%08xlx, won't fit\n",
dev->agp->base);
base = 0;
}
}
#endif
if (base == 0) {
base = dev_priv->fb_location + dev_priv->fb_size;
if (base < dev_priv->fb_location ||
((base + dev_priv->gart_size) & 0xfffffffful) < base)
base = dev_priv->fb_location
- dev_priv->gart_size;
}
/* start on the card */
dev_priv->gart_vm_start = base & 0xffc00000u;
if (dev_priv->gart_vm_start != base)
DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n",
base, dev_priv->gart_vm_start);
/* if on PCIE we need to allocate an fb object for the PCIE GART table */
if (dev_priv->flags & RADEON_IS_PCIE) {
ret = drm_buffer_object_create(dev, RADEON_PCIGART_TABLE_SIZE,
drm_bo_type_kernel,
DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_NO_EVICT,
0, 1, 0, &dev_priv->mm.pcie_table);
if (ret)
return -EINVAL;
DRM_DEBUG("pcie table bo created %p, %x\n", dev_priv->mm.pcie_table, dev_priv->mm.pcie_table->offset);
ret = drm_bo_kmap(dev_priv->mm.pcie_table, 0, RADEON_PCIGART_TABLE_SIZE >> PAGE_SHIFT,
&dev_priv->mm.pcie_table_map);
if (ret)
return -EINVAL;
dev_priv->pcigart_offset_set = 2;
dev_priv->gart_info.bus_addr = dev_priv->fb_location + dev_priv->mm.pcie_table->offset;
dev_priv->gart_info.addr = dev_priv->mm.pcie_table_map.virtual;
dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE;
dev_priv->gart_info.gart_table_location = DRM_ATI_GART_FB;
memset(dev_priv->gart_info.addr, 0, RADEON_PCIGART_TABLE_SIZE);
} else if (!(dev_priv->flags & RADEON_IS_AGP)) {
/* allocate PCI GART table */
dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
ret = drm_ati_alloc_pcigart_table(dev, &dev_priv->gart_info);
if (ret) {
DRM_ERROR("cannot allocate PCI GART page!\n");
return -EINVAL;
}
dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN;
if (dev_priv->flags & RADEON_IS_IGPGART)
dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP;
else
dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI;
dev_priv->gart_info.addr = NULL;
dev_priv->gart_info.bus_addr = 0;
}
/* gart values setup - start the GART */
if (dev_priv->flags & RADEON_IS_AGP) {
radeon_set_pcigart(dev_priv, 0);
} else {
radeon_set_pcigart(dev_priv, 1);
}
return 0;
}
int radeon_alloc_gart_objects(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
int ret;
ret = drm_buffer_object_create(dev, RADEON_DEFAULT_RING_SIZE,
drm_bo_type_kernel,
DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_TT |
DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_NO_EVICT,
0, 1, 0, &dev_priv->mm.ring);
if (ret) {
DRM_ERROR("failed to allocate ring\n");
return -EINVAL;
}
ret = drm_bo_kmap(dev_priv->mm.ring, 0, RADEON_DEFAULT_RING_SIZE >> PAGE_SHIFT,
&dev_priv->mm.ring_map);
if (ret) {
DRM_ERROR("failed to map ring\n");
return -EINVAL;
}
ret = drm_buffer_object_create(dev, PAGE_SIZE,
drm_bo_type_kernel,
DRM_BO_FLAG_WRITE |DRM_BO_FLAG_READ | DRM_BO_FLAG_MEM_TT |
DRM_BO_FLAG_MAPPABLE | DRM_BO_FLAG_NO_EVICT,
0, 1, 0, &dev_priv->mm.ring_read_ptr);
if (ret) {
DRM_ERROR("failed to allocate ring read\n");
return -EINVAL;
}
ret = drm_bo_kmap(dev_priv->mm.ring_read_ptr, 0,
PAGE_SIZE >> PAGE_SHIFT,
&dev_priv->mm.ring_read_ptr_map);
if (ret) {
DRM_ERROR("failed to map ring read\n");
return -EINVAL;
}
DRM_DEBUG("Ring ptr %p mapped at %d %p, read ptr %p maped at %d %p\n",
dev_priv->mm.ring, dev_priv->mm.ring->offset, dev_priv->mm.ring_map.virtual,
dev_priv->mm.ring_read_ptr, dev_priv->mm.ring_read_ptr->offset, dev_priv->mm.ring_read_ptr_map.virtual);
return 0;
}
/* init memory manager - start with all of VRAM and a 32MB GART aperture for now */
int radeon_gem_mm_init(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
int ret;
/* size the mappable VRAM memory for now */
radeon_vram_setup(dev);
drm_bo_init_mm(dev, DRM_BO_MEM_VRAM, 0, /*dev_priv->mm.vram_offset >> PAGE_SHIFT,*/
(dev_priv->mm.vram_visible) >> PAGE_SHIFT,
0);
dev_priv->mm.gart_size = (32 * 1024 * 1024);
dev_priv->mm.gart_start = 0;
ret = radeon_gart_init(dev);
if (ret)
return -EINVAL;
drm_bo_init_mm(dev, DRM_BO_MEM_TT, 0,
dev_priv->mm.gart_size >> PAGE_SHIFT,
0);
/* need to allocate some objects in the GART */
/* ring + ring read ptr */
ret = radeon_alloc_gart_objects(dev);
if (ret)
return -EINVAL;
return 0;
}
void radeon_gem_mm_fini(struct drm_device *dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
mutex_lock(&dev->struct_mutex);
if (dev_priv->mm.ring_read_ptr) {
drm_bo_kunmap(&dev_priv->mm.ring_read_ptr_map);
drm_bo_usage_deref_locked(&dev_priv->mm.ring_read_ptr);
}
if (dev_priv->mm.ring) {
drm_bo_kunmap(&dev_priv->mm.ring_map);
drm_bo_usage_deref_locked(&dev_priv->mm.ring);
}
if (drm_bo_clean_mm(dev, DRM_BO_MEM_TT, 1)) {
DRM_DEBUG("delaying takedown of TTM memory\n");
}
if (dev_priv->flags & RADEON_IS_PCIE) {
if (dev_priv->mm.pcie_table) {
drm_bo_kunmap(&dev_priv->mm.pcie_table_map);
drm_bo_usage_deref_locked(&dev_priv->mm.pcie_table);
}
}
if (drm_bo_clean_mm(dev, DRM_BO_MEM_VRAM, 1)) {
DRM_DEBUG("delaying takedown of TTM memory\n");
}
mutex_unlock(&dev->struct_mutex);
}
int radeon_gem_object_pin(struct drm_gem_object *obj,
uint32_t alignment)
{
struct drm_radeon_gem_object *obj_priv;
int ret;
obj_priv = obj->driver_private;
ret = drm_bo_do_validate(obj_priv->bo, 0, DRM_BO_FLAG_NO_EVICT,
DRM_BO_HINT_DONT_FENCE, 0, NULL);
return ret;
}

131
linux-core/radeon_i2c.c Normal file
View File

@ -0,0 +1,131 @@
/*
* Copyright 2007-8 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Dave Airlie
* Alex Deucher
*/
#include "drmP.h"
#include "radeon_drm.h"
#include "radeon_drv.h"
static int get_clock(void *i2c_priv)
{
struct radeon_i2c_chan *i2c = i2c_priv;
struct drm_radeon_private *dev_priv = i2c->dev->dev_private;
struct radeon_i2c_bus_rec *rec = &i2c->rec;
uint32_t val;
val = RADEON_READ(rec->get_clk_reg);
val &= rec->get_clk_mask;
return (val != 0);
}
static int get_data(void *i2c_priv)
{
struct radeon_i2c_chan *i2c = i2c_priv;
struct drm_radeon_private *dev_priv = i2c->dev->dev_private;
struct radeon_i2c_bus_rec *rec = &i2c->rec;
uint32_t val;
val = RADEON_READ(rec->get_data_reg);
val &= rec->get_data_mask;
return (val != 0);
}
static void set_clock(void *i2c_priv, int clock)
{
struct radeon_i2c_chan *i2c = i2c_priv;
struct drm_radeon_private *dev_priv = i2c->dev->dev_private;
struct radeon_i2c_bus_rec *rec = &i2c->rec;
uint32_t val;
val = RADEON_READ(rec->put_clk_reg) & (uint32_t)~(rec->put_clk_mask);
val |= clock ? 0 : rec->put_clk_mask;
RADEON_WRITE(rec->put_clk_reg, val);
}
static void set_data(void *i2c_priv, int data)
{
struct radeon_i2c_chan *i2c = i2c_priv;
struct drm_radeon_private *dev_priv = i2c->dev->dev_private;
struct radeon_i2c_bus_rec *rec = &i2c->rec;
uint32_t val;
val = RADEON_READ(rec->put_data_reg) & (uint32_t)~(rec->put_data_mask);
val |= data ? 0 : rec->put_data_mask;
RADEON_WRITE(rec->put_data_reg, val);
}
struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
struct radeon_i2c_bus_rec *rec,
const char *name)
{
struct radeon_i2c_chan *i2c;
int ret;
i2c = drm_calloc(1, sizeof(struct radeon_i2c_chan), DRM_MEM_DRIVER);
if (i2c == NULL)
return NULL;
i2c->adapter.owner = THIS_MODULE;
i2c->adapter.id = I2C_HW_B_RADEON;
i2c->adapter.algo_data = &i2c->algo;
i2c->dev = dev;
i2c->algo.setsda = set_data;
i2c->algo.setscl = set_clock;
i2c->algo.getsda = get_data;
i2c->algo.getscl = get_clock;
i2c->algo.udelay = 20;
i2c->algo.timeout = usecs_to_jiffies(2200);
i2c->algo.data = i2c;
i2c->rec = *rec;
i2c_set_adapdata(&i2c->adapter, i2c);
ret = i2c_bit_add_bus(&i2c->adapter);
if (ret) {
DRM_INFO("Failed to register i2c %s\n", name);
goto out_free;
}
return i2c;
out_free:
drm_free(i2c, sizeof(struct radeon_i2c_chan), DRM_MEM_DRIVER);
return NULL;
}
void radeon_i2c_destroy(struct radeon_i2c_chan *i2c)
{
if (!i2c)
return;
i2c_del_adapter(&i2c->adapter);
drm_free(i2c, sizeof(struct radeon_i2c_chan), DRM_MEM_DRIVER);
}
struct drm_encoder *radeon_best_encoder(struct drm_connector *connector)
{
return NULL;
}

255
linux-core/radeon_mode.h Normal file
View File

@ -0,0 +1,255 @@
/*
* Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
* VA Linux Systems Inc., Fremont, California.
* Copyright 2008 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Original Authors:
* Kevin E. Martin, Rickard E. Faith, Alan Hourihane
*
* Kernel port Author: Dave Airlie
*/
#ifndef RADEON_MODE_H
#define RADEON_MODE_H
#include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/i2c-algo-bit.h>
#define to_radeon_crtc(x) container_of(x, struct radeon_crtc, base)
#define to_radeon_connector(x) container_of(x, struct radeon_connector, base)
#define to_radeon_encoder(x) container_of(x, struct radeon_encoder, base)
#define to_radeon_framebuffer(x) container_of(x, struct radeon_framebuffer, base)
enum radeon_connector_type {
CONNECTOR_NONE,
CONNECTOR_VGA,
CONNECTOR_DVI_I,
CONNECTOR_DVI_D,
CONNECTOR_DVI_A,
CONNECTOR_STV,
CONNECTOR_CTV,
CONNECTOR_LVDS,
CONNECTOR_DIGITAL,
CONNECTOR_SCART,
CONNECTOR_HDMI_TYPE_A,
CONNECTOR_HDMI_TYPE_B,
CONNECTOR_0XC,
CONNECTOR_0XD,
CONNECTOR_DIN,
CONNECTOR_DISPLAY_PORT,
CONNECTOR_UNSUPPORTED
};
enum radeon_dac_type {
DAC_NONE = 0,
DAC_PRIMARY = 1,
DAC_TVDAC = 2,
DAC_EXT = 3
};
enum radeon_tmds_type {
TMDS_NONE = 0,
TMDS_INT = 1,
TMDS_EXT = 2,
TMDS_LVTMA = 3,
TMDS_DDIA = 4,
TMDS_UNIPHY = 5
};
enum radeon_dvi_type {
DVI_AUTO,
DVI_DIGITAL,
DVI_ANALOG
};
enum radeon_rmx_type {
RMX_OFF,
RMX_FULL,
RMX_CENTER,
};
struct radeon_i2c_bus_rec {
bool valid;
uint32_t mask_clk_reg;
uint32_t mask_data_reg;
uint32_t put_clk_reg;
uint32_t put_data_reg;
uint32_t get_clk_reg;
uint32_t get_data_reg;
uint32_t mask_clk_mask;
uint32_t mask_data_mask;
uint32_t put_clk_mask;
uint32_t put_data_mask;
uint32_t get_clk_mask;
uint32_t get_data_mask;
};
struct radeon_bios_connector {
enum radeon_dac_type dac_type;
enum radeon_tmds_type tmds_type;
enum radeon_connector_type connector_type;
bool valid;
int output_id;
int devices;
int hpd_mask;
struct radeon_i2c_bus_rec ddc_i2c;
int igp_lane_info;
};
#define RADEON_MAX_BIOS_CONNECTOR 16
#define RADEON_PLL_USE_BIOS_DIVS (1 << 0)
#define RADEON_PLL_NO_ODD_POST_DIV (1 << 1)
#define RADEON_PLL_USE_REF_DIV (1 << 2)
#define RADEON_PLL_LEGACY (1 << 3)
#define RADEON_PLL_PREFER_LOW_REF_DIV (1 << 4)
struct radeon_pll {
uint16_t reference_freq;
uint16_t reference_div;
uint32_t pll_in_min;
uint32_t pll_in_max;
uint32_t pll_out_min;
uint32_t pll_out_max;
uint16_t xclk;
uint32_t min_ref_div;
uint32_t max_ref_div;
uint32_t min_post_div;
uint32_t max_post_div;
uint32_t min_feedback_div;
uint32_t max_feedback_div;
uint32_t best_vco;
};
struct radeon_mode_info {
struct atom_context *atom_context;
struct radeon_bios_connector bios_connector[RADEON_MAX_BIOS_CONNECTOR];
struct radeon_pll pll;
};
struct radeon_crtc {
struct drm_crtc base;
int crtc_id;
u8 lut_r[256], lut_g[256], lut_b[256];
bool enabled;
bool can_tile;
uint32_t crtc_offset;
struct radeon_framebuffer *fbdev_fb;
struct drm_mode_set mode_set;
};
struct radeon_i2c_chan {
struct drm_device *dev;
struct i2c_adapter adapter;
struct i2c_algo_bit_data algo;
struct radeon_i2c_bus_rec rec;
};
#define RADEON_USE_RMX 1
struct radeon_encoder {
struct drm_encoder base;
uint32_t encoder_mode;
uint32_t flags;
enum radeon_rmx_type rmx_type;
union {
enum radeon_dac_type dac;
enum radeon_tmds_type tmds;
} type;
int atom_device; /* atom devices */
uint32_t panel_xres, panel_yres;
uint32_t hoverplus, hsync_width;
uint32_t hblank;
uint32_t voverplus, vsync_width;
uint32_t vblank;
uint32_t panel_pwr_delay;
uint32_t dotclock;
};
struct radeon_connector {
struct drm_connector base;
struct radeon_i2c_chan *ddc_bus;
int use_digital;
};
struct radeon_framebuffer {
struct drm_framebuffer base;
struct drm_gem_object *obj;
struct drm_bo_kmap_obj kmap_obj;
};
extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
struct radeon_i2c_bus_rec *rec,
const char *name);
extern void radeon_i2c_destroy(struct radeon_i2c_chan *i2c);
extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
extern struct drm_connector *radeon_connector_add(struct drm_device *dev, int bios_index);
extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector);
extern void radeon_compute_pll(struct radeon_pll *pll,
uint64_t freq,
uint32_t *dot_clock_p,
uint32_t *fb_div_p,
uint32_t *ref_div_p,
uint32_t *post_div_p,
int flags);
struct drm_encoder *radeon_encoder_lvtma_add(struct drm_device *dev, int bios_index);
struct drm_encoder *radeon_encoder_atom_dac_add(struct drm_device *dev, int bios_index, int dac_id, int with_tv);
struct drm_encoder *radeon_encoder_atom_tmds_add(struct drm_device *dev, int bios_index, int tmds_type);
struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index);
extern void radeon_crtc_load_lut(struct drm_crtc *crtc);
extern void atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y);
extern void atombios_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode,
int x, int y);
extern void atombios_crtc_dpms(struct drm_crtc *crtc, int mode);
extern bool radeon_atom_get_clock_info(struct drm_device *dev);
extern bool radeon_combios_get_clock_info(struct drm_device *dev);
extern void radeon_get_lvds_info(struct radeon_encoder *encoder);
extern bool radeon_combios_get_lvds_info(struct radeon_encoder *encoder);
extern void radeon_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno);
struct drm_framebuffer *radeon_user_framebuffer_create(struct drm_device *dev,
struct drm_file *filp,
struct drm_mode_fb_cmd *mode_cmd);
int radeonfb_probe(struct drm_device *dev);
int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev);
void radeon_atombios_init_crtc(struct drm_device *dev,
struct radeon_crtc *radeon_crtc);
void avivo_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state);
void radeon_atom_static_pwrmgt_setup(struct drm_device *dev, int enable);
void radeon_atom_dyn_clk_setup(struct drm_device *dev, int enable);
void radeon_get_clock_info(struct drm_device *dev);
extern bool radeon_get_atom_connector_info_from_bios_connector_table(struct drm_device *dev);
#endif

5276
linux-core/radeon_reg.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -236,7 +236,7 @@ enum drm_map_type {
_DRM_AGP = 3, /**< AGP/GART */
_DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */
_DRM_CONSISTENT = 5, /**< Consistent memory for PCI DMA */
_DRM_TTM = 6
_DRM_TTM = 6,
};
/**

View File

@ -732,12 +732,12 @@ static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv)
* The actual age emit is done by r300_do_cp_cmdbuf, which is why you must
* be careful about how this function is called.
*/
static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
static void r300_discard_buffer(struct drm_device * dev, struct drm_master *master, struct drm_buf * buf)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
struct drm_radeon_master_private *master_priv = master->driver_priv;
buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
buf_priv->age = ++master_priv->sarea_priv->last_dispatch;
buf->pending = 1;
buf->used = 0;
}
@ -898,6 +898,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
drm_radeon_kcmd_buffer_t *cmdbuf)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
struct drm_device_dma *dma = dev->dma;
struct drm_buf *buf = NULL;
int emit_dispatch_age = 0;
@ -1005,7 +1006,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
}
emit_dispatch_age = 1;
r300_discard_buffer(dev, buf);
r300_discard_buffer(dev, file_priv->master, buf);
break;
case R300_CMD_WAIT:
@ -1060,7 +1061,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
/* Emit the vertex buffer age */
BEGIN_RING(2);
RADEON_DISPATCH_AGE(dev_priv->sarea_priv->last_dispatch);
RADEON_DISPATCH_AGE(master_priv->sarea_priv->last_dispatch);
ADVANCE_RING();
}

File diff suppressed because it is too large Load Diff

View File

@ -457,12 +457,6 @@ typedef struct {
unsigned int last_fence;
} drm_radeon_sarea_t;
/* The only fence class we support */
#define DRM_RADEON_FENCE_CLASS_ACCEL 0
/* Fence type that guarantees read-write flush */
#define DRM_RADEON_FENCE_TYPE_RW 2
/* cache flushes programmed just before the fence */
#define DRM_RADEON_FENCE_FLAG_FLUSHED 0x01000000
/* WARNING: If you change any of these defines, make sure to change the
* defines in the Xserver file (xf86drmRadeon.h)
@ -502,6 +496,17 @@ typedef struct {
#define DRM_RADEON_SURF_ALLOC 0x1a
#define DRM_RADEON_SURF_FREE 0x1b
#define DRM_RADEON_GEM_INFO 0x1c
#define DRM_RADEON_GEM_CREATE 0x1d
#define DRM_RADEON_GEM_MMAP 0x1e
#define DRM_RADEON_GEM_PIN 0x1f
#define DRM_RADEON_GEM_UNPIN 0x20
#define DRM_RADEON_GEM_PREAD 0x21
#define DRM_RADEON_GEM_PWRITE 0x22
#define DRM_RADEON_GEM_SET_DOMAIN 0x23
#define DRM_RADEON_GEM_INDIRECT 0x24 // temporary for X server
#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)
#define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START)
#define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_STOP, drm_radeon_cp_stop_t)
@ -530,6 +535,18 @@ typedef struct {
#define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t)
#define DRM_IOCTL_RADEON_SURF_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t)
#define DRM_IOCTL_RADEON_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_INFO, struct drm_radeon_gem_info)
#define DRM_IOCTL_RADEON_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_CREATE, struct drm_radeon_gem_create)
#define DRM_IOCTL_RADEON_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_MMAP, struct drm_radeon_gem_mmap)
#define DRM_IOCTL_RADEON_GEM_PIN DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PIN, struct drm_radeon_gem_pin)
#define DRM_IOCTL_RADEON_GEM_UNPIN DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_UNPIN, struct drm_radeon_gem_unpin)
#define DRM_IOCTL_RADEON_GEM_PREAD DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PREAD, struct drm_radeon_gem_pread)
#define DRM_IOCTL_RADEON_GEM_PWRITE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PWRITE, struct drm_radeon_gem_pwrite)
#define DRM_IOCTL_RADEON_GEM_SET_DOMAIN DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_DOMAIN, struct drm_radeon_gem_set_domain)
#define DRM_IOCTL_RADEON_GEM_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_INDIRECT, struct drm_radeon_gem_indirect)
typedef struct drm_radeon_init {
enum {
RADEON_INIT_CP = 0x01,
@ -756,4 +773,92 @@ typedef struct drm_radeon_surface_free {
#define DRM_RADEON_VBLANK_CRTC1 1
#define DRM_RADEON_VBLANK_CRTC2 2
#define RADEON_GEM_DOMAIN_CPU 0x1
#define RADEON_GEM_DOMAIN_VRAM 0x2
#define RADEON_GEM_DOMAIN_2D 0x4
#define RADEON_GEM_DOMAIN_3D 0x8
#define RADEON_GEM_DOMAIN_TEXTURE 0x10
#define RADEON_GEM_DOMAIN_GPU 0x20 // for vertex buffers
/* return to userspace start/size of gtt and vram apertures */
struct drm_radeon_gem_info {
uint64_t gart_start;
uint64_t gart_size;
uint64_t vram_start;
uint64_t vram_size;
uint64_t vram_visible;
};
struct drm_radeon_gem_create {
uint64_t size;
uint64_t alignment;
uint32_t handle;
uint32_t initial_domain; // to allow VRAM to be created
uint32_t no_backing_store; // for VRAM objects - select whether they need backing store
// pretty much front/back/depth don't need it - other things do
};
struct drm_radeon_gem_mmap {
uint32_t handle;
uint32_t pad;
uint64_t offset;
uint64_t size;
uint64_t addr_ptr;
};
struct drm_radeon_gem_set_domain {
uint32_t handle;
uint32_t read_domains;
uint32_t write_domain;
};
struct drm_radeon_gem_exec_buffer {
};
struct drm_radeon_gem_pin {
uint32_t handle;
uint32_t pad;
uint64_t alignment;
uint64_t offset;
};
struct drm_radeon_gem_unpin {
uint32_t handle;
uint32_t pad;
};
struct drm_radeon_gem_busy {
uint32_t handle;
uint32_t busy;
};
struct drm_radeon_gem_pread {
/** Handle for the object being read. */
uint32_t handle;
uint32_t pad;
/** Offset into the object to read from */
uint64_t offset;
/** Length of data to read */
uint64_t size;
/** Pointer to write the data into. */
uint64_t data_ptr; /* void *, but pointers are not 32/64 compatible */
};
struct drm_radeon_gem_pwrite {
/** Handle for the object being written to. */
uint32_t handle;
uint32_t pad;
/** Offset into the object to write to */
uint64_t offset;
/** Length of data to write */
uint64_t size;
/** Pointer to read the data from. */
uint64_t data_ptr; /* void *, but pointers are not 32/64 compatible */
};
struct drm_radeon_gem_indirect {
uint32_t handle;
uint32_t used;
};
#endif

View File

@ -31,6 +31,7 @@
#ifndef __RADEON_DRV_H__
#define __RADEON_DRV_H__
#include "atom.h"
/* General customization:
*/
@ -96,13 +97,13 @@
* 1.25- Add support for r200 vertex programs (R200_EMIT_VAP_PVS_CNTL,
* new packet type)
* 1.26- Add support for variable size PCI(E) gart aperture
* 1.27- Add support for IGP GART
* 1.27- Add support for IGPGART
* 1.28- Add support for VBL on CRTC2
* 1.29- R500 3D cmd buffer support
*/
#define DRIVER_MAJOR 1
#define DRIVER_MINOR 29
#define DRIVER_MINOR 30
#define DRIVER_PATCHLEVEL 0
/*
@ -124,23 +125,29 @@ enum radeon_family {
CHIP_RV380,
CHIP_R420,
CHIP_RV410,
CHIP_RS400,
CHIP_RS480,
CHIP_RS600,
CHIP_RS690,
CHIP_RS740,
CHIP_RV515,
CHIP_R520,
CHIP_RV530,
CHIP_RV560,
CHIP_RV570,
CHIP_R580,
CHIP_R600,
CHIP_R630,
CHIP_RV610,
CHIP_RV630,
CHIP_RV670,
CHIP_RV620,
CHIP_RV635,
CHIP_RS780,
CHIP_RV770,
CHIP_LAST,
};
enum radeon_cp_microcode_version {
UCODE_R100,
UCODE_R200,
UCODE_R300,
};
/*
* Chip flags
*/
@ -158,9 +165,42 @@ enum radeon_chip_flags {
RADEON_IS_IGPGART = 0x01000000UL,
};
/*
* Errata workarounds
*/
enum radeon_pll_errata {
CHIP_ERRATA_R300_CG = 0x00000001,
CHIP_ERRATA_PLL_DUMMYREADS = 0x00000002,
CHIP_ERRATA_PLL_DELAY = 0x00000004
};
enum radeon_ext_tmds_chip {
RADEON_DVOCHIP_NONE,
RADEON_SIL_164,
RADEON_SIL_1178
};
#if defined(__powerpc__)
enum radeon_mac_model {
RADEON_MAC_NONE,
RADEON_MAC_IBOOK,
RADEON_MAC_POWERBOOK_EXTERNAL,
RADEON_MAC_POWERBOOK_INTERNAL,
RADEON_MAC_POWERBOOK_VGA,
RADEON_MAC_MINI_EXTERNAL,
RADEON_MAC_MINI_INTERNAL,
RADEON_MAC_IMAC_G5_ISIGHT
};
#endif
#define GET_RING_HEAD(dev_priv) (dev_priv->writeback_works ? \
DRM_READ32( (dev_priv)->ring_rptr, 0 ) : RADEON_READ(RADEON_CP_RB_RPTR))
#define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) )
(dev_priv->mm.ring_read_ptr ? readl(dev_priv->mm.ring_read_ptr_map.virtual + 0) : DRM_READ32((dev_priv)->ring_rptr, 0 )) : \
RADEON_READ(RADEON_CP_RB_RPTR))
#define SET_RING_HEAD(dev_priv,val) (dev_priv->mm.ring_read_ptr ? \
writel((val), dev_priv->mm.ring_read_ptr_map.virtual) : \
DRM_WRITE32((dev_priv)->ring_rptr, 0, (val)))
typedef struct drm_radeon_freelist {
unsigned int age;
@ -221,13 +261,35 @@ struct radeon_virt_surface {
struct drm_file *file_priv;
};
struct radeon_mm_info {
uint64_t vram_offset; // Offset into GPU space
uint64_t vram_size;
uint64_t vram_visible;
uint64_t gart_start;
uint64_t gart_size;
struct drm_buffer_object *pcie_table;
struct drm_bo_kmap_obj pcie_table_map;
struct drm_buffer_object *ring;
struct drm_bo_kmap_obj ring_map;
struct drm_buffer_object *ring_read_ptr;
struct drm_bo_kmap_obj ring_read_ptr_map;
};
#include "radeon_mode.h"
struct drm_radeon_master_private {
drm_local_map_t *sarea;
drm_radeon_sarea_t *sarea_priv;
};
typedef struct drm_radeon_private {
drm_radeon_ring_buffer_t ring;
drm_radeon_sarea_t *sarea_priv;
u32 fb_location;
u32 fb_size;
int new_memmap;
int gart_size;
@ -245,8 +307,6 @@ typedef struct drm_radeon_private {
int usec_timeout;
int microcode_version;
struct {
u32 boxes;
int freelist_timeouts;
@ -282,8 +342,6 @@ typedef struct drm_radeon_private {
unsigned long buffers_offset;
unsigned long gart_textures_offset;
drm_local_map_t *sarea;
drm_local_map_t *mmio;
drm_local_map_t *cp_ring;
drm_local_map_t *ring_rptr;
drm_local_map_t *gart_textures;
@ -292,8 +350,8 @@ typedef struct drm_radeon_private {
struct mem_block *fb_heap;
/* SW interrupt */
int counter;
wait_queue_head_t swi_queue;
atomic_t swi_emitted;
int vblank_crtc;
uint32_t irq_enable_reg;
int irq_enabled;
@ -302,9 +360,6 @@ typedef struct drm_radeon_private {
struct radeon_surface surfaces[RADEON_MAX_SURFACES];
struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES];
unsigned long pcigart_offset;
unsigned int pcigart_offset_set;
struct drm_ati_pcigart_info gart_info;
u32 scratch_ages[5];
@ -316,6 +371,28 @@ typedef struct drm_radeon_private {
unsigned long fb_aper_offset;
int num_gb_pipes;
struct radeon_mm_info mm;
drm_local_map_t *mmio;
uint32_t chip_family;
unsigned long pcigart_offset;
unsigned int pcigart_offset_set;
struct drm_ati_pcigart_info gart_info;
struct radeon_mode_info mode_info;
uint8_t *bios; /* copy of the BIOS image */
bool is_atom_bios;
uint16_t bios_header_start;
u32 fb_location;
u32 fb_size;
bool is_ddr;
u32 ram_width;
enum radeon_pll_errata pll_errata;
} drm_radeon_private_t;
typedef struct drm_radeon_buf_priv {
@ -330,6 +407,7 @@ typedef struct drm_radeon_kcmd_buffer {
} drm_radeon_kcmd_buffer_t;
extern int radeon_no_wb;
extern int radeon_dynclks;
extern struct drm_ioctl_desc radeon_ioctls[];
extern int radeon_max_ioctl;
@ -417,9 +495,14 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev,
#define RADEON_BOX_WAIT_IDLE 0x8
#define RADEON_BOX_TEXTURE_LOAD 0x10
#define R600_CONFIG_MEMSIZE 0x5428
#define R600_CONFIG_APER_SIZE 0x5430
/* Register definitions, register access macros and drmAddMap constants
* for Radeon kernel driver.
*/
#include "radeon_reg.h"
#define RADEON_AGP_COMMAND 0x0f60
#define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config */
# define RADEON_AGP_ENABLE (1<<8)
@ -522,16 +605,6 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev,
#define R520_MC_IND_WR_EN (1 << 24)
#define R520_MC_IND_DATA 0x74
#define RV515_MC_FB_LOCATION 0x01
#define RV515_MC_AGP_LOCATION 0x02
#define RV515_MC_AGP_BASE 0x03
#define RV515_MC_AGP_BASE_2 0x04
#define R520_MC_FB_LOCATION 0x04
#define R520_MC_AGP_LOCATION 0x05
#define R520_MC_AGP_BASE 0x06
#define R520_MC_AGP_BASE_2 0x07
#define RADEON_MPP_TB_CONFIG 0x01c0
#define RADEON_MEM_CNTL 0x0140
#define RADEON_MEM_SDRAM_MODE_REG 0x0158
@ -601,9 +674,11 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev,
#define RADEON_SCRATCHOFF( x ) (RADEON_SCRATCH_REG_OFFSET + 4*(x))
#define GET_SCRATCH( x ) (dev_priv->writeback_works \
? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
: RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
#define GET_SCRATCH( x ) (dev_priv->writeback_works ? \
(dev_priv->mm.ring_read_ptr ? \
readl(dev_priv->mm.ring_read_ptr_map.virtual + RADEON_SCRATCHOFF(0)) : \
DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(x))) : \
RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x)))
#define RADEON_CRTC_CRNT_FRAME 0x0214
#define RADEON_CRTC2_CRNT_FRAME 0x0314
@ -628,11 +703,11 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev,
# define RADEON_SW_INT_FIRE (1 << 26)
# define R500_DISPLAY_INT_STATUS (1 << 0)
#define RADEON_HOST_PATH_CNTL 0x0130
# define RADEON_HDP_SOFT_RESET (1 << 26)
# define RADEON_HDP_APER_CNTL (1 << 23)
#define RADEON_HOST_PATH_CNTL 0x0130
# define RADEON_HDP_SOFT_RESET (1 << 26)
# define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28)
# define RADEON_HDP_WC_TIMEOUT_28BCLK (7 << 28)
#define RADEON_NB_TOM 0x15c
#define RADEON_ISYNC_CNTL 0x1724
# define RADEON_ISYNC_ANY2D_IDLE3D (1 << 0)
@ -703,11 +778,6 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev,
# define R300_ZC_FREE (1 << 1)
# define R300_ZC_FLUSH_ALL 0x3
# define R300_ZC_BUSY (1 << 31)
#define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325c
# define RADEON_RB3D_DC_FLUSH (3 << 0)
# define RADEON_RB3D_DC_FREE (3 << 2)
# define RADEON_RB3D_DC_FLUSH_ALL 0xf
# define RADEON_RB3D_DC_BUSY (1 << 31)
#define R300_RB3D_DSTCACHE_CTLSTAT 0x4e4c
# define R300_RB3D_DC_FINISH (1 << 4)
#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c
@ -981,27 +1051,6 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev,
#define RADEON_NUM_VERTICES_SHIFT 16
#define RADEON_COLOR_FORMAT_CI8 2
#define RADEON_COLOR_FORMAT_ARGB1555 3
#define RADEON_COLOR_FORMAT_RGB565 4
#define RADEON_COLOR_FORMAT_ARGB8888 6
#define RADEON_COLOR_FORMAT_RGB332 7
#define RADEON_COLOR_FORMAT_RGB8 9
#define RADEON_COLOR_FORMAT_ARGB4444 15
#define RADEON_TXFORMAT_I8 0
#define RADEON_TXFORMAT_AI88 1
#define RADEON_TXFORMAT_RGB332 2
#define RADEON_TXFORMAT_ARGB1555 3
#define RADEON_TXFORMAT_RGB565 4
#define RADEON_TXFORMAT_ARGB4444 5
#define RADEON_TXFORMAT_ARGB8888 6
#define RADEON_TXFORMAT_RGBA8888 7
#define RADEON_TXFORMAT_Y8 8
#define RADEON_TXFORMAT_VYUY422 10
#define RADEON_TXFORMAT_YVYU422 11
#define RADEON_TXFORMAT_DXT1 12
#define RADEON_TXFORMAT_DXT23 14
#define RADEON_TXFORMAT_DXT45 15
#define R200_PP_TXCBLEND_0 0x2f00
#define R200_PP_TXCBLEND_1 0x2f10
@ -1187,18 +1236,16 @@ extern int r300_do_cp_cmdbuf(struct drm_device *dev,
#define RADEON_RING_HIGH_MARK 128
#define RADEON_PCIGART_TABLE_SIZE (32*1024)
#define RADEON_DEFAULT_RING_SIZE (1024*1024)
#define RADEON_DEFAULT_CP_TIMEOUT 100000 /* usecs */
#define RADEON_READ(reg) DRM_READ32( dev_priv->mmio, (reg) )
#define RADEON_WRITE(reg,val) DRM_WRITE32( dev_priv->mmio, (reg), (val) )
#define RADEON_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) )
#define RADEON_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) )
#define RADEON_WRITE_PLL( addr, val ) \
do { \
RADEON_WRITE8( RADEON_CLOCK_CNTL_INDEX, \
((addr) & 0x1f) | RADEON_PLL_WR_EN ); \
RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) ); \
} while (0)
extern int RADEON_READ_PLL(struct drm_radeon_private *dev_priv, int addr);
extern void RADEON_WRITE_PLL(struct drm_radeon_private *dev_priv, int addr, uint32_t data);
#define RADEON_WRITE_PCIE( addr, val ) \
do { \
@ -1311,7 +1358,7 @@ do { \
OUT_RING( CP_PACKET0( RADEON_RB3D_ZCACHE_CTLSTAT, 0 ) ); \
OUT_RING( RADEON_RB3D_ZC_FLUSH_ALL ); \
} else { \
OUT_RING( CP_PACKET0( R300_RB3D_DSTCACHE_CTLSTAT, 0 ) ); \
OUT_RING( CP_PACKET0( R300_RB3D_ZCACHE_CTLSTAT, 0 ) ); \
OUT_RING( R300_ZC_FLUSH_ALL ); \
} \
} while (0)
@ -1333,7 +1380,8 @@ do { \
#define VB_AGE_TEST_WITH_RETURN( dev_priv ) \
do { \
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; \
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; \
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; \
if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) { \
int __ret = radeon_do_cp_idle( dev_priv ); \
if ( __ret ) return __ret; \
@ -1439,4 +1487,110 @@ do { \
write &= mask; \
} while (0)
/* radeon GEM->TTM munger */
struct drm_radeon_gem_object {
/* wrap a TTM bo */
struct drm_buffer_object *bo;
struct drm_fence_object *fence;
struct drm_gem_object *obj;
};
extern int radeon_gem_info_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int radeon_gem_create_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int radeon_gem_pwrite_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int radeon_gem_pread_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern void radeon_fence_handler(struct drm_device *dev);
extern int radeon_fence_emit_sequence(struct drm_device *dev, uint32_t class,
uint32_t flags, uint32_t *sequence,
uint32_t *native_type);
extern void radeon_poke_flush(struct drm_device *dev, uint32_t class);
extern int radeon_fence_has_irq(struct drm_device *dev, uint32_t class, uint32_t flags);
/* radeon_buffer.c */
extern struct drm_ttm_backend *radeon_create_ttm_backend_entry(struct drm_device *dev);
extern int radeon_fence_types(struct drm_buffer_object *bo, uint32_t *class, uint32_t *type);
extern int radeon_invalidate_caches(struct drm_device *dev, uint64_t buffer_flags);
extern int radeon_init_mem_type(struct drm_device * dev, uint32_t type,
struct drm_mem_type_manager * man);
extern int radeon_move(struct drm_buffer_object * bo,
int evict, int no_wait, struct drm_bo_mem_reg * new_mem);
extern void radeon_gart_flush(struct drm_device *dev);
extern uint64_t radeon_evict_flags(struct drm_buffer_object *bo);
#define BREADCRUMB_BITS 31
#define BREADCRUMB_MASK ((1U << BREADCRUMB_BITS) - 1)
/* Breadcrumb - swi irq */
#define READ_BREADCRUMB(dev_priv) RADEON_READ(RADEON_LAST_SWI_REG)
static inline int radeon_update_breadcrumb(struct drm_device *dev)
{
struct drm_radeon_private *dev_priv = dev->dev_private;
struct drm_radeon_master_private *master_priv;
++dev_priv->counter;
if (dev_priv->counter > BREADCRUMB_MASK)
dev_priv->counter = 1;
if (dev->primary->master) {
master_priv = dev->primary->master->driver_priv;
if (master_priv->sarea_priv)
master_priv->sarea_priv->last_fence = dev_priv->counter;
}
return dev_priv->counter;
}
#define radeon_is_avivo(dev_priv) ((dev_priv->chip_family >= CHIP_RS600))
#define radeon_is_dce3(dev_priv) ((dev_priv->chip_family >= CHIP_RV620))
#define radeon_bios8(dev_priv, v) (dev_priv->bios[v])
#define radeon_bios16(dev_priv, v) (dev_priv->bios[v] | (dev_priv->bios[(v) + 1] << 8))
#define radeon_bios32(dev_priv, v) ((dev_priv->bios[v]) | \
(dev_priv->bios[(v) + 1] << 8) | \
(dev_priv->bios[(v) + 2] << 16) | \
(dev_priv->bios[(v) + 3] << 24))
extern int radeon_emit_irq(struct drm_device * dev);
extern void radeon_gem_free_object(struct drm_gem_object *obj);
extern int radeon_gem_init_object(struct drm_gem_object *obj);
extern int radeon_gem_mm_init(struct drm_device *dev);
extern void radeon_gem_mm_fini(struct drm_device *dev);
extern int radeon_gem_pin_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int radeon_gem_unpin_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int radeon_gem_object_pin(struct drm_gem_object *obj,
uint32_t alignment);
int radeon_gem_indirect_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
struct drm_gem_object *radeon_gem_object_alloc(struct drm_device *dev, int size, int alignment,
int initial_domain);
int radeon_modeset_init(struct drm_device *dev);
void radeon_modeset_cleanup(struct drm_device *dev);
extern u32 radeon_read_mc_reg(drm_radeon_private_t *dev_priv, int addr);
extern void radeon_write_mc_reg(drm_radeon_private_t *dev_priv, u32 addr, u32 val);
extern void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on);
#define RADEONFB_CONN_LIMIT 4
extern int radeon_master_create(struct drm_device *dev, struct drm_master *master);
extern void radeon_master_destroy(struct drm_device *dev, struct drm_master *master);
extern void radeon_cp_dispatch_flip(struct drm_device * dev, struct drm_master *master);
#endif /* __RADEON_DRV_H__ */

View File

@ -198,8 +198,10 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
stat &= dev_priv->irq_enable_reg;
/* SW interrupt */
if (stat & RADEON_SW_INT_TEST)
if (stat & RADEON_SW_INT_TEST) {
DRM_WAKEUP(&dev_priv->swi_queue);
radeon_fence_handler(dev);
}
/* VBLANK interrupt */
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS690) {
@ -216,14 +218,13 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
return IRQ_HANDLED;
}
static int radeon_emit_irq(struct drm_device * dev)
int radeon_emit_irq(struct drm_device * dev)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
unsigned int ret;
RING_LOCALS;
atomic_inc(&dev_priv->swi_emitted);
ret = atomic_read(&dev_priv->swi_emitted);
ret = radeon_update_breadcrumb(dev);
BEGIN_RING(4);
OUT_RING_REG(RADEON_LAST_SWI_REG, ret);
@ -240,13 +241,13 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
(drm_radeon_private_t *) dev->dev_private;
int ret = 0;
if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr)
if (READ_BREADCRUMB(dev_priv) >= swi_nr)
return 0;
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ,
RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr);
READ_BREADCRUMB(dev_priv) >= swi_nr);
return ret;
}
@ -349,7 +350,6 @@ int radeon_driver_irq_postinstall(struct drm_device * dev)
(drm_radeon_private_t *) dev->dev_private;
int ret;
atomic_set(&dev_priv->swi_emitted, 0);
DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
ret = drm_vblank_init(dev, 2);

View File

@ -305,8 +305,9 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
case RADEON_CP_3D_DRAW_INDX_2:
case RADEON_3D_CLEAR_HIZ:
/* safe but r200 only */
if (dev_priv->microcode_version != UCODE_R200) {
DRM_ERROR("Invalid 3d packet for r100-class chip\n");
if ((dev_priv->chip_family < CHIP_R200) ||
(dev_priv->chip_family > CHIP_RV280)) {
DRM_ERROR("Invalid 3d packet for non r200-class chip\n");
return -EINVAL;
}
break;
@ -359,8 +360,8 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
break;
case RADEON_3D_RNDR_GEN_INDX_PRIM:
if (dev_priv->microcode_version != UCODE_R100) {
DRM_ERROR("Invalid 3d packet for r200-class chip\n");
if (dev_priv->chip_family > CHIP_RS200) {
DRM_ERROR("Invalid 3d packet for non-r100-class chip\n");
return -EINVAL;
}
if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[1])) {
@ -370,8 +371,10 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t *
break;
case RADEON_CP_INDX_BUFFER:
if (dev_priv->microcode_version != UCODE_R200) {
DRM_ERROR("Invalid 3d packet for r100-class chip\n");
/* safe but r200 only */
if ((dev_priv->chip_family < CHIP_R200) ||
(dev_priv->chip_family > CHIP_RV280)) {
DRM_ERROR("Invalid 3d packet for non-r200-class chip\n");
return -EINVAL;
}
if ((cmd[1] & 0x8000ffff) != 0x80000810) {
@ -742,13 +745,14 @@ static struct {
*/
static void radeon_clear_box(drm_radeon_private_t * dev_priv,
struct drm_radeon_master_private *master_priv,
int x, int y, int w, int h, int r, int g, int b)
{
u32 color;
RING_LOCALS;
x += dev_priv->sarea_priv->boxes[0].x1;
y += dev_priv->sarea_priv->boxes[0].y1;
x += master_priv->sarea_priv->boxes[0].x1;
y += master_priv->sarea_priv->boxes[0].y1;
switch (dev_priv->color_fmt) {
case RADEON_COLOR_FORMAT_RGB565:
@ -776,7 +780,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv,
RADEON_GMC_SRC_DATATYPE_COLOR |
RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS);
if (dev_priv->sarea_priv->pfCurrentPage == 1) {
if (master_priv->sarea_priv->pfCurrentPage == 1) {
OUT_RING(dev_priv->front_pitch_offset);
} else {
OUT_RING(dev_priv->back_pitch_offset);
@ -790,7 +794,7 @@ static void radeon_clear_box(drm_radeon_private_t * dev_priv,
ADVANCE_RING();
}
static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv, struct drm_radeon_master_private *master_priv)
{
/* Collapse various things into a wait flag -- trying to
* guess if userspase slept -- better just to have them tell us.
@ -807,12 +811,12 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
/* Purple box for page flipping
*/
if (dev_priv->stats.boxes & RADEON_BOX_FLIP)
radeon_clear_box(dev_priv, 4, 4, 8, 8, 255, 0, 255);
radeon_clear_box(dev_priv, master_priv, 4, 4, 8, 8, 255, 0, 255);
/* Red box if we have to wait for idle at any point
*/
if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE)
radeon_clear_box(dev_priv, 16, 4, 8, 8, 255, 0, 0);
radeon_clear_box(dev_priv, master_priv, 16, 4, 8, 8, 255, 0, 0);
/* Blue box: lost context?
*/
@ -820,12 +824,12 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
/* Yellow box for texture swaps
*/
if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD)
radeon_clear_box(dev_priv, 40, 4, 8, 8, 255, 255, 0);
radeon_clear_box(dev_priv, master_priv, 40, 4, 8, 8, 255, 255, 0);
/* Green box if hardware never idles (as far as we can tell)
*/
if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE))
radeon_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0);
radeon_clear_box(dev_priv, master_priv, 64, 4, 8, 8, 0, 255, 0);
/* Draw bars indicating number of buffers allocated
* (not a great measure, easily confused)
@ -834,7 +838,7 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
if (dev_priv->stats.requested_bufs > 100)
dev_priv->stats.requested_bufs = 100;
radeon_clear_box(dev_priv, 4, 16,
radeon_clear_box(dev_priv, master_priv, 4, 16,
dev_priv->stats.requested_bufs, 4,
196, 128, 128);
}
@ -848,11 +852,13 @@ static void radeon_cp_performance_boxes(drm_radeon_private_t * dev_priv)
*/
static void radeon_cp_dispatch_clear(struct drm_device * dev,
struct drm_master *master,
drm_radeon_clear_t * clear,
drm_radeon_clear_rect_t * depth_boxes)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
struct drm_radeon_master_private *master_priv = master->driver_priv;
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear;
int nbox = sarea_priv->nbox;
struct drm_clip_rect *pbox = sarea_priv->boxes;
@ -864,7 +870,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
dev_priv->stats.clears++;
if (dev_priv->sarea_priv->pfCurrentPage == 1) {
if (sarea_priv->pfCurrentPage == 1) {
unsigned int tmp = flags;
flags &= ~(RADEON_FRONT | RADEON_BACK);
@ -890,7 +896,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
/* Make sure we restore the 3D state next time.
*/
dev_priv->sarea_priv->ctx_owner = 0;
sarea_priv->ctx_owner = 0;
for (i = 0; i < nbox; i++) {
int x = pbox[i].x1;
@ -967,7 +973,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
/* Make sure we restore the 3D state next time.
* we haven't touched any "normal" state - still need this?
*/
dev_priv->sarea_priv->ctx_owner = 0;
sarea_priv->ctx_owner = 0;
if ((dev_priv->flags & RADEON_HAS_HIERZ)
&& (flags & RADEON_USE_HIERZ)) {
@ -1015,7 +1021,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
int tileoffset, nrtilesx, nrtilesy, j;
/* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */
if ((dev_priv->flags & RADEON_HAS_HIERZ)
&& !(dev_priv->microcode_version == UCODE_R200)) {
&& (dev_priv->chip_family < CHIP_R200)) {
/* FIXME : figure this out for r200 (when hierz is enabled). Or
maybe r200 actually doesn't need to put the low-res z value into
the tile cache like r100, but just needs to clear the hi-level z-buffer?
@ -1044,7 +1050,8 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
ADVANCE_RING();
tileoffset += depthpixperline >> 6;
}
} else if (dev_priv->microcode_version == UCODE_R200) {
} else if ((dev_priv->chip_family >= CHIP_R200) &&
(dev_priv->chip_family <= CHIP_RV280)) {
/* works for rv250. */
/* find first macro tile (8x2 4x4 z-pixels on rv250) */
tileoffset =
@ -1099,7 +1106,8 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
/* TODO don't always clear all hi-level z tiles */
if ((dev_priv->flags & RADEON_HAS_HIERZ)
&& (dev_priv->microcode_version == UCODE_R200)
&& ((dev_priv->chip_family >= CHIP_R200) &&
(dev_priv->chip_family <= CHIP_RV280))
&& (flags & RADEON_USE_HIERZ))
/* r100 and cards without hierarchical z-buffer have no high-level z-buffer */
/* FIXME : the mask supposedly contains low-res z values. So can't set
@ -1119,8 +1127,9 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
* rendering a quad into just those buffers. Thus, we have to
* make sure the 3D engine is configured correctly.
*/
else if ((dev_priv->microcode_version == UCODE_R200) &&
(flags & (RADEON_DEPTH | RADEON_STENCIL))) {
else if ((dev_priv->chip_family >= CHIP_R200) &&
(dev_priv->chip_family <= CHIP_RV280) &&
(flags & (RADEON_DEPTH | RADEON_STENCIL))) {
int tempPP_CNTL;
int tempRE_CNTL;
@ -1214,7 +1223,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
/* Make sure we restore the 3D state next time.
*/
dev_priv->sarea_priv->ctx_owner = 0;
sarea_priv->ctx_owner = 0;
for (i = 0; i < nbox; i++) {
@ -1285,7 +1294,7 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
/* Make sure we restore the 3D state next time.
*/
dev_priv->sarea_priv->ctx_owner = 0;
sarea_priv->ctx_owner = 0;
for (i = 0; i < nbox; i++) {
@ -1328,20 +1337,21 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev,
* wait on this value before performing the clear ioctl. We
* need this because the card's so damned fast...
*/
dev_priv->sarea_priv->last_clear++;
sarea_priv->last_clear++;
BEGIN_RING(4);
RADEON_CLEAR_AGE(dev_priv->sarea_priv->last_clear);
RADEON_CLEAR_AGE(sarea_priv->last_clear);
RADEON_WAIT_UNTIL_IDLE();
ADVANCE_RING();
}
static void radeon_cp_dispatch_swap(struct drm_device * dev)
static void radeon_cp_dispatch_swap(struct drm_device * dev, struct drm_master *master)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
struct drm_radeon_master_private *master_priv = master->driver_priv;
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
int nbox = sarea_priv->nbox;
struct drm_clip_rect *pbox = sarea_priv->boxes;
int i;
@ -1351,7 +1361,7 @@ static void radeon_cp_dispatch_swap(struct drm_device * dev)
/* Do some trivial performance monitoring...
*/
if (dev_priv->do_boxes)
radeon_cp_performance_boxes(dev_priv);
radeon_cp_performance_boxes(dev_priv, master_priv);
/* Wait for the 3D stream to idle before dispatching the bitblt.
* This will prevent data corruption between the two streams.
@ -1385,7 +1395,7 @@ static void radeon_cp_dispatch_swap(struct drm_device * dev)
/* Make this work even if front & back are flipped:
*/
OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1));
if (dev_priv->sarea_priv->pfCurrentPage == 0) {
if (sarea_priv->pfCurrentPage == 0) {
OUT_RING(dev_priv->back_pitch_offset);
OUT_RING(dev_priv->front_pitch_offset);
} else {
@ -1405,31 +1415,32 @@ static void radeon_cp_dispatch_swap(struct drm_device * dev)
* throttle the framerate by waiting for this value before
* performing the swapbuffer ioctl.
*/
dev_priv->sarea_priv->last_frame++;
sarea_priv->last_frame++;
BEGIN_RING(4);
RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
RADEON_FRAME_AGE(sarea_priv->last_frame);
RADEON_WAIT_UNTIL_2D_IDLE();
ADVANCE_RING();
}
static void radeon_cp_dispatch_flip(struct drm_device * dev)
void radeon_cp_dispatch_flip(struct drm_device * dev, struct drm_master *master)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
struct drm_sarea *sarea = (struct drm_sarea *) dev_priv->sarea->handle;
int offset = (dev_priv->sarea_priv->pfCurrentPage == 1)
struct drm_radeon_master_private *master_priv = master->driver_priv;
struct drm_sarea *sarea = (struct drm_sarea *) master_priv->sarea->handle;
int offset = (master_priv->sarea_priv->pfCurrentPage == 1)
? dev_priv->front_offset : dev_priv->back_offset;
RING_LOCALS;
DRM_DEBUG("pfCurrentPage=%d\n",
dev_priv->sarea_priv->pfCurrentPage);
master_priv->sarea_priv->pfCurrentPage);
/* Do some trivial performance monitoring...
*/
if (dev_priv->do_boxes) {
dev_priv->stats.boxes |= RADEON_BOX_FLIP;
radeon_cp_performance_boxes(dev_priv);
radeon_cp_performance_boxes(dev_priv, master_priv);
}
/* Update the frame offsets for both CRTCs
@ -1441,7 +1452,7 @@ static void radeon_cp_dispatch_flip(struct drm_device * dev)
((sarea->frame.y * dev_priv->front_pitch +
sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7)
+ offset);
OUT_RING_REG(RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base
OUT_RING_REG(RADEON_CRTC2_OFFSET, master_priv->sarea_priv->crtc2_base
+ offset);
ADVANCE_RING();
@ -1450,13 +1461,13 @@ static void radeon_cp_dispatch_flip(struct drm_device * dev)
* throttle the framerate by waiting for this value before
* performing the swapbuffer ioctl.
*/
dev_priv->sarea_priv->last_frame++;
dev_priv->sarea_priv->pfCurrentPage =
1 - dev_priv->sarea_priv->pfCurrentPage;
master_priv->sarea_priv->last_frame++;
master_priv->sarea_priv->pfCurrentPage =
1 - master_priv->sarea_priv->pfCurrentPage;
BEGIN_RING(2);
RADEON_FRAME_AGE(dev_priv->sarea_priv->last_frame);
RADEON_FRAME_AGE(master_priv->sarea_priv->last_frame);
ADVANCE_RING();
}
@ -1494,11 +1505,13 @@ typedef struct {
} drm_radeon_tcl_prim_t;
static void radeon_cp_dispatch_vertex(struct drm_device * dev,
struct drm_file *file_priv,
struct drm_buf * buf,
drm_radeon_tcl_prim_t * prim)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start;
int numverts = (int)prim->numverts;
int nbox = sarea_priv->nbox;
@ -1539,13 +1552,14 @@ static void radeon_cp_dispatch_vertex(struct drm_device * dev,
} while (i < nbox);
}
static void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
static void radeon_cp_discard_buffer(struct drm_device * dev, struct drm_master *master, struct drm_buf * buf)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
struct drm_radeon_master_private *master_priv = master->driver_priv;
drm_radeon_buf_priv_t *buf_priv = buf->dev_private;
RING_LOCALS;
buf_priv->age = ++dev_priv->sarea_priv->last_dispatch;
buf_priv->age = ++master_priv->sarea_priv->last_dispatch;
/* Emit the vertex buffer age */
BEGIN_RING(2);
@ -1590,12 +1604,14 @@ static void radeon_cp_dispatch_indirect(struct drm_device * dev,
}
}
static void radeon_cp_dispatch_indices(struct drm_device * dev,
static void radeon_cp_dispatch_indices(struct drm_device *dev,
struct drm_master *master,
struct drm_buf * elt_buf,
drm_radeon_tcl_prim_t * prim)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
struct drm_radeon_master_private *master_priv = master->driver_priv;
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
int offset = dev_priv->gart_buffers_offset + prim->offset;
u32 *data;
int dwords;
@ -1870,7 +1886,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev,
ADVANCE_RING();
COMMIT_RING();
radeon_cp_discard_buffer(dev, buf);
radeon_cp_discard_buffer(dev, file_priv->master, buf);
/* Update the input parameters for next time */
image->y += height;
@ -2120,7 +2136,8 @@ static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_fi
static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
drm_radeon_clear_t *clear = data;
drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
DRM_DEBUG("\n");
@ -2136,7 +2153,7 @@ static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *
sarea_priv->nbox * sizeof(depth_boxes[0])))
return -EFAULT;
radeon_cp_dispatch_clear(dev, clear, depth_boxes);
radeon_cp_dispatch_clear(dev, file_priv->master, clear, depth_boxes);
COMMIT_RING();
return 0;
@ -2144,9 +2161,10 @@ static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *
/* Not sure why this isn't set all the time:
*/
static int radeon_do_init_pageflip(struct drm_device * dev)
static int radeon_do_init_pageflip(struct drm_device * dev, struct drm_master *master)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
struct drm_radeon_master_private *master_priv = master->driver_priv;
RING_LOCALS;
DRM_DEBUG("\n");
@ -2163,8 +2181,8 @@ static int radeon_do_init_pageflip(struct drm_device * dev)
dev_priv->page_flipping = 1;
if (dev_priv->sarea_priv->pfCurrentPage != 1)
dev_priv->sarea_priv->pfCurrentPage = 0;
if (master_priv->sarea_priv->pfCurrentPage != 1)
master_priv->sarea_priv->pfCurrentPage = 0;
return 0;
}
@ -2182,9 +2200,9 @@ static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *f
RING_SPACE_TEST_WITH_RETURN(dev_priv);
if (!dev_priv->page_flipping)
radeon_do_init_pageflip(dev);
radeon_do_init_pageflip(dev, file_priv->master);
radeon_cp_dispatch_flip(dev);
radeon_cp_dispatch_flip(dev, file_priv->master);
COMMIT_RING();
return 0;
@ -2193,7 +2211,9 @@ static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *f
static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv;
DRM_DEBUG("\n");
LOCK_TEST_WITH_RETURN(dev, file_priv);
@ -2203,8 +2223,8 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f
if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS)
sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS;
radeon_cp_dispatch_swap(dev);
dev_priv->sarea_priv->ctx_owner = 0;
radeon_cp_dispatch_swap(dev, file_priv->master);
sarea_priv->ctx_owner = 0;
COMMIT_RING();
return 0;
@ -2213,6 +2233,7 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f
static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
drm_radeon_sarea_t *sarea_priv;
struct drm_device_dma *dma = dev->dma;
struct drm_buf *buf;
@ -2226,7 +2247,7 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file
return -EINVAL;
}
sarea_priv = dev_priv->sarea_priv;
sarea_priv = master_priv->sarea_priv;
DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n",
DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard);
@ -2280,13 +2301,13 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file
prim.finish = vertex->count; /* unused */
prim.prim = vertex->prim;
prim.numverts = vertex->count;
prim.vc_format = dev_priv->sarea_priv->vc_format;
prim.vc_format = sarea_priv->vc_format;
radeon_cp_dispatch_vertex(dev, buf, &prim);
radeon_cp_dispatch_vertex(dev, file_priv, buf, &prim);
}
if (vertex->discard) {
radeon_cp_discard_buffer(dev, buf);
radeon_cp_discard_buffer(dev, file_priv->master, buf);
}
COMMIT_RING();
@ -2296,6 +2317,7 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file
static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
drm_radeon_sarea_t *sarea_priv;
struct drm_device_dma *dma = dev->dma;
struct drm_buf *buf;
@ -2309,7 +2331,7 @@ static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
sarea_priv = dev_priv->sarea_priv;
sarea_priv = master_priv->sarea_priv;
DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n",
DRM_CURRENTPID, elts->idx, elts->start, elts->end,
@ -2376,11 +2398,11 @@ static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file
prim.prim = elts->prim;
prim.offset = 0; /* offset from start of dma buffers */
prim.numverts = RADEON_MAX_VB_VERTS; /* duh */
prim.vc_format = dev_priv->sarea_priv->vc_format;
prim.vc_format = sarea_priv->vc_format;
radeon_cp_dispatch_indices(dev, buf, &prim);
radeon_cp_dispatch_indices(dev, file_priv->master, buf, &prim);
if (elts->discard) {
radeon_cp_discard_buffer(dev, buf);
radeon_cp_discard_buffer(dev, file_priv->master, buf);
}
COMMIT_RING();
@ -2496,7 +2518,7 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil
*/
radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end);
if (indirect->discard) {
radeon_cp_discard_buffer(dev, buf);
radeon_cp_discard_buffer(dev, file_priv->master, buf);
}
COMMIT_RING();
@ -2506,6 +2528,7 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil
static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
drm_radeon_sarea_t *sarea_priv;
struct drm_device_dma *dma = dev->dma;
struct drm_buf *buf;
@ -2520,7 +2543,7 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file
return -EINVAL;
}
sarea_priv = dev_priv->sarea_priv;
sarea_priv = master_priv->sarea_priv;
DRM_DEBUG("pid=%d index=%d discard=%d\n",
DRM_CURRENTPID, vertex->idx, vertex->discard);
@ -2582,12 +2605,12 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file
tclprim.offset = prim.numverts * 64;
tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */
radeon_cp_dispatch_indices(dev, buf, &tclprim);
radeon_cp_dispatch_indices(dev, file_priv->master, buf, &tclprim);
} else {
tclprim.numverts = prim.numverts;
tclprim.offset = 0; /* not used */
radeon_cp_dispatch_vertex(dev, buf, &tclprim);
radeon_cp_dispatch_vertex(dev, file_priv, buf, &tclprim);
}
if (sarea_priv->nbox == 1)
@ -2595,7 +2618,7 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file
}
if (vertex->discard) {
radeon_cp_discard_buffer(dev, buf);
radeon_cp_discard_buffer(dev, file_priv->master, buf);
}
COMMIT_RING();
@ -2889,7 +2912,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
orig_nbox = cmdbuf->nbox;
if (dev_priv->microcode_version == UCODE_R300) {
if (dev_priv->chip_family >= CHIP_R300) {
int temp;
temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf);
@ -2949,7 +2972,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file
goto err;
}
radeon_cp_discard_buffer(dev, buf);
radeon_cp_discard_buffer(dev, file_priv->master, buf);
break;
case RADEON_CMD_PACKET3:
@ -3110,6 +3133,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil
static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv;
drm_radeon_setparam_t *sp = data;
struct drm_radeon_driver_file_fields *radeon_priv;
@ -3129,14 +3153,14 @@ static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_fil
DRM_DEBUG("color tiling disabled\n");
dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO;
dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO;
if (dev_priv->sarea_priv)
dev_priv->sarea_priv->tiling_enabled = 0;
if (master_priv->sarea_priv)
master_priv->sarea_priv->tiling_enabled = 0;
} else if (sp->value == 1) {
DRM_DEBUG("color tiling enabled\n");
dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO;
dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO;
if (dev_priv->sarea_priv)
dev_priv->sarea_priv->tiling_enabled = 1;
if (master_priv->sarea_priv)
master_priv->sarea_priv->tiling_enabled = 1;
}
break;
case RADEON_SETPARAM_PCIGART_LOCATION:
@ -3183,14 +3207,6 @@ void radeon_driver_preclose(struct drm_device *dev,
void radeon_driver_lastclose(struct drm_device *dev)
{
if (dev->dev_private) {
drm_radeon_private_t *dev_priv = dev->dev_private;
if (dev_priv->sarea_priv &&
dev_priv->sarea_priv->pfCurrentPage != 0)
radeon_cp_dispatch_flip(dev);
}
radeon_do_release(dev);
}
@ -3251,7 +3267,18 @@ struct drm_ioctl_desc radeon_ioctls[] = {
DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH)
DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_INFO, radeon_gem_info_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_CREATE, radeon_gem_create_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_MMAP, radeon_gem_mmap_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_PIN, radeon_gem_pin_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_UNPIN, radeon_gem_unpin_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_PREAD, radeon_gem_pread_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_PWRITE, radeon_gem_pwrite_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_DOMAIN, radeon_gem_set_domain_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_INDIRECT, radeon_gem_indirect_ioctl, DRM_AUTH),
};
int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);