Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 1178 → Rev 1179

/drivers/video/drm/radeon/radeon_drm.h
File deleted
/drivers/video/drm/radeon/atikms.lds
20,11 → 20,21
*(.data)
}
 
.reloc ALIGN(__section_alignment__) :
.bss ALIGN(__section_alignment__):
{
*(.reloc)
*(.bss)
*(COMMON)
}
 
/DISCARD/ :
{
*(.debug$S)
*(.debug$T)
*(.debug$F)
*(.drectve)
*(.edata)
}
 
.idata ALIGN(__section_alignment__):
{
SORT(*)(.idata$2)
37,19 → 47,10
SORT(*)(.idata$7)
}
 
.bss ALIGN(__section_alignment__):
.reloc ALIGN(__section_alignment__) :
{
*(.bss)
*(COMMON)
*(.reloc)
}
 
/DISCARD/ :
{
*(.debug$S)
*(.debug$T)
*(.debug$F)
*(.drectve)
*(.edata)
}
}
 
/drivers/video/drm/radeon/atom.c
22,12 → 22,9
* Author: Stanislaw Skowronek
*/
 
//#include <linux/module.h>
//#include <linux/sched.h>
#include <linux/module.h>
#include <linux/sched.h>
 
#include <types.h>
#include <syscall.h>
 
#define ATOM_DEBUG
 
#include "atom.h"
1164,9 → 1161,6
 
int atom_asic_init(struct atom_context *ctx)
{
 
dbgprintf("%s\n",__FUNCTION__);
 
int hwi = CU16(ctx->data_table + ATOM_DATA_FWI_PTR);
uint32_t ps[16];
memset(ps, 0, 64);
/drivers/video/drm/radeon/atom.h
25,7 → 25,7
#ifndef ATOM_H
#define ATOM_H
 
#include <types.h>
#include <linux/types.h>
#include "drmP.h"
 
#define ATOM_BIOS_MAGIC 0xAA55
/drivers/video/drm/radeon/atombios.h
2374,6 → 2374,17
ATOM_MODE_TIMING aModeTimings[MAX_SUPPORTED_TV_TIMING];
} ATOM_ANALOG_TV_INFO;
 
#define MAX_SUPPORTED_TV_TIMING_V1_2 3
 
typedef struct _ATOM_ANALOG_TV_INFO_V1_2 {
ATOM_COMMON_TABLE_HEADER sHeader;
UCHAR ucTV_SupportedStandard;
UCHAR ucTV_BootUpDefaultStandard;
UCHAR ucExt_TV_ASIC_ID;
UCHAR ucExt_TV_ASIC_SlaveAddr;
ATOM_DTD_FORMAT aModeTimings[MAX_SUPPORTED_TV_TIMING];
} ATOM_ANALOG_TV_INFO_V1_2;
 
/**************************************************************************/
/* VRAM usage and their defintions */
 
/drivers/video/drm/radeon/atombios_crtc.c
23,14 → 23,159
* Authors: Dave Airlie
* Alex Deucher
*/
#include <drmP.h>
#include <drm_crtc_helper.h>
#include "radeon_drm.h"
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include <drm/radeon_drm.h>
#include "radeon_fixed.h"
#include "radeon.h"
#include "atom.h"
#include "atom-bits.h"
 
/* evil but including atombios.h is much worse */
bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing,
int32_t *pixel_clock);
static void atombios_overscan_setup(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
SET_CRTC_OVERSCAN_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
int a1, a2;
 
memset(&args, 0, sizeof(args));
 
args.usOverscanRight = 0;
args.usOverscanLeft = 0;
args.usOverscanBottom = 0;
args.usOverscanTop = 0;
args.ucCRTC = radeon_crtc->crtc_id;
 
switch (radeon_crtc->rmx_type) {
case RMX_CENTER:
args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
break;
case RMX_ASPECT:
a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay;
a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay;
 
if (a1 > a2) {
args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
} else if (a2 > a1) {
args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
}
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
break;
case RMX_FULL:
default:
args.usOverscanRight = 0;
args.usOverscanLeft = 0;
args.usOverscanBottom = 0;
args.usOverscanTop = 0;
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
break;
}
}
 
static void atombios_scaler_setup(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
ENABLE_SCALER_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
 
/* fixme - fill in enc_priv for atom dac */
enum radeon_tv_std tv_std = TV_STD_NTSC;
bool is_tv = false, is_cv = false;
struct drm_encoder *encoder;
 
if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id)
return;
 
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
/* find tv std */
if (encoder->crtc == crtc) {
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
tv_std = tv_dac->tv_std;
is_tv = true;
}
}
}
 
memset(&args, 0, sizeof(args));
 
args.ucScaler = radeon_crtc->crtc_id;
 
if (is_tv) {
switch (tv_std) {
case TV_STD_NTSC:
default:
args.ucTVStandard = ATOM_TV_NTSC;
break;
case TV_STD_PAL:
args.ucTVStandard = ATOM_TV_PAL;
break;
case TV_STD_PAL_M:
args.ucTVStandard = ATOM_TV_PALM;
break;
case TV_STD_PAL_60:
args.ucTVStandard = ATOM_TV_PAL60;
break;
case TV_STD_NTSC_J:
args.ucTVStandard = ATOM_TV_NTSCJ;
break;
case TV_STD_SCART_PAL:
args.ucTVStandard = ATOM_TV_PAL; /* ??? */
break;
case TV_STD_SECAM:
args.ucTVStandard = ATOM_TV_SECAM;
break;
case TV_STD_PAL_CN:
args.ucTVStandard = ATOM_TV_PALCN;
break;
}
args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
} else if (is_cv) {
args.ucTVStandard = ATOM_TV_CV;
args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
} else {
switch (radeon_crtc->rmx_type) {
case RMX_FULL:
args.ucEnable = ATOM_SCALER_EXPANSION;
break;
case RMX_CENTER:
args.ucEnable = ATOM_SCALER_CENTER;
break;
case RMX_ASPECT:
args.ucEnable = ATOM_SCALER_EXPANSION;
break;
default:
if (ASIC_IS_AVIVO(rdev))
args.ucEnable = ATOM_SCALER_DISABLE;
else
args.ucEnable = ATOM_SCALER_CENTER;
break;
}
}
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
if ((is_tv || is_cv)
&& rdev->family >= CHIP_RV515 && rdev->family <= CHIP_R580) {
atom_rv515_force_tv_scaler(rdev, radeon_crtc);
}
}
 
static void atombios_lock_crtc(struct drm_crtc *crtc, int lock)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
203,6 → 348,12
if (ASIC_IS_AVIVO(rdev)) {
uint32_t ss_cntl;
 
if ((rdev->family == CHIP_RS600) ||
(rdev->family == CHIP_RS690) ||
(rdev->family == CHIP_RS740))
pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV |
RADEON_PLL_PREFER_CLOSEST_LOWER);
 
if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */
pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
else
238,6 → 389,7
pll_flags |= RADEON_PLL_USE_REF_DIV;
}
radeon_encoder = to_radeon_encoder(encoder);
break;
}
}
 
321,13 → 473,15
struct drm_gem_object *obj;
struct drm_radeon_gem_object *obj_priv;
uint64_t fb_location;
uint32_t fb_format, fb_pitch_pixels;
uint32_t fb_format, fb_pitch_pixels, tiling_flags;
 
ENTRY();
 
if (!crtc->fb)
return -EINVAL;
 
dbgprintf("x = %d y = %d width = %d height = %d\n",
x, y, crtc->fb->width, crtc->fb->height);
dbgprintf("hdisplay = %d\n", crtc->mode.hdisplay);
 
radeon_fb = to_radeon_framebuffer(crtc->fb);
 
obj = radeon_fb->obj;
340,9 → 494,14
fb_location = 0; //rdev->mc.vram_location;
 
dbgprintf("fb_location %x\n", fb_location);
dbgprintf("bpp %x\n", crtc->fb->bits_per_pixel);
dbgprintf("bpp %d\n", crtc->fb->bits_per_pixel);
 
switch (crtc->fb->bits_per_pixel) {
case 8:
fb_format =
AVIVO_D1GRPH_CONTROL_DEPTH_8BPP |
AVIVO_D1GRPH_CONTROL_8BPP_INDEXED;
break;
case 15:
fb_format =
AVIVO_D1GRPH_CONTROL_DEPTH_16BPP |
365,7 → 524,14
return -EINVAL;
}
 
/* TODO tiling */
// radeon_object_get_tiling_flags(obj->driver_private,
// &tiling_flags, NULL);
// if (tiling_flags & RADEON_TILING_MACRO)
// fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE;
 
// if (tiling_flags & RADEON_TILING_MICRO)
// fb_format |= AVIVO_D1GRPH_TILED;
 
if (radeon_crtc->crtc_id == 0)
WREG32(AVIVO_D1VGA_CONTROL, 0);
else
403,10 → 569,9
WREG32(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, 0);
 
if (old_fb && old_fb != crtc->fb) {
radeon_fb = to_radeon_framebuffer(old_fb);
// radeon_fb = to_radeon_framebuffer(old_fb);
// radeon_gem_object_unpin(radeon_fb->obj);
}
LEAVE();
return 0;
}
 
420,18 → 585,41
struct radeon_device *rdev = dev->dev_private;
struct drm_encoder *encoder;
SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION crtc_timing;
int need_tv_timings = 0;
bool ret;
 
ENTRY();
 
/* TODO color tiling */
memset(&crtc_timing, 0, sizeof(crtc_timing));
 
/* TODO tv */
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
/* find tv std */
if (encoder->crtc == crtc) {
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 
if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
if (tv_dac) {
if (tv_dac->tv_std == TV_STD_NTSC ||
tv_dac->tv_std == TV_STD_NTSC_J ||
tv_dac->tv_std == TV_STD_PAL_M)
need_tv_timings = 1;
else
need_tv_timings = 2;
break;
}
}
}
}
 
crtc_timing.ucCRTC = radeon_crtc->crtc_id;
if (need_tv_timings) {
ret = radeon_atom_get_tv_timings(rdev, need_tv_timings - 1,
&crtc_timing, &adjusted_mode->clock);
if (ret == false)
need_tv_timings = 0;
}
 
if (!need_tv_timings) {
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;
458,6 → 646,7
 
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
crtc_timing.susModeMiscInfo.usAccess |= ATOM_DOUBLE_CLOCK_MODE;
}
 
atombios_crtc_set_pll(crtc, adjusted_mode);
atombios_crtc_set_timing(crtc, &crtc_timing);
519,8 → 708,9
radeon_crtc_set_base(crtc, x, y, old_fb);
radeon_legacy_atom_set_surface(crtc);
}
LEAVE();
 
atombios_overscan_setup(crtc, mode, adjusted_mode);
atombios_scaler_setup(crtc);
radeon_bandwidth_update(rdev);
return 0;
}
 
528,6 → 718,8
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
return false;
return true;
}
 
560,150 → 752,3
AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL;
drm_crtc_helper_add(&radeon_crtc->base, &atombios_helper_funcs);
}
 
void radeon_init_disp_bw_avivo(struct drm_device *dev,
struct drm_display_mode *mode1,
uint32_t pixel_bytes1,
struct drm_display_mode *mode2,
uint32_t pixel_bytes2)
{
struct radeon_device *rdev = dev->dev_private;
fixed20_12 min_mem_eff;
fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff;
fixed20_12 sclk_ff, mclk_ff;
uint32_t dc_lb_memory_split, temp;
 
min_mem_eff.full = rfixed_const_8(0);
if (rdev->disp_priority == 2) {
uint32_t mc_init_misc_lat_timer = 0;
if (rdev->family == CHIP_RV515)
mc_init_misc_lat_timer =
RREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER);
else if (rdev->family == CHIP_RS690)
mc_init_misc_lat_timer =
RREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER);
 
mc_init_misc_lat_timer &=
~(R300_MC_DISP1R_INIT_LAT_MASK <<
R300_MC_DISP1R_INIT_LAT_SHIFT);
mc_init_misc_lat_timer &=
~(R300_MC_DISP0R_INIT_LAT_MASK <<
R300_MC_DISP0R_INIT_LAT_SHIFT);
 
if (mode2)
mc_init_misc_lat_timer |=
(1 << R300_MC_DISP1R_INIT_LAT_SHIFT);
if (mode1)
mc_init_misc_lat_timer |=
(1 << R300_MC_DISP0R_INIT_LAT_SHIFT);
 
if (rdev->family == CHIP_RV515)
WREG32_MC(RV515_MC_INIT_MISC_LAT_TIMER,
mc_init_misc_lat_timer);
else if (rdev->family == CHIP_RS690)
WREG32_MC(RS690_MC_INIT_MISC_LAT_TIMER,
mc_init_misc_lat_timer);
}
 
/*
* determine is there is enough bw for current mode
*/
temp_ff.full = rfixed_const(100);
mclk_ff.full = rfixed_const(rdev->clock.default_mclk);
mclk_ff.full = rfixed_div(mclk_ff, temp_ff);
sclk_ff.full = rfixed_const(rdev->clock.default_sclk);
sclk_ff.full = rfixed_div(sclk_ff, temp_ff);
 
temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1);
temp_ff.full = rfixed_const(temp);
mem_bw.full = rfixed_mul(mclk_ff, temp_ff);
mem_bw.full = rfixed_mul(mem_bw, min_mem_eff);
 
pix_clk.full = 0;
pix_clk2.full = 0;
peak_disp_bw.full = 0;
if (mode1) {
temp_ff.full = rfixed_const(1000);
pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */
pix_clk.full = rfixed_div(pix_clk, temp_ff);
temp_ff.full = rfixed_const(pixel_bytes1);
peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff);
}
if (mode2) {
temp_ff.full = rfixed_const(1000);
pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */
pix_clk2.full = rfixed_div(pix_clk2, temp_ff);
temp_ff.full = rfixed_const(pixel_bytes2);
peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff);
}
 
if (peak_disp_bw.full >= mem_bw.full) {
DRM_ERROR
("You may not have enough display bandwidth for current mode\n"
"If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
printk("peak disp bw %d, mem_bw %d\n",
rfixed_trunc(peak_disp_bw), rfixed_trunc(mem_bw));
}
 
/*
* Line Buffer Setup
* There is a single line buffer shared by both display controllers.
* DC_LB_MEMORY_SPLIT controls how that line buffer is shared between the display
* controllers. The paritioning can either be done manually or via one of four
* preset allocations specified in bits 1:0:
* 0 - line buffer is divided in half and shared between each display controller
* 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4
* 2 - D1 gets the whole buffer
* 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4
* Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual allocation mode.
* In manual allocation mode, D1 always starts at 0, D1 end/2 is specified in bits
* 14:4; D2 allocation follows D1.
*/
 
/* is auto or manual better ? */
dc_lb_memory_split =
RREG32(AVIVO_DC_LB_MEMORY_SPLIT) & ~AVIVO_DC_LB_MEMORY_SPLIT_MASK;
dc_lb_memory_split &= ~AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
#if 1
/* auto */
if (mode1 && mode2) {
if (mode1->hdisplay > mode2->hdisplay) {
if (mode1->hdisplay > 2560)
dc_lb_memory_split |=
AVIVO_DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;
else
dc_lb_memory_split |=
AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
} else if (mode2->hdisplay > mode1->hdisplay) {
if (mode2->hdisplay > 2560)
dc_lb_memory_split |=
AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
else
dc_lb_memory_split |=
AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
} else
dc_lb_memory_split |=
AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
} else if (mode1) {
dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_ONLY;
} else if (mode2) {
dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
}
#else
/* manual */
dc_lb_memory_split |= AVIVO_DC_LB_MEMORY_SPLIT_SHIFT_MODE;
dc_lb_memory_split &=
~(AVIVO_DC_LB_DISP1_END_ADR_MASK <<
AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
if (mode1) {
dc_lb_memory_split |=
((((mode1->hdisplay / 2) + 64) & AVIVO_DC_LB_DISP1_END_ADR_MASK)
<< AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
} else if (mode2) {
dc_lb_memory_split |= (0 << AVIVO_DC_LB_DISP1_END_ADR_SHIFT);
}
#endif
WREG32(AVIVO_DC_LB_MEMORY_SPLIT, dc_lb_memory_split);
}
 
 
/drivers/video/drm/radeon/avivod.h
0,0 → 1,69
/*
* Copyright 2009 Advanced Micro Devices, Inc.
* Copyright 2009 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
* Jerome Glisse
*/
#ifndef AVIVOD_H
#define AVIVOD_H
 
 
#define D1CRTC_CONTROL 0x6080
#define CRTC_EN (1 << 0)
#define D1CRTC_UPDATE_LOCK 0x60E8
#define D1GRPH_PRIMARY_SURFACE_ADDRESS 0x6110
#define D1GRPH_SECONDARY_SURFACE_ADDRESS 0x6118
 
#define D2CRTC_CONTROL 0x6880
#define D2CRTC_UPDATE_LOCK 0x68E8
#define D2GRPH_PRIMARY_SURFACE_ADDRESS 0x6910
#define D2GRPH_SECONDARY_SURFACE_ADDRESS 0x6918
 
#define D1VGA_CONTROL 0x0330
#define DVGA_CONTROL_MODE_ENABLE (1 << 0)
#define DVGA_CONTROL_TIMING_SELECT (1 << 8)
#define DVGA_CONTROL_SYNC_POLARITY_SELECT (1 << 9)
#define DVGA_CONTROL_OVERSCAN_TIMING_SELECT (1 << 10)
#define DVGA_CONTROL_OVERSCAN_COLOR_EN (1 << 16)
#define DVGA_CONTROL_ROTATE (1 << 24)
#define D2VGA_CONTROL 0x0338
 
#define VGA_HDP_CONTROL 0x328
#define VGA_MEM_PAGE_SELECT_EN (1 << 0)
#define VGA_MEMORY_DISABLE (1 << 4)
#define VGA_RBBM_LOCK_DISABLE (1 << 8)
#define VGA_SOFT_RESET (1 << 16)
#define VGA_MEMORY_BASE_ADDRESS 0x0310
#define VGA_RENDER_CONTROL 0x0300
#define VGA_VSTATUS_CNTL_MASK 0x00030000
 
/* AVIVO disable VGA rendering */
static inline void radeon_avivo_vga_render_disable(struct radeon_device *rdev)
{
u32 vga_render;
vga_render = RREG32(VGA_RENDER_CONTROL);
vga_render &= ~VGA_VSTATUS_CNTL_MASK;
WREG32(VGA_RENDER_CONTROL, vga_render);
}
 
#endif
/drivers/video/drm/radeon/display.h
0,0 → 1,25
 
 
typedef struct
{
u32_t width;
u32_t height;
u32_t bpp;
 
u32_t lfb;
u32_t pci_fb;
u32_t gpu_fb;
u32_t fb_object;
 
struct drm_display_mode *mode;
cursor_t *cursor;
 
int (*set_cursor)();
int (*show_cursor)();
int (*hide_cursor)();
int (*move_cursor)();
 
int (*copy)();
int (*blit)();
 
}display_t;
/drivers/video/drm/radeon/makefile
4,7 → 4,6
CFLAGS = -c -O2 -fomit-frame-pointer -fno-builtin-printf
LDFLAGS = -nostdlib -shared -s -Map atikms.map --image-base 0 --file-alignment 512 --section-alignment 4096
 
 
DRM_TOPDIR = $(CURDIR)/..
DRM_INCLUDES = $(DRM_TOPDIR)/include
 
14,16 → 13,16
 
NAME:= atikms
 
INCLUDES = -I $(DRM_INCLUDES) -I $(DRM_INCLUDES)/ttm
INCLUDES = -I $(DRM_INCLUDES) -I $(DRM_INCLUDES)/linux -I $(DRM_INCLUDES)/drm
 
HFILES:= $(DRM_INCLUDES)/types.h \
$(DRM_INCLUDES)/list.h \
HFILES:= $(DRM_INCLUDES)/linux/types.h \
$(DRM_INCLUDES)/linux/list.h \
$(DRM_INCLUDES)/pci.h \
$(DRM_INCLUDES)/drm.h \
$(DRM_INCLUDES)/drmP.h \
$(DRM_INCLUDES)/drm/drmP.h \
$(DRM_INCLUDES)/drm_edid.h \
$(DRM_INCLUDES)/drm_crtc.h \
$(DRM_INCLUDES)/drm_mode.h \
$(DRM_INCLUDES)/drm/drm_crtc.h \
$(DRM_INCLUDES)/drm/drm_mode.h \
$(DRM_INCLUDES)/drm_mm.h \
atom.h \
radeon.h \
36,6 → 35,7
$(DRM_TOPDIR)/drm_modes.c \
$(DRM_TOPDIR)/drm_crtc.c \
$(DRM_TOPDIR)/drm_crtc_helper.c \
$(DRM_TOPDIR)/drm_fb_helper.c \
$(DRM_TOPDIR)/i2c/i2c-core.c \
$(DRM_TOPDIR)/i2c/i2c-algo-bit.c \
$(DRM_TOPDIR)/idr.c \
52,11 → 52,14
radeon_combios.c \
radeon_legacy_crtc.c \
radeon_legacy_encoders.c \
radeon_legacy_tv.c \
radeon_display.c \
radeon_cursor.c \
radeon_object.c \
radeon_gart.c \
radeon_ring.c \
r100.c \
r200.c \
r300.c \
r420.c \
rv515.c \
71,8 → 74,8
SRC_DEP:=
 
 
NAME_OBJS = $(patsubst %.s, %.obj, $(patsubst %.asm, %.obj,\
$(patsubst %.c, %.obj, $(NAME_SRC))))
NAME_OBJS = $(patsubst %.s, %.o, $(patsubst %.asm, %.o,\
$(patsubst %.c, %.o, $(NAME_SRC))))
 
 
 
82,5 → 85,5
ld -L$(LIBPATH) $(LDFLAGS) -T atikms.lds -o $@ $(NAME_OBJS) vsprintf.obj icompute.obj $(LIBS)
 
 
%.obj : %.c $(HFILES) Makefile
%.o : %.c $(HFILES) Makefile
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ -c $<
/drivers/video/drm/radeon/r100.c
25,7 → 25,7
* Alex Deucher
* Jerome Glisse
*/
//#include <linux/seq_file.h>
#include <linux/seq_file.h>
#include "drmP.h"
#include "drm.h"
#include "radeon_drm.h"
32,12 → 32,16
#include "radeon_microcode.h"
#include "radeon_reg.h"
#include "radeon.h"
#include "r100d.h"
 
#include "r100_reg_safe.h"
#include "rn50_reg_safe.h"
/* This files gather functions specifics to:
* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
*
* Some of these functions might be used by newer ASICs.
*/
int r200_init(struct radeon_device *rdev);
void r100_hdp_reset(struct radeon_device *rdev);
void r100_gpu_init(struct radeon_device *rdev);
int r100_gui_wait_for_idle(struct radeon_device *rdev);
46,6 → 50,7
void r100_gpu_wait_for_vsync2(struct radeon_device *rdev);
int r100_debugfs_mc_info_init(struct radeon_device *rdev);
 
 
/*
* PCI GART
*/
57,23 → 62,28
* could end up in wrong address. */
}
 
int r100_pci_gart_enable(struct radeon_device *rdev)
int r100_pci_gart_init(struct radeon_device *rdev)
{
uint32_t tmp;
int r;
 
if (rdev->gart.table.ram.ptr) {
WARN(1, "R100 PCI GART already initialized.\n");
return 0;
}
/* Initialize common gart structure */
r = radeon_gart_init(rdev);
if (r) {
if (r)
return r;
}
if (rdev->gart.table.ram.ptr == NULL) {
rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
r = radeon_gart_table_ram_alloc(rdev);
if (r) {
return r;
rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush;
rdev->asic->gart_set_page = &r100_pci_gart_set_page;
return radeon_gart_table_ram_alloc(rdev);
}
}
 
int r100_pci_gart_enable(struct radeon_device *rdev)
{
uint32_t tmp;
 
/* discard memory request outside of configured range */
tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS;
WREG32(RADEON_AIC_CNTL, tmp);
104,24 → 114,21
WREG32(RADEON_AIC_HI_ADDR, 0);
}
 
 
int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
{
if (i < 0 || i > rdev->gart.num_gpu_pages) {
return -EINVAL;
}
rdev->gart.table.ram.ptr[i] = cpu_to_le32((uint32_t)addr);
rdev->gart.table.ram.ptr[i] = cpu_to_le32(lower_32_bits(addr));
return 0;
}
 
int r100_gart_enable(struct radeon_device *rdev)
void r100_pci_gart_fini(struct radeon_device *rdev)
{
if (rdev->flags & RADEON_IS_AGP) {
r100_pci_gart_disable(rdev);
return 0;
radeon_gart_table_ram_free(rdev);
radeon_gart_fini(rdev);
}
return r100_pci_gart_enable(rdev);
}
 
 
/*
173,8 → 180,12
DRM_ERROR("Failed to register debugfs file for R100 MC !\n");
}
/* Write VRAM size in case we are limiting it */
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size);
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1;
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
/* Novell bug 204882 for RN50/M6/M7 with 8/16/32MB VRAM,
* if the aperture is 64MB but we have 32MB VRAM
* we report only 32MB VRAM but we have to set MC_FB_LOCATION
* to 64MB, otherwise the gpu accidentially dies */
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16);
tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16);
WREG32(RADEON_MC_FB_LOCATION, tmp);
215,18 → 226,7
r100_pci_gart_disable(rdev);
 
/* Setup GPU memory space */
rdev->mc.vram_location = 0xFFFFFFFFUL;
rdev->mc.gtt_location = 0xFFFFFFFFUL;
if (rdev->flags & RADEON_IS_AGP) {
r = radeon_agp_init(rdev);
if (r) {
printk(KERN_WARNING "[drm] Disabling AGP\n");
rdev->flags &= ~RADEON_IS_AGP;
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
} else {
rdev->mc.gtt_location = rdev->mc.agp_base;
}
}
r = radeon_mc_setup(rdev);
if (r) {
return r;
244,11 → 244,17
 
void r100_mc_fini(struct radeon_device *rdev)
{
r100_pci_gart_disable(rdev);
// radeon_gart_table_ram_free(rdev);
// radeon_gart_fini(rdev);
}
 
u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc)
{
if (crtc == 0)
return RREG32(RADEON_CRTC_CRNT_FRAME);
else
return RREG32(RADEON_CRTC2_CRNT_FRAME);
}
 
 
/*
* Fence emission
*/
297,14 → 303,21
return r;
}
}
WREG32(0x774, rdev->wb.gpu_addr);
WREG32(0x70C, rdev->wb.gpu_addr + 1024);
WREG32(0x770, 0xff);
WREG32(R_000774_SCRATCH_ADDR, rdev->wb.gpu_addr);
WREG32(R_00070C_CP_RB_RPTR_ADDR,
S_00070C_RB_RPTR_ADDR((rdev->wb.gpu_addr + 1024) >> 2));
WREG32(R_000770_SCRATCH_UMSK, 0xff);
return 0;
}
 
void r100_wb_disable(struct radeon_device *rdev)
{
WREG32(R_000770_SCRATCH_UMSK, 0);
}
 
void r100_wb_fini(struct radeon_device *rdev)
{
r100_wb_disable(rdev);
if (rdev->wb.wb_obj) {
// radeon_object_kunmap(rdev->wb.wb_obj);
// radeon_object_unpin(rdev->wb.wb_obj);
314,7 → 327,6
}
}
 
 
int r100_copy_blit(struct radeon_device *rdev,
uint64_t src_offset,
uint64_t dst_offset,
393,6 → 405,21
/*
* CP
*/
static int r100_cp_wait_for_idle(struct radeon_device *rdev)
{
unsigned i;
u32 tmp;
 
for (i = 0; i < rdev->usec_timeout; i++) {
tmp = RREG32(R_000E40_RBBM_STATUS);
if (!G_000E40_CP_CMDSTRM_BUSY(tmp)) {
return 0;
}
udelay(1);
}
return -1;
}
 
void r100_ring_start(struct radeon_device *rdev)
{
int r;
483,6 → 510,12
}
}
 
static int r100_cp_init_microcode(struct radeon_device *rdev)
{
return 0;
}
 
 
int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
{
unsigned rb_bufsz;
517,6 → 550,15
} else {
DRM_INFO("radeon: cp idle (0x%08X)\n", tmp);
}
 
if (!rdev->me_fw) {
r = r100_cp_init_microcode(rdev);
if (r) {
DRM_ERROR("Failed to load firmware!\n");
return r;
}
}
 
/* Align ring size */
rb_bufsz = drm_order(ring_size / 8);
ring_size = (1 << (rb_bufsz + 1)) * 4;
588,12 → 630,13
return 0;
}
 
 
void r100_cp_fini(struct radeon_device *rdev)
{
if (r100_cp_wait_for_idle(rdev)) {
DRM_ERROR("Wait for CP idle timeout, shutting down CP.\n");
}
/* Disable ring */
rdev->cp.ready = false;
WREG32(RADEON_CP_CSQ_CNTL, 0);
r100_cp_disable(rdev);
radeon_ring_fini(rdev);
DRM_INFO("radeon: cp finalized\n");
}
610,7 → 653,6
}
}
 
 
int r100_cp_reset(struct radeon_device *rdev)
{
uint32_t tmp;
617,9 → 659,8
bool reinit_cp;
int i;
 
dbgprintf("%s\n",__FUNCTION__);
ENTER();
 
 
reinit_cp = rdev->cp.ready;
rdev->cp.ready = false;
WREG32(RADEON_CP_CSQ_MODE, 0);
647,6 → 688,13
return -1;
}
 
void r100_cp_commit(struct radeon_device *rdev)
{
WREG32(RADEON_CP_RB_WPTR, rdev->cp.wptr);
(void)RREG32(RADEON_CP_RB_WPTR);
}
 
 
#if 0
/*
* CS functions
725,7 → 773,7
unsigned idx)
{
struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
uint32_t header = ib_chunk->kdata[idx];
uint32_t header;
 
if (idx >= ib_chunk->length_dw) {
DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
732,6 → 780,7
idx, ib_chunk->length_dw);
return -EINVAL;
}
header = ib_chunk->kdata[idx];
pkt->idx = idx;
pkt->type = CP_PACKET_GET_TYPE(header);
pkt->count = CP_PACKET_GET_COUNT(header);
759,6 → 808,102
}
 
/**
* r100_cs_packet_next_vline() - parse userspace VLINE packet
* @parser: parser structure holding parsing context.
*
* Userspace sends a special sequence for VLINE waits.
* PACKET0 - VLINE_START_END + value
* PACKET0 - WAIT_UNTIL +_value
* RELOC (P3) - crtc_id in reloc.
*
* This function parses this and relocates the VLINE START END
* and WAIT UNTIL packets to the correct crtc.
* It also detects a switched off crtc and nulls out the
* wait in that case.
*/
int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
{
struct radeon_cs_chunk *ib_chunk;
struct drm_mode_object *obj;
struct drm_crtc *crtc;
struct radeon_crtc *radeon_crtc;
struct radeon_cs_packet p3reloc, waitreloc;
int crtc_id;
int r;
uint32_t header, h_idx, reg;
 
ib_chunk = &p->chunks[p->chunk_ib_idx];
 
/* parse the wait until */
r = r100_cs_packet_parse(p, &waitreloc, p->idx);
if (r)
return r;
 
/* check its a wait until and only 1 count */
if (waitreloc.reg != RADEON_WAIT_UNTIL ||
waitreloc.count != 0) {
DRM_ERROR("vline wait had illegal wait until segment\n");
r = -EINVAL;
return r;
}
 
if (ib_chunk->kdata[waitreloc.idx + 1] != RADEON_WAIT_CRTC_VLINE) {
DRM_ERROR("vline wait had illegal wait until\n");
r = -EINVAL;
return r;
}
 
/* jump over the NOP */
r = r100_cs_packet_parse(p, &p3reloc, p->idx);
if (r)
return r;
 
h_idx = p->idx - 2;
p->idx += waitreloc.count;
p->idx += p3reloc.count;
 
header = ib_chunk->kdata[h_idx];
crtc_id = ib_chunk->kdata[h_idx + 5];
reg = ib_chunk->kdata[h_idx] >> 2;
mutex_lock(&p->rdev->ddev->mode_config.mutex);
obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);
if (!obj) {
DRM_ERROR("cannot find crtc %d\n", crtc_id);
r = -EINVAL;
goto out;
}
crtc = obj_to_crtc(obj);
radeon_crtc = to_radeon_crtc(crtc);
crtc_id = radeon_crtc->crtc_id;
 
if (!crtc->enabled) {
/* if the CRTC isn't enabled - we need to nop out the wait until */
ib_chunk->kdata[h_idx + 2] = PACKET2(0);
ib_chunk->kdata[h_idx + 3] = PACKET2(0);
} else if (crtc_id == 1) {
switch (reg) {
case AVIVO_D1MODE_VLINE_START_END:
header &= R300_CP_PACKET0_REG_MASK;
header |= AVIVO_D2MODE_VLINE_START_END >> 2;
break;
case RADEON_CRTC_GUI_TRIG_VLINE:
header &= R300_CP_PACKET0_REG_MASK;
header |= RADEON_CRTC2_GUI_TRIG_VLINE >> 2;
break;
default:
DRM_ERROR("unknown crtc reloc\n");
r = -EINVAL;
goto out;
}
ib_chunk->kdata[h_idx] = header;
ib_chunk->kdata[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1;
}
out:
mutex_unlock(&p->rdev->ddev->mode_config.mutex);
return r;
}
 
/**
* r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3
* @parser: parser structure holding parsing context.
* @data: pointer to relocation data
808,33 → 953,95
return 0;
}
 
static int r100_get_vtx_size(uint32_t vtx_fmt)
{
int vtx_size;
vtx_size = 2;
/* ordered according to bits in spec */
if (vtx_fmt & RADEON_SE_VTX_FMT_W0)
vtx_size++;
if (vtx_fmt & RADEON_SE_VTX_FMT_FPCOLOR)
vtx_size += 3;
if (vtx_fmt & RADEON_SE_VTX_FMT_FPALPHA)
vtx_size++;
if (vtx_fmt & RADEON_SE_VTX_FMT_PKCOLOR)
vtx_size++;
if (vtx_fmt & RADEON_SE_VTX_FMT_FPSPEC)
vtx_size += 3;
if (vtx_fmt & RADEON_SE_VTX_FMT_FPFOG)
vtx_size++;
if (vtx_fmt & RADEON_SE_VTX_FMT_PKSPEC)
vtx_size++;
if (vtx_fmt & RADEON_SE_VTX_FMT_ST0)
vtx_size += 2;
if (vtx_fmt & RADEON_SE_VTX_FMT_ST1)
vtx_size += 2;
if (vtx_fmt & RADEON_SE_VTX_FMT_Q1)
vtx_size++;
if (vtx_fmt & RADEON_SE_VTX_FMT_ST2)
vtx_size += 2;
if (vtx_fmt & RADEON_SE_VTX_FMT_Q2)
vtx_size++;
if (vtx_fmt & RADEON_SE_VTX_FMT_ST3)
vtx_size += 2;
if (vtx_fmt & RADEON_SE_VTX_FMT_Q3)
vtx_size++;
if (vtx_fmt & RADEON_SE_VTX_FMT_Q0)
vtx_size++;
/* blend weight */
if (vtx_fmt & (0x7 << 15))
vtx_size += (vtx_fmt >> 15) & 0x7;
if (vtx_fmt & RADEON_SE_VTX_FMT_N0)
vtx_size += 3;
if (vtx_fmt & RADEON_SE_VTX_FMT_XY1)
vtx_size += 2;
if (vtx_fmt & RADEON_SE_VTX_FMT_Z1)
vtx_size++;
if (vtx_fmt & RADEON_SE_VTX_FMT_W1)
vtx_size++;
if (vtx_fmt & RADEON_SE_VTX_FMT_N1)
vtx_size++;
if (vtx_fmt & RADEON_SE_VTX_FMT_Z)
vtx_size++;
return vtx_size;
}
 
static int r100_packet0_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt)
struct radeon_cs_packet *pkt,
unsigned idx, unsigned reg)
{
struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_reloc *reloc;
struct r100_cs_track *track;
volatile uint32_t *ib;
uint32_t tmp;
unsigned reg;
unsigned i;
unsigned idx;
bool onereg;
int r;
int i, face;
u32 tile_flags = 0;
 
ib = p->ib->ptr;
ib_chunk = &p->chunks[p->chunk_ib_idx];
idx = pkt->idx + 1;
reg = pkt->reg;
onereg = false;
if (CP_PACKET0_GET_ONE_REG_WR(ib_chunk->kdata[pkt->idx])) {
onereg = true;
track = (struct r100_cs_track *)p->track;
 
switch (reg) {
case RADEON_CRTC_GUI_TRIG_VLINE:
r = r100_cs_packet_parse_vline(p);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
switch (reg) {
break;
/* FIXME: only allow PACKET3 blit? easier to check for out of
* range access */
case RADEON_DST_PITCH_OFFSET:
case RADEON_SRC_PITCH_OFFSET:
r = r100_reloc_pitch_offset(p, pkt, idx, reg);
if (r)
return r;
break;
case RADEON_RB3D_DEPTHOFFSET:
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
842,39 → 1049,26
r100_cs_dump_packet(p, pkt);
return r;
}
tmp = ib_chunk->kdata[idx] & 0x003fffff;
tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp;
track->zb.robj = reloc->robj;
track->zb.offset = ib_chunk->kdata[idx];
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
break;
case RADEON_RB3D_DEPTHOFFSET:
case RADEON_RB3D_COLOROFFSET:
case R300_RB3D_COLOROFFSET0:
case R300_ZB_DEPTHOFFSET:
case R200_PP_TXOFFSET_0:
case R200_PP_TXOFFSET_1:
case R200_PP_TXOFFSET_2:
case R200_PP_TXOFFSET_3:
case R200_PP_TXOFFSET_4:
case R200_PP_TXOFFSET_5:
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
track->cb[0].robj = reloc->robj;
track->cb[0].offset = ib_chunk->kdata[idx];
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
break;
case RADEON_PP_TXOFFSET_0:
case RADEON_PP_TXOFFSET_1:
case RADEON_PP_TXOFFSET_2:
case R300_TX_OFFSET_0:
case R300_TX_OFFSET_0+4:
case R300_TX_OFFSET_0+8:
case R300_TX_OFFSET_0+12:
case R300_TX_OFFSET_0+16:
case R300_TX_OFFSET_0+20:
case R300_TX_OFFSET_0+24:
case R300_TX_OFFSET_0+28:
case R300_TX_OFFSET_0+32:
case R300_TX_OFFSET_0+36:
case R300_TX_OFFSET_0+40:
case R300_TX_OFFSET_0+44:
case R300_TX_OFFSET_0+48:
case R300_TX_OFFSET_0+52:
case R300_TX_OFFSET_0+56:
case R300_TX_OFFSET_0+60:
i = (reg - RADEON_PP_TXOFFSET_0) / 24;
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
883,16 → 1077,233
return r;
}
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
track->textures[i].robj = reloc->robj;
break;
case RADEON_PP_CUBIC_OFFSET_T0_0:
case RADEON_PP_CUBIC_OFFSET_T0_1:
case RADEON_PP_CUBIC_OFFSET_T0_2:
case RADEON_PP_CUBIC_OFFSET_T0_3:
case RADEON_PP_CUBIC_OFFSET_T0_4:
i = (reg - RADEON_PP_CUBIC_OFFSET_T0_0) / 4;
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
track->textures[0].cube_info[i].offset = ib_chunk->kdata[idx];
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
track->textures[0].cube_info[i].robj = reloc->robj;
break;
case RADEON_PP_CUBIC_OFFSET_T1_0:
case RADEON_PP_CUBIC_OFFSET_T1_1:
case RADEON_PP_CUBIC_OFFSET_T1_2:
case RADEON_PP_CUBIC_OFFSET_T1_3:
case RADEON_PP_CUBIC_OFFSET_T1_4:
i = (reg - RADEON_PP_CUBIC_OFFSET_T1_0) / 4;
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
track->textures[1].cube_info[i].offset = ib_chunk->kdata[idx];
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
track->textures[1].cube_info[i].robj = reloc->robj;
break;
case RADEON_PP_CUBIC_OFFSET_T2_0:
case RADEON_PP_CUBIC_OFFSET_T2_1:
case RADEON_PP_CUBIC_OFFSET_T2_2:
case RADEON_PP_CUBIC_OFFSET_T2_3:
case RADEON_PP_CUBIC_OFFSET_T2_4:
i = (reg - RADEON_PP_CUBIC_OFFSET_T2_0) / 4;
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
track->textures[2].cube_info[i].offset = ib_chunk->kdata[idx];
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
track->textures[2].cube_info[i].robj = reloc->robj;
break;
case RADEON_RE_WIDTH_HEIGHT:
track->maxy = ((ib_chunk->kdata[idx] >> 16) & 0x7FF);
break;
case RADEON_RB3D_COLORPITCH:
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
 
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
tile_flags |= RADEON_COLOR_TILE_ENABLE;
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
 
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
tmp |= tile_flags;
ib[idx] = tmp;
 
track->cb[0].pitch = ib_chunk->kdata[idx] & RADEON_COLORPITCH_MASK;
break;
case RADEON_RB3D_DEPTHPITCH:
track->zb.pitch = ib_chunk->kdata[idx] & RADEON_DEPTHPITCH_MASK;
break;
case RADEON_RB3D_CNTL:
switch ((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
case 7:
case 8:
case 9:
case 11:
case 12:
track->cb[0].cpp = 1;
break;
case 3:
case 4:
case 15:
track->cb[0].cpp = 2;
break;
case 6:
track->cb[0].cpp = 4;
break;
default:
/* FIXME: we don't want to allow anyothers packet */
DRM_ERROR("Invalid color buffer format (%d) !\n",
((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
return -EINVAL;
}
track->z_enabled = !!(ib_chunk->kdata[idx] & RADEON_Z_ENABLE);
break;
case RADEON_RB3D_ZSTENCILCNTL:
switch (ib_chunk->kdata[idx] & 0xf) {
case 0:
track->zb.cpp = 2;
break;
case 2:
case 3:
case 4:
case 5:
case 9:
case 11:
track->zb.cpp = 4;
break;
default:
break;
}
if (onereg) {
/* FIXME: forbid onereg write to register on relocate */
break;
case RADEON_RB3D_ZPASS_ADDR:
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
break;
case RADEON_PP_CNTL:
{
uint32_t temp = ib_chunk->kdata[idx] >> 4;
for (i = 0; i < track->num_texture; i++)
track->textures[i].enabled = !!(temp & (1 << i));
}
break;
case RADEON_SE_VF_CNTL:
track->vap_vf_cntl = ib_chunk->kdata[idx];
break;
case RADEON_SE_VTX_FMT:
track->vtx_size = r100_get_vtx_size(ib_chunk->kdata[idx]);
break;
case RADEON_PP_TEX_SIZE_0:
case RADEON_PP_TEX_SIZE_1:
case RADEON_PP_TEX_SIZE_2:
i = (reg - RADEON_PP_TEX_SIZE_0) / 8;
track->textures[i].width = (ib_chunk->kdata[idx] & RADEON_TEX_USIZE_MASK) + 1;
track->textures[i].height = ((ib_chunk->kdata[idx] & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
break;
case RADEON_PP_TEX_PITCH_0:
case RADEON_PP_TEX_PITCH_1:
case RADEON_PP_TEX_PITCH_2:
i = (reg - RADEON_PP_TEX_PITCH_0) / 8;
track->textures[i].pitch = ib_chunk->kdata[idx] + 32;
break;
case RADEON_PP_TXFILTER_0:
case RADEON_PP_TXFILTER_1:
case RADEON_PP_TXFILTER_2:
i = (reg - RADEON_PP_TXFILTER_0) / 24;
track->textures[i].num_levels = ((ib_chunk->kdata[idx] & RADEON_MAX_MIP_LEVEL_MASK)
>> RADEON_MAX_MIP_LEVEL_SHIFT);
tmp = (ib_chunk->kdata[idx] >> 23) & 0x7;
if (tmp == 2 || tmp == 6)
track->textures[i].roundup_w = false;
tmp = (ib_chunk->kdata[idx] >> 27) & 0x7;
if (tmp == 2 || tmp == 6)
track->textures[i].roundup_h = false;
break;
case RADEON_PP_TXFORMAT_0:
case RADEON_PP_TXFORMAT_1:
case RADEON_PP_TXFORMAT_2:
i = (reg - RADEON_PP_TXFORMAT_0) / 24;
if (ib_chunk->kdata[idx] & RADEON_TXFORMAT_NON_POWER2) {
track->textures[i].use_pitch = 1;
} else {
track->textures[i].use_pitch = 0;
track->textures[i].width = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
track->textures[i].height = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
}
if (ib_chunk->kdata[idx] & RADEON_TXFORMAT_CUBIC_MAP_ENABLE)
track->textures[i].tex_coord_type = 2;
switch ((ib_chunk->kdata[idx] & RADEON_TXFORMAT_FORMAT_MASK)) {
case RADEON_TXFORMAT_I8:
case RADEON_TXFORMAT_RGB332:
case RADEON_TXFORMAT_Y8:
track->textures[i].cpp = 1;
break;
case RADEON_TXFORMAT_AI88:
case RADEON_TXFORMAT_ARGB1555:
case RADEON_TXFORMAT_RGB565:
case RADEON_TXFORMAT_ARGB4444:
case RADEON_TXFORMAT_VYUY422:
case RADEON_TXFORMAT_YVYU422:
case RADEON_TXFORMAT_DXT1:
case RADEON_TXFORMAT_SHADOW16:
case RADEON_TXFORMAT_LDUDV655:
case RADEON_TXFORMAT_DUDV88:
track->textures[i].cpp = 2;
break;
case RADEON_TXFORMAT_ARGB8888:
case RADEON_TXFORMAT_RGBA8888:
case RADEON_TXFORMAT_DXT23:
case RADEON_TXFORMAT_DXT45:
case RADEON_TXFORMAT_SHADOW32:
case RADEON_TXFORMAT_LDUDUV8888:
track->textures[i].cpp = 4;
break;
}
track->textures[i].cube_info[4].width = 1 << ((ib_chunk->kdata[idx] >> 16) & 0xf);
track->textures[i].cube_info[4].height = 1 << ((ib_chunk->kdata[idx] >> 20) & 0xf);
break;
case RADEON_PP_CUBIC_FACES_0:
case RADEON_PP_CUBIC_FACES_1:
case RADEON_PP_CUBIC_FACES_2:
tmp = ib_chunk->kdata[idx];
i = (reg - RADEON_PP_CUBIC_FACES_0) / 4;
for (face = 0; face < 4; face++) {
track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf);
}
break;
default:
printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
reg, idx);
return -EINVAL;
}
return 0;
}
 
920,6 → 1331,7
{
struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_reloc *reloc;
struct r100_cs_track *track;
unsigned idx;
unsigned i, c;
volatile uint32_t *ib;
928,9 → 1340,11
ib = p->ib->ptr;
ib_chunk = &p->chunks[p->chunk_ib_idx];
idx = pkt->idx + 1;
track = (struct r100_cs_track *)p->track;
switch (pkt->opcode) {
case PACKET3_3D_LOAD_VBPNTR:
c = ib_chunk->kdata[idx++];
track->num_arrays = c;
for (i = 0; i < (c - 1); i += 2, idx += 3) {
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
940,6 → 1354,9
return r;
}
ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
track->arrays[i + 0].robj = reloc->robj;
track->arrays[i + 0].esize = ib_chunk->kdata[idx] >> 8;
track->arrays[i + 0].esize &= 0x7F;
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for packet3 %d\n",
948,6 → 1365,9
return r;
}
ib[idx+2] = ib_chunk->kdata[idx+2] + ((u32)reloc->lobj.gpu_offset);
track->arrays[i + 1].robj = reloc->robj;
track->arrays[i + 1].esize = ib_chunk->kdata[idx] >> 24;
track->arrays[i + 1].esize &= 0x7F;
}
if (c & 1) {
r = r100_cs_packet_next_reloc(p, &reloc);
958,6 → 1378,9
return r;
}
ib[idx+1] = ib_chunk->kdata[idx+1] + ((u32)reloc->lobj.gpu_offset);
track->arrays[i + 0].robj = reloc->robj;
track->arrays[i + 0].esize = ib_chunk->kdata[idx] >> 8;
track->arrays[i + 0].esize &= 0x7F;
}
break;
case PACKET3_INDX_BUFFER:
974,7 → 1397,6
}
break;
case 0x23:
/* FIXME: cleanup */
/* 3D_RNDR_GEN_INDX_PRIM on r100/r200 */
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
983,18 → 1405,71
return r;
}
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
track->num_arrays = 1;
track->vtx_size = r100_get_vtx_size(ib_chunk->kdata[idx+2]);
 
track->arrays[0].robj = reloc->robj;
track->arrays[0].esize = track->vtx_size;
 
track->max_indx = ib_chunk->kdata[idx+1];
 
track->vap_vf_cntl = ib_chunk->kdata[idx+3];
track->immd_dwords = pkt->count - 1;
r = r100_cs_track_check(p->rdev, track);
if (r)
return r;
break;
case PACKET3_3D_DRAW_IMMD:
if (((ib_chunk->kdata[idx+1] >> 4) & 0x3) != 3) {
DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
return -EINVAL;
}
track->vap_vf_cntl = ib_chunk->kdata[idx+1];
track->immd_dwords = pkt->count - 1;
r = r100_cs_track_check(p->rdev, track);
if (r)
return r;
break;
/* triggers drawing using in-packet vertex data */
case PACKET3_3D_DRAW_IMMD_2:
if (((ib_chunk->kdata[idx] >> 4) & 0x3) != 3) {
DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
return -EINVAL;
}
track->vap_vf_cntl = ib_chunk->kdata[idx];
track->immd_dwords = pkt->count;
r = r100_cs_track_check(p->rdev, track);
if (r)
return r;
break;
/* triggers drawing using in-packet vertex data */
case PACKET3_3D_DRAW_VBUF_2:
track->vap_vf_cntl = ib_chunk->kdata[idx];
r = r100_cs_track_check(p->rdev, track);
if (r)
return r;
break;
/* triggers drawing of vertex buffers setup elsewhere */
case PACKET3_3D_DRAW_INDX_2:
track->vap_vf_cntl = ib_chunk->kdata[idx];
r = r100_cs_track_check(p->rdev, track);
if (r)
return r;
break;
/* triggers drawing using indices to vertex buffer */
case PACKET3_3D_DRAW_VBUF:
track->vap_vf_cntl = ib_chunk->kdata[idx + 1];
r = r100_cs_track_check(p->rdev, track);
if (r)
return r;
break;
/* triggers drawing of vertex buffers setup elsewhere */
case PACKET3_3D_DRAW_INDX:
track->vap_vf_cntl = ib_chunk->kdata[idx + 1];
r = r100_cs_track_check(p->rdev, track);
if (r)
return r;
break;
/* triggers drawing using indices to vertex buffer */
case PACKET3_NOP:
break;
1008,8 → 1483,12
int r100_cs_parse(struct radeon_cs_parser *p)
{
struct radeon_cs_packet pkt;
struct r100_cs_track *track;
int r;
 
track = kzalloc(sizeof(*track), GFP_KERNEL);
r100_cs_track_clear(p->rdev, track);
p->track = track;
do {
r = r100_cs_packet_parse(p, &pkt, p->idx);
if (r) {
1018,7 → 1497,16
p->idx += pkt.count + 2;
switch (pkt.type) {
case PACKET_TYPE0:
r = r100_packet0_check(p, &pkt);
if (p->rdev->family >= CHIP_R200)
r = r100_cs_parse_packet0(p, &pkt,
p->rdev->config.r100.reg_safe_bm,
p->rdev->config.r100.reg_safe_bm_size,
&r200_packet0_check);
else
r = r100_cs_parse_packet0(p, &pkt,
p->rdev->config.r100.reg_safe_bm,
p->rdev->config.r100.reg_safe_bm_size,
&r100_packet0_check);
break;
case PACKET_TYPE2:
break;
1057,8 → 1545,6
}
}
 
 
 
/* Wait for vertical sync on primary CRTC */
void r100_gpu_wait_for_vsync(struct radeon_device *rdev)
{
1163,7 → 1649,7
{
uint32_t tmp;
 
dbgprintf("%s\n",__FUNCTION__);
ENTER();
 
tmp = RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL;
tmp |= (7 << 28);
1180,7 → 1666,7
uint32_t tmp;
int i;
 
dbgprintf("%s\n",__FUNCTION__);
ENTER();
 
WREG32(RADEON_RBBM_SOFT_RESET, RADEON_SOFT_RESET_E2);
(void)RREG32(RADEON_RBBM_SOFT_RESET);
1269,31 → 1755,117
}
}
 
void r100_vram_info(struct radeon_device *rdev)
static u32 r100_get_accessible_vram(struct radeon_device *rdev)
{
r100_vram_get_type(rdev);
u32 aper_size;
u8 byte;
 
aper_size = RREG32(RADEON_CONFIG_APER_SIZE);
 
/* Set HDP_APER_CNTL only on cards that are known not to be broken,
* that is has the 2nd generation multifunction PCI interface
*/
if (rdev->family == CHIP_RV280 ||
rdev->family >= CHIP_RV350) {
WREG32_P(RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL,
~RADEON_HDP_APER_CNTL);
DRM_INFO("Generation 2 PCI interface, using max accessible memory\n");
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(rdev->pdev, 0xe, &byte);
// if (byte & 0x80) {
// DRM_INFO("Generation 1 PCI interface in multifunction mode\n");
// DRM_INFO("Limiting VRAM to one aperture\n");
// 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 (RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL)
return aper_size * 2;
return aper_size;
}
 
void r100_vram_init_sizes(struct radeon_device *rdev)
{
u64 config_aper_size;
u32 accessible;
 
config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE);
 
if (rdev->flags & RADEON_IS_IGP) {
uint32_t tom;
/* read NB_TOM to get the amount of ram stolen for the GPU */
tom = RREG32(RADEON_NB_TOM);
rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16);
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size);
rdev->mc.real_vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16);
/* for IGPs we need to keep VRAM where it was put by the BIOS */
rdev->mc.vram_location = (tom & 0xffff) << 16;
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
} else {
rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
/* Some production boards of m6 will report 0
* if it's 8 MB
*/
if (rdev->mc.vram_size == 0) {
rdev->mc.vram_size = 8192 * 1024;
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size);
if (rdev->mc.real_vram_size == 0) {
rdev->mc.real_vram_size = 8192 * 1024;
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
}
/* let driver place VRAM */
rdev->mc.vram_location = 0xFFFFFFFFUL;
/* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM -
* Novell bug 204882 + along with lots of ubuntu ones */
if (config_aper_size > rdev->mc.real_vram_size)
rdev->mc.mc_vram_size = config_aper_size;
else
rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
}
 
/* work out accessible VRAM */
accessible = r100_get_accessible_vram(rdev);
 
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
 
if (accessible > rdev->mc.aper_size)
accessible = rdev->mc.aper_size;
 
if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
rdev->mc.mc_vram_size = rdev->mc.aper_size;
 
if (rdev->mc.real_vram_size > rdev->mc.aper_size)
rdev->mc.real_vram_size = rdev->mc.aper_size;
}
 
void r100_vga_set_state(struct radeon_device *rdev, bool state)
{
uint32_t temp;
 
temp = RREG32(RADEON_CONFIG_CNTL);
if (state == false) {
temp &= ~(1<<8);
temp |= (1<<9);
} else {
temp &= ~(1<<9);
}
WREG32(RADEON_CONFIG_CNTL, temp);
}
 
void r100_vram_info(struct radeon_device *rdev)
{
r100_vram_get_type(rdev);
 
r100_vram_init_sizes(rdev);
}
 
 
/*
* Indirect registers accessor
*/
1350,28 → 1922,17
r100_pll_errata_after_data(rdev);
}
 
uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
int r100_init(struct radeon_device *rdev)
{
if (reg < 0x10000)
return readl(((void __iomem *)rdev->rmmio) + reg);
else {
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
if (ASIC_IS_RN50(rdev)) {
rdev->config.r100.reg_safe_bm = rn50_reg_safe_bm;
rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(rn50_reg_safe_bm);
} else if (rdev->family < CHIP_R200) {
rdev->config.r100.reg_safe_bm = r100_reg_safe_bm;
rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r100_reg_safe_bm);
} else {
return r200_init(rdev);
}
}
 
void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
{
if (reg < 0x10000)
writel(v, ((void __iomem *)rdev->rmmio) + reg);
else {
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
}
}
 
int r100_init(struct radeon_device *rdev)
{
return 0;
}
 
1545,3 → 2106,611
return 0;
#endif
}
 
int r100_set_surface_reg(struct radeon_device *rdev, int reg,
uint32_t tiling_flags, uint32_t pitch,
uint32_t offset, uint32_t obj_size)
{
int surf_index = reg * 16;
int flags = 0;
 
/* r100/r200 divide by 16 */
if (rdev->family < CHIP_R300)
flags = pitch / 16;
else
flags = pitch / 8;
 
if (rdev->family <= CHIP_RS200) {
if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
== (RADEON_TILING_MACRO|RADEON_TILING_MICRO))
flags |= RADEON_SURF_TILE_COLOR_BOTH;
if (tiling_flags & RADEON_TILING_MACRO)
flags |= RADEON_SURF_TILE_COLOR_MACRO;
} else if (rdev->family <= CHIP_RV280) {
if (tiling_flags & (RADEON_TILING_MACRO))
flags |= R200_SURF_TILE_COLOR_MACRO;
if (tiling_flags & RADEON_TILING_MICRO)
flags |= R200_SURF_TILE_COLOR_MICRO;
} else {
if (tiling_flags & RADEON_TILING_MACRO)
flags |= R300_SURF_TILE_MACRO;
if (tiling_flags & RADEON_TILING_MICRO)
flags |= R300_SURF_TILE_MICRO;
}
 
if (tiling_flags & RADEON_TILING_SWAP_16BIT)
flags |= RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP;
if (tiling_flags & RADEON_TILING_SWAP_32BIT)
flags |= RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP;
 
DRM_DEBUG("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1);
WREG32(RADEON_SURFACE0_INFO + surf_index, flags);
WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset);
WREG32(RADEON_SURFACE0_UPPER_BOUND + surf_index, offset + obj_size - 1);
return 0;
}
 
void r100_clear_surface_reg(struct radeon_device *rdev, int reg)
{
int surf_index = reg * 16;
WREG32(RADEON_SURFACE0_INFO + surf_index, 0);
}
 
void r100_bandwidth_update(struct radeon_device *rdev)
{
fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff;
fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff;
fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff;
uint32_t temp, data, mem_trcd, mem_trp, mem_tras;
fixed20_12 memtcas_ff[8] = {
fixed_init(1),
fixed_init(2),
fixed_init(3),
fixed_init(0),
fixed_init_half(1),
fixed_init_half(2),
fixed_init(0),
};
fixed20_12 memtcas_rs480_ff[8] = {
fixed_init(0),
fixed_init(1),
fixed_init(2),
fixed_init(3),
fixed_init(0),
fixed_init_half(1),
fixed_init_half(2),
fixed_init_half(3),
};
fixed20_12 memtcas2_ff[8] = {
fixed_init(0),
fixed_init(1),
fixed_init(2),
fixed_init(3),
fixed_init(4),
fixed_init(5),
fixed_init(6),
fixed_init(7),
};
fixed20_12 memtrbs[8] = {
fixed_init(1),
fixed_init_half(1),
fixed_init(2),
fixed_init_half(2),
fixed_init(3),
fixed_init_half(3),
fixed_init(4),
fixed_init_half(4)
};
fixed20_12 memtrbs_r4xx[8] = {
fixed_init(4),
fixed_init(5),
fixed_init(6),
fixed_init(7),
fixed_init(8),
fixed_init(9),
fixed_init(10),
fixed_init(11)
};
fixed20_12 min_mem_eff;
fixed20_12 mc_latency_sclk, mc_latency_mclk, k1;
fixed20_12 cur_latency_mclk, cur_latency_sclk;
fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate,
disp_drain_rate2, read_return_rate;
fixed20_12 time_disp1_drop_priority;
int c;
int cur_size = 16; /* in octawords */
int critical_point = 0, critical_point2;
/* uint32_t read_return_rate, time_disp1_drop_priority; */
int stop_req, max_stop_req;
struct drm_display_mode *mode1 = NULL;
struct drm_display_mode *mode2 = NULL;
uint32_t pixel_bytes1 = 0;
uint32_t pixel_bytes2 = 0;
 
if (rdev->mode_info.crtcs[0]->base.enabled) {
mode1 = &rdev->mode_info.crtcs[0]->base.mode;
pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8;
}
if (rdev->mode_info.crtcs[1]->base.enabled) {
mode2 = &rdev->mode_info.crtcs[1]->base.mode;
pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8;
}
 
min_mem_eff.full = rfixed_const_8(0);
/* get modes */
if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) {
uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER);
mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT);
mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT);
/* check crtc enables */
if (mode2)
mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT);
if (mode1)
mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT);
WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
}
 
/*
* determine is there is enough bw for current mode
*/
mclk_ff.full = rfixed_const(rdev->clock.default_mclk);
temp_ff.full = rfixed_const(100);
mclk_ff.full = rfixed_div(mclk_ff, temp_ff);
sclk_ff.full = rfixed_const(rdev->clock.default_sclk);
sclk_ff.full = rfixed_div(sclk_ff, temp_ff);
 
temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1);
temp_ff.full = rfixed_const(temp);
mem_bw.full = rfixed_mul(mclk_ff, temp_ff);
 
pix_clk.full = 0;
pix_clk2.full = 0;
peak_disp_bw.full = 0;
if (mode1) {
temp_ff.full = rfixed_const(1000);
pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */
pix_clk.full = rfixed_div(pix_clk, temp_ff);
temp_ff.full = rfixed_const(pixel_bytes1);
peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff);
}
if (mode2) {
temp_ff.full = rfixed_const(1000);
pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */
pix_clk2.full = rfixed_div(pix_clk2, temp_ff);
temp_ff.full = rfixed_const(pixel_bytes2);
peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff);
}
 
mem_bw.full = rfixed_mul(mem_bw, min_mem_eff);
if (peak_disp_bw.full >= mem_bw.full) {
DRM_ERROR("You may not have enough display bandwidth for current mode\n"
"If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
}
 
/* Get values from the EXT_MEM_CNTL register...converting its contents. */
temp = RREG32(RADEON_MEM_TIMING_CNTL);
if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */
mem_trcd = ((temp >> 2) & 0x3) + 1;
mem_trp = ((temp & 0x3)) + 1;
mem_tras = ((temp & 0x70) >> 4) + 1;
} else if (rdev->family == CHIP_R300 ||
rdev->family == CHIP_R350) { /* r300, r350 */
mem_trcd = (temp & 0x7) + 1;
mem_trp = ((temp >> 8) & 0x7) + 1;
mem_tras = ((temp >> 11) & 0xf) + 4;
} else if (rdev->family == CHIP_RV350 ||
rdev->family <= CHIP_RV380) {
/* rv3x0 */
mem_trcd = (temp & 0x7) + 3;
mem_trp = ((temp >> 8) & 0x7) + 3;
mem_tras = ((temp >> 11) & 0xf) + 6;
} else if (rdev->family == CHIP_R420 ||
rdev->family == CHIP_R423 ||
rdev->family == CHIP_RV410) {
/* r4xx */
mem_trcd = (temp & 0xf) + 3;
if (mem_trcd > 15)
mem_trcd = 15;
mem_trp = ((temp >> 8) & 0xf) + 3;
if (mem_trp > 15)
mem_trp = 15;
mem_tras = ((temp >> 12) & 0x1f) + 6;
if (mem_tras > 31)
mem_tras = 31;
} else { /* RV200, R200 */
mem_trcd = (temp & 0x7) + 1;
mem_trp = ((temp >> 8) & 0x7) + 1;
mem_tras = ((temp >> 12) & 0xf) + 4;
}
/* convert to FF */
trcd_ff.full = rfixed_const(mem_trcd);
trp_ff.full = rfixed_const(mem_trp);
tras_ff.full = rfixed_const(mem_tras);
 
/* Get values from the MEM_SDRAM_MODE_REG register...converting its */
temp = RREG32(RADEON_MEM_SDRAM_MODE_REG);
data = (temp & (7 << 20)) >> 20;
if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) {
if (rdev->family == CHIP_RS480) /* don't think rs400 */
tcas_ff = memtcas_rs480_ff[data];
else
tcas_ff = memtcas_ff[data];
} else
tcas_ff = memtcas2_ff[data];
 
if (rdev->family == CHIP_RS400 ||
rdev->family == CHIP_RS480) {
/* extra cas latency stored in bits 23-25 0-4 clocks */
data = (temp >> 23) & 0x7;
if (data < 5)
tcas_ff.full += rfixed_const(data);
}
 
if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) {
/* on the R300, Tcas is included in Trbs.
*/
temp = RREG32(RADEON_MEM_CNTL);
data = (R300_MEM_NUM_CHANNELS_MASK & temp);
if (data == 1) {
if (R300_MEM_USE_CD_CH_ONLY & temp) {
temp = RREG32(R300_MC_IND_INDEX);
temp &= ~R300_MC_IND_ADDR_MASK;
temp |= R300_MC_READ_CNTL_CD_mcind;
WREG32(R300_MC_IND_INDEX, temp);
temp = RREG32(R300_MC_IND_DATA);
data = (R300_MEM_RBS_POSITION_C_MASK & temp);
} else {
temp = RREG32(R300_MC_READ_CNTL_AB);
data = (R300_MEM_RBS_POSITION_A_MASK & temp);
}
} else {
temp = RREG32(R300_MC_READ_CNTL_AB);
data = (R300_MEM_RBS_POSITION_A_MASK & temp);
}
if (rdev->family == CHIP_RV410 ||
rdev->family == CHIP_R420 ||
rdev->family == CHIP_R423)
trbs_ff = memtrbs_r4xx[data];
else
trbs_ff = memtrbs[data];
tcas_ff.full += trbs_ff.full;
}
 
sclk_eff_ff.full = sclk_ff.full;
 
if (rdev->flags & RADEON_IS_AGP) {
fixed20_12 agpmode_ff;
agpmode_ff.full = rfixed_const(radeon_agpmode);
temp_ff.full = rfixed_const_666(16);
sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff);
}
/* TODO PCIE lanes may affect this - agpmode == 16?? */
 
if (ASIC_IS_R300(rdev)) {
sclk_delay_ff.full = rfixed_const(250);
} else {
if ((rdev->family == CHIP_RV100) ||
rdev->flags & RADEON_IS_IGP) {
if (rdev->mc.vram_is_ddr)
sclk_delay_ff.full = rfixed_const(41);
else
sclk_delay_ff.full = rfixed_const(33);
} else {
if (rdev->mc.vram_width == 128)
sclk_delay_ff.full = rfixed_const(57);
else
sclk_delay_ff.full = rfixed_const(41);
}
}
 
mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff);
 
if (rdev->mc.vram_is_ddr) {
if (rdev->mc.vram_width == 32) {
k1.full = rfixed_const(40);
c = 3;
} else {
k1.full = rfixed_const(20);
c = 1;
}
} else {
k1.full = rfixed_const(40);
c = 3;
}
 
temp_ff.full = rfixed_const(2);
mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff);
temp_ff.full = rfixed_const(c);
mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff);
temp_ff.full = rfixed_const(4);
mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff);
mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff);
mc_latency_mclk.full += k1.full;
 
mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff);
mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff);
 
/*
HW cursor time assuming worst case of full size colour cursor.
*/
temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1))));
temp_ff.full += trcd_ff.full;
if (temp_ff.full < tras_ff.full)
temp_ff.full = tras_ff.full;
cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff);
 
temp_ff.full = rfixed_const(cur_size);
cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff);
/*
Find the total latency for the display data.
*/
disp_latency_overhead.full = rfixed_const(80);
disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff);
mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full;
mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full;
 
if (mc_latency_mclk.full > mc_latency_sclk.full)
disp_latency.full = mc_latency_mclk.full;
else
disp_latency.full = mc_latency_sclk.full;
 
/* setup Max GRPH_STOP_REQ default value */
if (ASIC_IS_RV100(rdev))
max_stop_req = 0x5c;
else
max_stop_req = 0x7c;
 
if (mode1) {
/* CRTC1
Set GRPH_BUFFER_CNTL register using h/w defined optimal values.
GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ]
*/
stop_req = mode1->hdisplay * pixel_bytes1 / 16;
 
if (stop_req > max_stop_req)
stop_req = max_stop_req;
 
/*
Find the drain rate of the display buffer.
*/
temp_ff.full = rfixed_const((16/pixel_bytes1));
disp_drain_rate.full = rfixed_div(pix_clk, temp_ff);
 
/*
Find the critical point of the display buffer.
*/
crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency);
crit_point_ff.full += rfixed_const_half(0);
 
critical_point = rfixed_trunc(crit_point_ff);
 
if (rdev->disp_priority == 2) {
critical_point = 0;
}
 
/*
The critical point should never be above max_stop_req-4. Setting
GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time.
*/
if (max_stop_req - critical_point < 4)
critical_point = 0;
 
if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) {
/* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/
critical_point = 0x10;
}
 
temp = RREG32(RADEON_GRPH_BUFFER_CNTL);
temp &= ~(RADEON_GRPH_STOP_REQ_MASK);
temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
temp &= ~(RADEON_GRPH_START_REQ_MASK);
if ((rdev->family == CHIP_R350) &&
(stop_req > 0x15)) {
stop_req -= 0x10;
}
temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
temp |= RADEON_GRPH_BUFFER_SIZE;
temp &= ~(RADEON_GRPH_CRITICAL_CNTL |
RADEON_GRPH_CRITICAL_AT_SOF |
RADEON_GRPH_STOP_CNTL);
/*
Write the result into the register.
*/
WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
(critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
 
#if 0
if ((rdev->family == CHIP_RS400) ||
(rdev->family == CHIP_RS480)) {
/* attempt to program RS400 disp regs correctly ??? */
temp = RREG32(RS400_DISP1_REG_CNTL);
temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK |
RS400_DISP1_STOP_REQ_LEVEL_MASK);
WREG32(RS400_DISP1_REQ_CNTL1, (temp |
(critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) |
(critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT)));
temp = RREG32(RS400_DMIF_MEM_CNTL1);
temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK |
RS400_DISP1_CRITICAL_POINT_STOP_MASK);
WREG32(RS400_DMIF_MEM_CNTL1, (temp |
(critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) |
(critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT)));
}
#endif
 
DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n",
/* (unsigned int)info->SavedReg->grph_buffer_cntl, */
(unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL));
}
 
if (mode2) {
u32 grph2_cntl;
stop_req = mode2->hdisplay * pixel_bytes2 / 16;
 
if (stop_req > max_stop_req)
stop_req = max_stop_req;
 
/*
Find the drain rate of the display buffer.
*/
temp_ff.full = rfixed_const((16/pixel_bytes2));
disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff);
 
grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL);
grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK);
grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK);
if ((rdev->family == CHIP_R350) &&
(stop_req > 0x15)) {
stop_req -= 0x10;
}
grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
grph2_cntl |= RADEON_GRPH_BUFFER_SIZE;
grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL |
RADEON_GRPH_CRITICAL_AT_SOF |
RADEON_GRPH_STOP_CNTL);
 
if ((rdev->family == CHIP_RS100) ||
(rdev->family == CHIP_RS200))
critical_point2 = 0;
else {
temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128;
temp_ff.full = rfixed_const(temp);
temp_ff.full = rfixed_mul(mclk_ff, temp_ff);
if (sclk_ff.full < temp_ff.full)
temp_ff.full = sclk_ff.full;
 
read_return_rate.full = temp_ff.full;
 
if (mode1) {
temp_ff.full = read_return_rate.full - disp_drain_rate.full;
time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff);
} else {
time_disp1_drop_priority.full = 0;
}
crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full;
crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2);
crit_point_ff.full += rfixed_const_half(0);
 
critical_point2 = rfixed_trunc(crit_point_ff);
 
if (rdev->disp_priority == 2) {
critical_point2 = 0;
}
 
if (max_stop_req - critical_point2 < 4)
critical_point2 = 0;
 
}
 
if (critical_point2 == 0 && rdev->family == CHIP_R300) {
/* some R300 cards have problem with this set to 0 */
critical_point2 = 0x10;
}
 
WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
(critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
 
if ((rdev->family == CHIP_RS400) ||
(rdev->family == CHIP_RS480)) {
#if 0
/* attempt to program RS400 disp2 regs correctly ??? */
temp = RREG32(RS400_DISP2_REQ_CNTL1);
temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK |
RS400_DISP2_STOP_REQ_LEVEL_MASK);
WREG32(RS400_DISP2_REQ_CNTL1, (temp |
(critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) |
(critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT)));
temp = RREG32(RS400_DISP2_REQ_CNTL2);
temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK |
RS400_DISP2_CRITICAL_POINT_STOP_MASK);
WREG32(RS400_DISP2_REQ_CNTL2, (temp |
(critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) |
(critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT)));
#endif
WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC);
WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000);
WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC);
WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC);
}
 
DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n",
(unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL));
}
}
 
 
 
 
void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save)
{
/* Shutdown CP we shouldn't need to do that but better be safe than
* sorry
*/
rdev->cp.ready = false;
WREG32(R_000740_CP_CSQ_CNTL, 0);
 
/* Save few CRTC registers */
save->GENMO_WT = RREG32(R_0003C0_GENMO_WT);
save->CRTC_EXT_CNTL = RREG32(R_000054_CRTC_EXT_CNTL);
save->CRTC_GEN_CNTL = RREG32(R_000050_CRTC_GEN_CNTL);
save->CUR_OFFSET = RREG32(R_000260_CUR_OFFSET);
if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
save->CRTC2_GEN_CNTL = RREG32(R_0003F8_CRTC2_GEN_CNTL);
save->CUR2_OFFSET = RREG32(R_000360_CUR2_OFFSET);
}
 
/* Disable VGA aperture access */
WREG32(R_0003C0_GENMO_WT, C_0003C0_VGA_RAM_EN & save->GENMO_WT);
/* Disable cursor, overlay, crtc */
WREG32(R_000260_CUR_OFFSET, save->CUR_OFFSET | S_000260_CUR_LOCK(1));
WREG32(R_000054_CRTC_EXT_CNTL, save->CRTC_EXT_CNTL |
S_000054_CRTC_DISPLAY_DIS(1));
WREG32(R_000050_CRTC_GEN_CNTL,
(C_000050_CRTC_CUR_EN & save->CRTC_GEN_CNTL) |
S_000050_CRTC_DISP_REQ_EN_B(1));
WREG32(R_000420_OV0_SCALE_CNTL,
C_000420_OV0_OVERLAY_EN & RREG32(R_000420_OV0_SCALE_CNTL));
WREG32(R_000260_CUR_OFFSET, C_000260_CUR_LOCK & save->CUR_OFFSET);
if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
WREG32(R_000360_CUR2_OFFSET, save->CUR2_OFFSET |
S_000360_CUR2_LOCK(1));
WREG32(R_0003F8_CRTC2_GEN_CNTL,
(C_0003F8_CRTC2_CUR_EN & save->CRTC2_GEN_CNTL) |
S_0003F8_CRTC2_DISPLAY_DIS(1) |
S_0003F8_CRTC2_DISP_REQ_EN_B(1));
WREG32(R_000360_CUR2_OFFSET,
C_000360_CUR2_LOCK & save->CUR2_OFFSET);
}
}
 
void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save)
{
/* Update base address for crtc */
WREG32(R_00023C_DISPLAY_BASE_ADDR, rdev->mc.vram_location);
if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
WREG32(R_00033C_CRTC2_DISPLAY_BASE_ADDR,
rdev->mc.vram_location);
}
/* Restore CRTC registers */
WREG32(R_0003C0_GENMO_WT, save->GENMO_WT);
WREG32(R_000054_CRTC_EXT_CNTL, save->CRTC_EXT_CNTL);
WREG32(R_000050_CRTC_GEN_CNTL, save->CRTC_GEN_CNTL);
if (!(rdev->flags & RADEON_SINGLE_CRTC)) {
WREG32(R_0003F8_CRTC2_GEN_CNTL, save->CRTC2_GEN_CNTL);
}
}
 
int drm_order(unsigned long size)
{
int order;
unsigned long tmp;
 
for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) ;
 
if (size & (size - 1))
++order;
 
return order;
}
 
/drivers/video/drm/radeon/r100_reg_safe.h
0,0 → 1,28
static const unsigned r100_reg_safe_bm[102] = {
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF,
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF,
0xFFFFFFCF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFF9F, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x38E7FE1F, 0xFFC3FF8E, 0x7FF8FFFF, 0xFFFF803C,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFEFFFF, 0xFFFFFFFF,
0x00000000, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFCFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFEF,
};
/drivers/video/drm/radeon/r100d.h
0,0 → 1,607
/*
* Copyright 2008 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
* Copyright 2009 Jerome Glisse.
*
* 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
* Jerome Glisse
*/
#ifndef __R100D_H__
#define __R100D_H__
 
#define CP_PACKET0 0x00000000
#define PACKET0_BASE_INDEX_SHIFT 0
#define PACKET0_BASE_INDEX_MASK (0x1ffff << 0)
#define PACKET0_COUNT_SHIFT 16
#define PACKET0_COUNT_MASK (0x3fff << 16)
#define CP_PACKET1 0x40000000
#define CP_PACKET2 0x80000000
#define PACKET2_PAD_SHIFT 0
#define PACKET2_PAD_MASK (0x3fffffff << 0)
#define CP_PACKET3 0xC0000000
#define PACKET3_IT_OPCODE_SHIFT 8
#define PACKET3_IT_OPCODE_MASK (0xff << 8)
#define PACKET3_COUNT_SHIFT 16
#define PACKET3_COUNT_MASK (0x3fff << 16)
/* PACKET3 op code */
#define PACKET3_NOP 0x10
#define PACKET3_3D_DRAW_VBUF 0x28
#define PACKET3_3D_DRAW_IMMD 0x29
#define PACKET3_3D_DRAW_INDX 0x2A
#define PACKET3_3D_LOAD_VBPNTR 0x2F
#define PACKET3_INDX_BUFFER 0x33
#define PACKET3_3D_DRAW_VBUF_2 0x34
#define PACKET3_3D_DRAW_IMMD_2 0x35
#define PACKET3_3D_DRAW_INDX_2 0x36
#define PACKET3_BITBLT_MULTI 0x9B
 
#define PACKET0(reg, n) (CP_PACKET0 | \
REG_SET(PACKET0_BASE_INDEX, (reg) >> 2) | \
REG_SET(PACKET0_COUNT, (n)))
#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
#define PACKET3(op, n) (CP_PACKET3 | \
REG_SET(PACKET3_IT_OPCODE, (op)) | \
REG_SET(PACKET3_COUNT, (n)))
 
#define PACKET_TYPE0 0
#define PACKET_TYPE1 1
#define PACKET_TYPE2 2
#define PACKET_TYPE3 3
 
#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2)
#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1)
#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
 
/* Registers */
#define R_000040_GEN_INT_CNTL 0x000040
#define S_000040_CRTC_VBLANK(x) (((x) & 0x1) << 0)
#define G_000040_CRTC_VBLANK(x) (((x) >> 0) & 0x1)
#define C_000040_CRTC_VBLANK 0xFFFFFFFE
#define S_000040_CRTC_VLINE(x) (((x) & 0x1) << 1)
#define G_000040_CRTC_VLINE(x) (((x) >> 1) & 0x1)
#define C_000040_CRTC_VLINE 0xFFFFFFFD
#define S_000040_CRTC_VSYNC(x) (((x) & 0x1) << 2)
#define G_000040_CRTC_VSYNC(x) (((x) >> 2) & 0x1)
#define C_000040_CRTC_VSYNC 0xFFFFFFFB
#define S_000040_SNAPSHOT(x) (((x) & 0x1) << 3)
#define G_000040_SNAPSHOT(x) (((x) >> 3) & 0x1)
#define C_000040_SNAPSHOT 0xFFFFFFF7
#define S_000040_FP_DETECT(x) (((x) & 0x1) << 4)
#define G_000040_FP_DETECT(x) (((x) >> 4) & 0x1)
#define C_000040_FP_DETECT 0xFFFFFFEF
#define S_000040_CRTC2_VLINE(x) (((x) & 0x1) << 5)
#define G_000040_CRTC2_VLINE(x) (((x) >> 5) & 0x1)
#define C_000040_CRTC2_VLINE 0xFFFFFFDF
#define S_000040_DMA_VIPH0_INT_EN(x) (((x) & 0x1) << 12)
#define G_000040_DMA_VIPH0_INT_EN(x) (((x) >> 12) & 0x1)
#define C_000040_DMA_VIPH0_INT_EN 0xFFFFEFFF
#define S_000040_CRTC2_VSYNC(x) (((x) & 0x1) << 6)
#define G_000040_CRTC2_VSYNC(x) (((x) >> 6) & 0x1)
#define C_000040_CRTC2_VSYNC 0xFFFFFFBF
#define S_000040_SNAPSHOT2(x) (((x) & 0x1) << 7)
#define G_000040_SNAPSHOT2(x) (((x) >> 7) & 0x1)
#define C_000040_SNAPSHOT2 0xFFFFFF7F
#define S_000040_CRTC2_VBLANK(x) (((x) & 0x1) << 9)
#define G_000040_CRTC2_VBLANK(x) (((x) >> 9) & 0x1)
#define C_000040_CRTC2_VBLANK 0xFFFFFDFF
#define S_000040_FP2_DETECT(x) (((x) & 0x1) << 10)
#define G_000040_FP2_DETECT(x) (((x) >> 10) & 0x1)
#define C_000040_FP2_DETECT 0xFFFFFBFF
#define S_000040_VSYNC_DIFF_OVER_LIMIT(x) (((x) & 0x1) << 11)
#define G_000040_VSYNC_DIFF_OVER_LIMIT(x) (((x) >> 11) & 0x1)
#define C_000040_VSYNC_DIFF_OVER_LIMIT 0xFFFFF7FF
#define S_000040_DMA_VIPH1_INT_EN(x) (((x) & 0x1) << 13)
#define G_000040_DMA_VIPH1_INT_EN(x) (((x) >> 13) & 0x1)
#define C_000040_DMA_VIPH1_INT_EN 0xFFFFDFFF
#define S_000040_DMA_VIPH2_INT_EN(x) (((x) & 0x1) << 14)
#define G_000040_DMA_VIPH2_INT_EN(x) (((x) >> 14) & 0x1)
#define C_000040_DMA_VIPH2_INT_EN 0xFFFFBFFF
#define S_000040_DMA_VIPH3_INT_EN(x) (((x) & 0x1) << 15)
#define G_000040_DMA_VIPH3_INT_EN(x) (((x) >> 15) & 0x1)
#define C_000040_DMA_VIPH3_INT_EN 0xFFFF7FFF
#define S_000040_I2C_INT_EN(x) (((x) & 0x1) << 17)
#define G_000040_I2C_INT_EN(x) (((x) >> 17) & 0x1)
#define C_000040_I2C_INT_EN 0xFFFDFFFF
#define S_000040_GUI_IDLE(x) (((x) & 0x1) << 19)
#define G_000040_GUI_IDLE(x) (((x) >> 19) & 0x1)
#define C_000040_GUI_IDLE 0xFFF7FFFF
#define S_000040_VIPH_INT_EN(x) (((x) & 0x1) << 24)
#define G_000040_VIPH_INT_EN(x) (((x) >> 24) & 0x1)
#define C_000040_VIPH_INT_EN 0xFEFFFFFF
#define S_000040_SW_INT_EN(x) (((x) & 0x1) << 25)
#define G_000040_SW_INT_EN(x) (((x) >> 25) & 0x1)
#define C_000040_SW_INT_EN 0xFDFFFFFF
#define S_000040_GEYSERVILLE(x) (((x) & 0x1) << 27)
#define G_000040_GEYSERVILLE(x) (((x) >> 27) & 0x1)
#define C_000040_GEYSERVILLE 0xF7FFFFFF
#define S_000040_HDCP_AUTHORIZED_INT(x) (((x) & 0x1) << 28)
#define G_000040_HDCP_AUTHORIZED_INT(x) (((x) >> 28) & 0x1)
#define C_000040_HDCP_AUTHORIZED_INT 0xEFFFFFFF
#define S_000040_DVI_I2C_INT(x) (((x) & 0x1) << 29)
#define G_000040_DVI_I2C_INT(x) (((x) >> 29) & 0x1)
#define C_000040_DVI_I2C_INT 0xDFFFFFFF
#define S_000040_GUIDMA(x) (((x) & 0x1) << 30)
#define G_000040_GUIDMA(x) (((x) >> 30) & 0x1)
#define C_000040_GUIDMA 0xBFFFFFFF
#define S_000040_VIDDMA(x) (((x) & 0x1) << 31)
#define G_000040_VIDDMA(x) (((x) >> 31) & 0x1)
#define C_000040_VIDDMA 0x7FFFFFFF
#define R_000044_GEN_INT_STATUS 0x000044
#define S_000044_CRTC_VBLANK_STAT(x) (((x) & 0x1) << 0)
#define G_000044_CRTC_VBLANK_STAT(x) (((x) >> 0) & 0x1)
#define C_000044_CRTC_VBLANK_STAT 0xFFFFFFFE
#define S_000044_CRTC_VBLANK_STAT_AK(x) (((x) & 0x1) << 0)
#define G_000044_CRTC_VBLANK_STAT_AK(x) (((x) >> 0) & 0x1)
#define C_000044_CRTC_VBLANK_STAT_AK 0xFFFFFFFE
#define S_000044_CRTC_VLINE_STAT(x) (((x) & 0x1) << 1)
#define G_000044_CRTC_VLINE_STAT(x) (((x) >> 1) & 0x1)
#define C_000044_CRTC_VLINE_STAT 0xFFFFFFFD
#define S_000044_CRTC_VLINE_STAT_AK(x) (((x) & 0x1) << 1)
#define G_000044_CRTC_VLINE_STAT_AK(x) (((x) >> 1) & 0x1)
#define C_000044_CRTC_VLINE_STAT_AK 0xFFFFFFFD
#define S_000044_CRTC_VSYNC_STAT(x) (((x) & 0x1) << 2)
#define G_000044_CRTC_VSYNC_STAT(x) (((x) >> 2) & 0x1)
#define C_000044_CRTC_VSYNC_STAT 0xFFFFFFFB
#define S_000044_CRTC_VSYNC_STAT_AK(x) (((x) & 0x1) << 2)
#define G_000044_CRTC_VSYNC_STAT_AK(x) (((x) >> 2) & 0x1)
#define C_000044_CRTC_VSYNC_STAT_AK 0xFFFFFFFB
#define S_000044_SNAPSHOT_STAT(x) (((x) & 0x1) << 3)
#define G_000044_SNAPSHOT_STAT(x) (((x) >> 3) & 0x1)
#define C_000044_SNAPSHOT_STAT 0xFFFFFFF7
#define S_000044_SNAPSHOT_STAT_AK(x) (((x) & 0x1) << 3)
#define G_000044_SNAPSHOT_STAT_AK(x) (((x) >> 3) & 0x1)
#define C_000044_SNAPSHOT_STAT_AK 0xFFFFFFF7
#define S_000044_FP_DETECT_STAT(x) (((x) & 0x1) << 4)
#define G_000044_FP_DETECT_STAT(x) (((x) >> 4) & 0x1)
#define C_000044_FP_DETECT_STAT 0xFFFFFFEF
#define S_000044_FP_DETECT_STAT_AK(x) (((x) & 0x1) << 4)
#define G_000044_FP_DETECT_STAT_AK(x) (((x) >> 4) & 0x1)
#define C_000044_FP_DETECT_STAT_AK 0xFFFFFFEF
#define S_000044_CRTC2_VLINE_STAT(x) (((x) & 0x1) << 5)
#define G_000044_CRTC2_VLINE_STAT(x) (((x) >> 5) & 0x1)
#define C_000044_CRTC2_VLINE_STAT 0xFFFFFFDF
#define S_000044_CRTC2_VLINE_STAT_AK(x) (((x) & 0x1) << 5)
#define G_000044_CRTC2_VLINE_STAT_AK(x) (((x) >> 5) & 0x1)
#define C_000044_CRTC2_VLINE_STAT_AK 0xFFFFFFDF
#define S_000044_CRTC2_VSYNC_STAT(x) (((x) & 0x1) << 6)
#define G_000044_CRTC2_VSYNC_STAT(x) (((x) >> 6) & 0x1)
#define C_000044_CRTC2_VSYNC_STAT 0xFFFFFFBF
#define S_000044_CRTC2_VSYNC_STAT_AK(x) (((x) & 0x1) << 6)
#define G_000044_CRTC2_VSYNC_STAT_AK(x) (((x) >> 6) & 0x1)
#define C_000044_CRTC2_VSYNC_STAT_AK 0xFFFFFFBF
#define S_000044_SNAPSHOT2_STAT(x) (((x) & 0x1) << 7)
#define G_000044_SNAPSHOT2_STAT(x) (((x) >> 7) & 0x1)
#define C_000044_SNAPSHOT2_STAT 0xFFFFFF7F
#define S_000044_SNAPSHOT2_STAT_AK(x) (((x) & 0x1) << 7)
#define G_000044_SNAPSHOT2_STAT_AK(x) (((x) >> 7) & 0x1)
#define C_000044_SNAPSHOT2_STAT_AK 0xFFFFFF7F
#define S_000044_CAP0_INT_ACTIVE(x) (((x) & 0x1) << 8)
#define G_000044_CAP0_INT_ACTIVE(x) (((x) >> 8) & 0x1)
#define C_000044_CAP0_INT_ACTIVE 0xFFFFFEFF
#define S_000044_CRTC2_VBLANK_STAT(x) (((x) & 0x1) << 9)
#define G_000044_CRTC2_VBLANK_STAT(x) (((x) >> 9) & 0x1)
#define C_000044_CRTC2_VBLANK_STAT 0xFFFFFDFF
#define S_000044_CRTC2_VBLANK_STAT_AK(x) (((x) & 0x1) << 9)
#define G_000044_CRTC2_VBLANK_STAT_AK(x) (((x) >> 9) & 0x1)
#define C_000044_CRTC2_VBLANK_STAT_AK 0xFFFFFDFF
#define S_000044_FP2_DETECT_STAT(x) (((x) & 0x1) << 10)
#define G_000044_FP2_DETECT_STAT(x) (((x) >> 10) & 0x1)
#define C_000044_FP2_DETECT_STAT 0xFFFFFBFF
#define S_000044_FP2_DETECT_STAT_AK(x) (((x) & 0x1) << 10)
#define G_000044_FP2_DETECT_STAT_AK(x) (((x) >> 10) & 0x1)
#define C_000044_FP2_DETECT_STAT_AK 0xFFFFFBFF
#define S_000044_VSYNC_DIFF_OVER_LIMIT_STAT(x) (((x) & 0x1) << 11)
#define G_000044_VSYNC_DIFF_OVER_LIMIT_STAT(x) (((x) >> 11) & 0x1)
#define C_000044_VSYNC_DIFF_OVER_LIMIT_STAT 0xFFFFF7FF
#define S_000044_VSYNC_DIFF_OVER_LIMIT_STAT_AK(x) (((x) & 0x1) << 11)
#define G_000044_VSYNC_DIFF_OVER_LIMIT_STAT_AK(x) (((x) >> 11) & 0x1)
#define C_000044_VSYNC_DIFF_OVER_LIMIT_STAT_AK 0xFFFFF7FF
#define S_000044_DMA_VIPH0_INT(x) (((x) & 0x1) << 12)
#define G_000044_DMA_VIPH0_INT(x) (((x) >> 12) & 0x1)
#define C_000044_DMA_VIPH0_INT 0xFFFFEFFF
#define S_000044_DMA_VIPH0_INT_AK(x) (((x) & 0x1) << 12)
#define G_000044_DMA_VIPH0_INT_AK(x) (((x) >> 12) & 0x1)
#define C_000044_DMA_VIPH0_INT_AK 0xFFFFEFFF
#define S_000044_DMA_VIPH1_INT(x) (((x) & 0x1) << 13)
#define G_000044_DMA_VIPH1_INT(x) (((x) >> 13) & 0x1)
#define C_000044_DMA_VIPH1_INT 0xFFFFDFFF
#define S_000044_DMA_VIPH1_INT_AK(x) (((x) & 0x1) << 13)
#define G_000044_DMA_VIPH1_INT_AK(x) (((x) >> 13) & 0x1)
#define C_000044_DMA_VIPH1_INT_AK 0xFFFFDFFF
#define S_000044_DMA_VIPH2_INT(x) (((x) & 0x1) << 14)
#define G_000044_DMA_VIPH2_INT(x) (((x) >> 14) & 0x1)
#define C_000044_DMA_VIPH2_INT 0xFFFFBFFF
#define S_000044_DMA_VIPH2_INT_AK(x) (((x) & 0x1) << 14)
#define G_000044_DMA_VIPH2_INT_AK(x) (((x) >> 14) & 0x1)
#define C_000044_DMA_VIPH2_INT_AK 0xFFFFBFFF
#define S_000044_DMA_VIPH3_INT(x) (((x) & 0x1) << 15)
#define G_000044_DMA_VIPH3_INT(x) (((x) >> 15) & 0x1)
#define C_000044_DMA_VIPH3_INT 0xFFFF7FFF
#define S_000044_DMA_VIPH3_INT_AK(x) (((x) & 0x1) << 15)
#define G_000044_DMA_VIPH3_INT_AK(x) (((x) >> 15) & 0x1)
#define C_000044_DMA_VIPH3_INT_AK 0xFFFF7FFF
#define S_000044_I2C_INT(x) (((x) & 0x1) << 17)
#define G_000044_I2C_INT(x) (((x) >> 17) & 0x1)
#define C_000044_I2C_INT 0xFFFDFFFF
#define S_000044_I2C_INT_AK(x) (((x) & 0x1) << 17)
#define G_000044_I2C_INT_AK(x) (((x) >> 17) & 0x1)
#define C_000044_I2C_INT_AK 0xFFFDFFFF
#define S_000044_GUI_IDLE_STAT(x) (((x) & 0x1) << 19)
#define G_000044_GUI_IDLE_STAT(x) (((x) >> 19) & 0x1)
#define C_000044_GUI_IDLE_STAT 0xFFF7FFFF
#define S_000044_GUI_IDLE_STAT_AK(x) (((x) & 0x1) << 19)
#define G_000044_GUI_IDLE_STAT_AK(x) (((x) >> 19) & 0x1)
#define C_000044_GUI_IDLE_STAT_AK 0xFFF7FFFF
#define S_000044_VIPH_INT(x) (((x) & 0x1) << 24)
#define G_000044_VIPH_INT(x) (((x) >> 24) & 0x1)
#define C_000044_VIPH_INT 0xFEFFFFFF
#define S_000044_SW_INT(x) (((x) & 0x1) << 25)
#define G_000044_SW_INT(x) (((x) >> 25) & 0x1)
#define C_000044_SW_INT 0xFDFFFFFF
#define S_000044_SW_INT_AK(x) (((x) & 0x1) << 25)
#define G_000044_SW_INT_AK(x) (((x) >> 25) & 0x1)
#define C_000044_SW_INT_AK 0xFDFFFFFF
#define S_000044_SW_INT_SET(x) (((x) & 0x1) << 26)
#define G_000044_SW_INT_SET(x) (((x) >> 26) & 0x1)
#define C_000044_SW_INT_SET 0xFBFFFFFF
#define S_000044_GEYSERVILLE_STAT(x) (((x) & 0x1) << 27)
#define G_000044_GEYSERVILLE_STAT(x) (((x) >> 27) & 0x1)
#define C_000044_GEYSERVILLE_STAT 0xF7FFFFFF
#define S_000044_GEYSERVILLE_STAT_AK(x) (((x) & 0x1) << 27)
#define G_000044_GEYSERVILLE_STAT_AK(x) (((x) >> 27) & 0x1)
#define C_000044_GEYSERVILLE_STAT_AK 0xF7FFFFFF
#define S_000044_HDCP_AUTHORIZED_INT_STAT(x) (((x) & 0x1) << 28)
#define G_000044_HDCP_AUTHORIZED_INT_STAT(x) (((x) >> 28) & 0x1)
#define C_000044_HDCP_AUTHORIZED_INT_STAT 0xEFFFFFFF
#define S_000044_HDCP_AUTHORIZED_INT_AK(x) (((x) & 0x1) << 28)
#define G_000044_HDCP_AUTHORIZED_INT_AK(x) (((x) >> 28) & 0x1)
#define C_000044_HDCP_AUTHORIZED_INT_AK 0xEFFFFFFF
#define S_000044_DVI_I2C_INT_STAT(x) (((x) & 0x1) << 29)
#define G_000044_DVI_I2C_INT_STAT(x) (((x) >> 29) & 0x1)
#define C_000044_DVI_I2C_INT_STAT 0xDFFFFFFF
#define S_000044_DVI_I2C_INT_AK(x) (((x) & 0x1) << 29)
#define G_000044_DVI_I2C_INT_AK(x) (((x) >> 29) & 0x1)
#define C_000044_DVI_I2C_INT_AK 0xDFFFFFFF
#define S_000044_GUIDMA_STAT(x) (((x) & 0x1) << 30)
#define G_000044_GUIDMA_STAT(x) (((x) >> 30) & 0x1)
#define C_000044_GUIDMA_STAT 0xBFFFFFFF
#define S_000044_GUIDMA_AK(x) (((x) & 0x1) << 30)
#define G_000044_GUIDMA_AK(x) (((x) >> 30) & 0x1)
#define C_000044_GUIDMA_AK 0xBFFFFFFF
#define S_000044_VIDDMA_STAT(x) (((x) & 0x1) << 31)
#define G_000044_VIDDMA_STAT(x) (((x) >> 31) & 0x1)
#define C_000044_VIDDMA_STAT 0x7FFFFFFF
#define S_000044_VIDDMA_AK(x) (((x) & 0x1) << 31)
#define G_000044_VIDDMA_AK(x) (((x) >> 31) & 0x1)
#define C_000044_VIDDMA_AK 0x7FFFFFFF
#define R_000050_CRTC_GEN_CNTL 0x000050
#define S_000050_CRTC_DBL_SCAN_EN(x) (((x) & 0x1) << 0)
#define G_000050_CRTC_DBL_SCAN_EN(x) (((x) >> 0) & 0x1)
#define C_000050_CRTC_DBL_SCAN_EN 0xFFFFFFFE
#define S_000050_CRTC_INTERLACE_EN(x) (((x) & 0x1) << 1)
#define G_000050_CRTC_INTERLACE_EN(x) (((x) >> 1) & 0x1)
#define C_000050_CRTC_INTERLACE_EN 0xFFFFFFFD
#define S_000050_CRTC_C_SYNC_EN(x) (((x) & 0x1) << 4)
#define G_000050_CRTC_C_SYNC_EN(x) (((x) >> 4) & 0x1)
#define C_000050_CRTC_C_SYNC_EN 0xFFFFFFEF
#define S_000050_CRTC_PIX_WIDTH(x) (((x) & 0xF) << 8)
#define G_000050_CRTC_PIX_WIDTH(x) (((x) >> 8) & 0xF)
#define C_000050_CRTC_PIX_WIDTH 0xFFFFF0FF
#define S_000050_CRTC_ICON_EN(x) (((x) & 0x1) << 15)
#define G_000050_CRTC_ICON_EN(x) (((x) >> 15) & 0x1)
#define C_000050_CRTC_ICON_EN 0xFFFF7FFF
#define S_000050_CRTC_CUR_EN(x) (((x) & 0x1) << 16)
#define G_000050_CRTC_CUR_EN(x) (((x) >> 16) & 0x1)
#define C_000050_CRTC_CUR_EN 0xFFFEFFFF
#define S_000050_CRTC_VSTAT_MODE(x) (((x) & 0x3) << 17)
#define G_000050_CRTC_VSTAT_MODE(x) (((x) >> 17) & 0x3)
#define C_000050_CRTC_VSTAT_MODE 0xFFF9FFFF
#define S_000050_CRTC_CUR_MODE(x) (((x) & 0x7) << 20)
#define G_000050_CRTC_CUR_MODE(x) (((x) >> 20) & 0x7)
#define C_000050_CRTC_CUR_MODE 0xFF8FFFFF
#define S_000050_CRTC_EXT_DISP_EN(x) (((x) & 0x1) << 24)
#define G_000050_CRTC_EXT_DISP_EN(x) (((x) >> 24) & 0x1)
#define C_000050_CRTC_EXT_DISP_EN 0xFEFFFFFF
#define S_000050_CRTC_EN(x) (((x) & 0x1) << 25)
#define G_000050_CRTC_EN(x) (((x) >> 25) & 0x1)
#define C_000050_CRTC_EN 0xFDFFFFFF
#define S_000050_CRTC_DISP_REQ_EN_B(x) (((x) & 0x1) << 26)
#define G_000050_CRTC_DISP_REQ_EN_B(x) (((x) >> 26) & 0x1)
#define C_000050_CRTC_DISP_REQ_EN_B 0xFBFFFFFF
#define R_000054_CRTC_EXT_CNTL 0x000054
#define S_000054_CRTC_VGA_XOVERSCAN(x) (((x) & 0x1) << 0)
#define G_000054_CRTC_VGA_XOVERSCAN(x) (((x) >> 0) & 0x1)
#define C_000054_CRTC_VGA_XOVERSCAN 0xFFFFFFFE
#define S_000054_VGA_BLINK_RATE(x) (((x) & 0x3) << 1)
#define G_000054_VGA_BLINK_RATE(x) (((x) >> 1) & 0x3)
#define C_000054_VGA_BLINK_RATE 0xFFFFFFF9
#define S_000054_VGA_ATI_LINEAR(x) (((x) & 0x1) << 3)
#define G_000054_VGA_ATI_LINEAR(x) (((x) >> 3) & 0x1)
#define C_000054_VGA_ATI_LINEAR 0xFFFFFFF7
#define S_000054_VGA_128KAP_PAGING(x) (((x) & 0x1) << 4)
#define G_000054_VGA_128KAP_PAGING(x) (((x) >> 4) & 0x1)
#define C_000054_VGA_128KAP_PAGING 0xFFFFFFEF
#define S_000054_VGA_TEXT_132(x) (((x) & 0x1) << 5)
#define G_000054_VGA_TEXT_132(x) (((x) >> 5) & 0x1)
#define C_000054_VGA_TEXT_132 0xFFFFFFDF
#define S_000054_VGA_XCRT_CNT_EN(x) (((x) & 0x1) << 6)
#define G_000054_VGA_XCRT_CNT_EN(x) (((x) >> 6) & 0x1)
#define C_000054_VGA_XCRT_CNT_EN 0xFFFFFFBF
#define S_000054_CRTC_HSYNC_DIS(x) (((x) & 0x1) << 8)
#define G_000054_CRTC_HSYNC_DIS(x) (((x) >> 8) & 0x1)
#define C_000054_CRTC_HSYNC_DIS 0xFFFFFEFF
#define S_000054_CRTC_VSYNC_DIS(x) (((x) & 0x1) << 9)
#define G_000054_CRTC_VSYNC_DIS(x) (((x) >> 9) & 0x1)
#define C_000054_CRTC_VSYNC_DIS 0xFFFFFDFF
#define S_000054_CRTC_DISPLAY_DIS(x) (((x) & 0x1) << 10)
#define G_000054_CRTC_DISPLAY_DIS(x) (((x) >> 10) & 0x1)
#define C_000054_CRTC_DISPLAY_DIS 0xFFFFFBFF
#define S_000054_CRTC_SYNC_TRISTATE(x) (((x) & 0x1) << 11)
#define G_000054_CRTC_SYNC_TRISTATE(x) (((x) >> 11) & 0x1)
#define C_000054_CRTC_SYNC_TRISTATE 0xFFFFF7FF
#define S_000054_CRTC_HSYNC_TRISTATE(x) (((x) & 0x1) << 12)
#define G_000054_CRTC_HSYNC_TRISTATE(x) (((x) >> 12) & 0x1)
#define C_000054_CRTC_HSYNC_TRISTATE 0xFFFFEFFF
#define S_000054_CRTC_VSYNC_TRISTATE(x) (((x) & 0x1) << 13)
#define G_000054_CRTC_VSYNC_TRISTATE(x) (((x) >> 13) & 0x1)
#define C_000054_CRTC_VSYNC_TRISTATE 0xFFFFDFFF
#define S_000054_CRT_ON(x) (((x) & 0x1) << 15)
#define G_000054_CRT_ON(x) (((x) >> 15) & 0x1)
#define C_000054_CRT_ON 0xFFFF7FFF
#define S_000054_VGA_CUR_B_TEST(x) (((x) & 0x1) << 17)
#define G_000054_VGA_CUR_B_TEST(x) (((x) >> 17) & 0x1)
#define C_000054_VGA_CUR_B_TEST 0xFFFDFFFF
#define S_000054_VGA_PACK_DIS(x) (((x) & 0x1) << 18)
#define G_000054_VGA_PACK_DIS(x) (((x) >> 18) & 0x1)
#define C_000054_VGA_PACK_DIS 0xFFFBFFFF
#define S_000054_VGA_MEM_PS_EN(x) (((x) & 0x1) << 19)
#define G_000054_VGA_MEM_PS_EN(x) (((x) >> 19) & 0x1)
#define C_000054_VGA_MEM_PS_EN 0xFFF7FFFF
#define S_000054_VCRTC_IDX_MASTER(x) (((x) & 0x7F) << 24)
#define G_000054_VCRTC_IDX_MASTER(x) (((x) >> 24) & 0x7F)
#define C_000054_VCRTC_IDX_MASTER 0x80FFFFFF
#define R_00023C_DISPLAY_BASE_ADDR 0x00023C
#define S_00023C_DISPLAY_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0)
#define G_00023C_DISPLAY_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF)
#define C_00023C_DISPLAY_BASE_ADDR 0x00000000
#define R_000260_CUR_OFFSET 0x000260
#define S_000260_CUR_OFFSET(x) (((x) & 0x7FFFFFF) << 0)
#define G_000260_CUR_OFFSET(x) (((x) >> 0) & 0x7FFFFFF)
#define C_000260_CUR_OFFSET 0xF8000000
#define S_000260_CUR_LOCK(x) (((x) & 0x1) << 31)
#define G_000260_CUR_LOCK(x) (((x) >> 31) & 0x1)
#define C_000260_CUR_LOCK 0x7FFFFFFF
#define R_00033C_CRTC2_DISPLAY_BASE_ADDR 0x00033C
#define S_00033C_CRTC2_DISPLAY_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0)
#define G_00033C_CRTC2_DISPLAY_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF)
#define C_00033C_CRTC2_DISPLAY_BASE_ADDR 0x00000000
#define R_000360_CUR2_OFFSET 0x000360
#define S_000360_CUR2_OFFSET(x) (((x) & 0x7FFFFFF) << 0)
#define G_000360_CUR2_OFFSET(x) (((x) >> 0) & 0x7FFFFFF)
#define C_000360_CUR2_OFFSET 0xF8000000
#define S_000360_CUR2_LOCK(x) (((x) & 0x1) << 31)
#define G_000360_CUR2_LOCK(x) (((x) >> 31) & 0x1)
#define C_000360_CUR2_LOCK 0x7FFFFFFF
#define R_0003C0_GENMO_WT 0x0003C0
#define S_0003C0_GENMO_MONO_ADDRESS_B(x) (((x) & 0x1) << 0)
#define G_0003C0_GENMO_MONO_ADDRESS_B(x) (((x) >> 0) & 0x1)
#define C_0003C0_GENMO_MONO_ADDRESS_B 0xFFFFFFFE
#define S_0003C0_VGA_RAM_EN(x) (((x) & 0x1) << 1)
#define G_0003C0_VGA_RAM_EN(x) (((x) >> 1) & 0x1)
#define C_0003C0_VGA_RAM_EN 0xFFFFFFFD
#define S_0003C0_VGA_CKSEL(x) (((x) & 0x3) << 2)
#define G_0003C0_VGA_CKSEL(x) (((x) >> 2) & 0x3)
#define C_0003C0_VGA_CKSEL 0xFFFFFFF3
#define S_0003C0_ODD_EVEN_MD_PGSEL(x) (((x) & 0x1) << 5)
#define G_0003C0_ODD_EVEN_MD_PGSEL(x) (((x) >> 5) & 0x1)
#define C_0003C0_ODD_EVEN_MD_PGSEL 0xFFFFFFDF
#define S_0003C0_VGA_HSYNC_POL(x) (((x) & 0x1) << 6)
#define G_0003C0_VGA_HSYNC_POL(x) (((x) >> 6) & 0x1)
#define C_0003C0_VGA_HSYNC_POL 0xFFFFFFBF
#define S_0003C0_VGA_VSYNC_POL(x) (((x) & 0x1) << 7)
#define G_0003C0_VGA_VSYNC_POL(x) (((x) >> 7) & 0x1)
#define C_0003C0_VGA_VSYNC_POL 0xFFFFFF7F
#define R_0003F8_CRTC2_GEN_CNTL 0x0003F8
#define S_0003F8_CRTC2_DBL_SCAN_EN(x) (((x) & 0x1) << 0)
#define G_0003F8_CRTC2_DBL_SCAN_EN(x) (((x) >> 0) & 0x1)
#define C_0003F8_CRTC2_DBL_SCAN_EN 0xFFFFFFFE
#define S_0003F8_CRTC2_INTERLACE_EN(x) (((x) & 0x1) << 1)
#define G_0003F8_CRTC2_INTERLACE_EN(x) (((x) >> 1) & 0x1)
#define C_0003F8_CRTC2_INTERLACE_EN 0xFFFFFFFD
#define S_0003F8_CRTC2_SYNC_TRISTATE(x) (((x) & 0x1) << 4)
#define G_0003F8_CRTC2_SYNC_TRISTATE(x) (((x) >> 4) & 0x1)
#define C_0003F8_CRTC2_SYNC_TRISTATE 0xFFFFFFEF
#define S_0003F8_CRTC2_HSYNC_TRISTATE(x) (((x) & 0x1) << 5)
#define G_0003F8_CRTC2_HSYNC_TRISTATE(x) (((x) >> 5) & 0x1)
#define C_0003F8_CRTC2_HSYNC_TRISTATE 0xFFFFFFDF
#define S_0003F8_CRTC2_VSYNC_TRISTATE(x) (((x) & 0x1) << 6)
#define G_0003F8_CRTC2_VSYNC_TRISTATE(x) (((x) >> 6) & 0x1)
#define C_0003F8_CRTC2_VSYNC_TRISTATE 0xFFFFFFBF
#define S_0003F8_CRT2_ON(x) (((x) & 0x1) << 7)
#define G_0003F8_CRT2_ON(x) (((x) >> 7) & 0x1)
#define C_0003F8_CRT2_ON 0xFFFFFF7F
#define S_0003F8_CRTC2_PIX_WIDTH(x) (((x) & 0xF) << 8)
#define G_0003F8_CRTC2_PIX_WIDTH(x) (((x) >> 8) & 0xF)
#define C_0003F8_CRTC2_PIX_WIDTH 0xFFFFF0FF
#define S_0003F8_CRTC2_ICON_EN(x) (((x) & 0x1) << 15)
#define G_0003F8_CRTC2_ICON_EN(x) (((x) >> 15) & 0x1)
#define C_0003F8_CRTC2_ICON_EN 0xFFFF7FFF
#define S_0003F8_CRTC2_CUR_EN(x) (((x) & 0x1) << 16)
#define G_0003F8_CRTC2_CUR_EN(x) (((x) >> 16) & 0x1)
#define C_0003F8_CRTC2_CUR_EN 0xFFFEFFFF
#define S_0003F8_CRTC2_CUR_MODE(x) (((x) & 0x7) << 20)
#define G_0003F8_CRTC2_CUR_MODE(x) (((x) >> 20) & 0x7)
#define C_0003F8_CRTC2_CUR_MODE 0xFF8FFFFF
#define S_0003F8_CRTC2_DISPLAY_DIS(x) (((x) & 0x1) << 23)
#define G_0003F8_CRTC2_DISPLAY_DIS(x) (((x) >> 23) & 0x1)
#define C_0003F8_CRTC2_DISPLAY_DIS 0xFF7FFFFF
#define S_0003F8_CRTC2_EN(x) (((x) & 0x1) << 25)
#define G_0003F8_CRTC2_EN(x) (((x) >> 25) & 0x1)
#define C_0003F8_CRTC2_EN 0xFDFFFFFF
#define S_0003F8_CRTC2_DISP_REQ_EN_B(x) (((x) & 0x1) << 26)
#define G_0003F8_CRTC2_DISP_REQ_EN_B(x) (((x) >> 26) & 0x1)
#define C_0003F8_CRTC2_DISP_REQ_EN_B 0xFBFFFFFF
#define S_0003F8_CRTC2_C_SYNC_EN(x) (((x) & 0x1) << 27)
#define G_0003F8_CRTC2_C_SYNC_EN(x) (((x) >> 27) & 0x1)
#define C_0003F8_CRTC2_C_SYNC_EN 0xF7FFFFFF
#define S_0003F8_CRTC2_HSYNC_DIS(x) (((x) & 0x1) << 28)
#define G_0003F8_CRTC2_HSYNC_DIS(x) (((x) >> 28) & 0x1)
#define C_0003F8_CRTC2_HSYNC_DIS 0xEFFFFFFF
#define S_0003F8_CRTC2_VSYNC_DIS(x) (((x) & 0x1) << 29)
#define G_0003F8_CRTC2_VSYNC_DIS(x) (((x) >> 29) & 0x1)
#define C_0003F8_CRTC2_VSYNC_DIS 0xDFFFFFFF
#define R_000420_OV0_SCALE_CNTL 0x000420
#define S_000420_OV0_NO_READ_BEHIND_SCAN(x) (((x) & 0x1) << 1)
#define G_000420_OV0_NO_READ_BEHIND_SCAN(x) (((x) >> 1) & 0x1)
#define C_000420_OV0_NO_READ_BEHIND_SCAN 0xFFFFFFFD
#define S_000420_OV0_HORZ_PICK_NEAREST(x) (((x) & 0x1) << 2)
#define G_000420_OV0_HORZ_PICK_NEAREST(x) (((x) >> 2) & 0x1)
#define C_000420_OV0_HORZ_PICK_NEAREST 0xFFFFFFFB
#define S_000420_OV0_VERT_PICK_NEAREST(x) (((x) & 0x1) << 3)
#define G_000420_OV0_VERT_PICK_NEAREST(x) (((x) >> 3) & 0x1)
#define C_000420_OV0_VERT_PICK_NEAREST 0xFFFFFFF7
#define S_000420_OV0_SIGNED_UV(x) (((x) & 0x1) << 4)
#define G_000420_OV0_SIGNED_UV(x) (((x) >> 4) & 0x1)
#define C_000420_OV0_SIGNED_UV 0xFFFFFFEF
#define S_000420_OV0_GAMMA_SEL(x) (((x) & 0x7) << 5)
#define G_000420_OV0_GAMMA_SEL(x) (((x) >> 5) & 0x7)
#define C_000420_OV0_GAMMA_SEL 0xFFFFFF1F
#define S_000420_OV0_SURFACE_FORMAT(x) (((x) & 0xF) << 8)
#define G_000420_OV0_SURFACE_FORMAT(x) (((x) >> 8) & 0xF)
#define C_000420_OV0_SURFACE_FORMAT 0xFFFFF0FF
#define S_000420_OV0_ADAPTIVE_DEINT(x) (((x) & 0x1) << 12)
#define G_000420_OV0_ADAPTIVE_DEINT(x) (((x) >> 12) & 0x1)
#define C_000420_OV0_ADAPTIVE_DEINT 0xFFFFEFFF
#define S_000420_OV0_CRTC_SEL(x) (((x) & 0x1) << 14)
#define G_000420_OV0_CRTC_SEL(x) (((x) >> 14) & 0x1)
#define C_000420_OV0_CRTC_SEL 0xFFFFBFFF
#define S_000420_OV0_BURST_PER_PLANE(x) (((x) & 0x7F) << 16)
#define G_000420_OV0_BURST_PER_PLANE(x) (((x) >> 16) & 0x7F)
#define C_000420_OV0_BURST_PER_PLANE 0xFF80FFFF
#define S_000420_OV0_DOUBLE_BUFFER_REGS(x) (((x) & 0x1) << 24)
#define G_000420_OV0_DOUBLE_BUFFER_REGS(x) (((x) >> 24) & 0x1)
#define C_000420_OV0_DOUBLE_BUFFER_REGS 0xFEFFFFFF
#define S_000420_OV0_BANDWIDTH(x) (((x) & 0x1) << 26)
#define G_000420_OV0_BANDWIDTH(x) (((x) >> 26) & 0x1)
#define C_000420_OV0_BANDWIDTH 0xFBFFFFFF
#define S_000420_OV0_LIN_TRANS_BYPASS(x) (((x) & 0x1) << 28)
#define G_000420_OV0_LIN_TRANS_BYPASS(x) (((x) >> 28) & 0x1)
#define C_000420_OV0_LIN_TRANS_BYPASS 0xEFFFFFFF
#define S_000420_OV0_INT_EMU(x) (((x) & 0x1) << 29)
#define G_000420_OV0_INT_EMU(x) (((x) >> 29) & 0x1)
#define C_000420_OV0_INT_EMU 0xDFFFFFFF
#define S_000420_OV0_OVERLAY_EN(x) (((x) & 0x1) << 30)
#define G_000420_OV0_OVERLAY_EN(x) (((x) >> 30) & 0x1)
#define C_000420_OV0_OVERLAY_EN 0xBFFFFFFF
#define S_000420_OV0_SOFT_RESET(x) (((x) & 0x1) << 31)
#define G_000420_OV0_SOFT_RESET(x) (((x) >> 31) & 0x1)
#define C_000420_OV0_SOFT_RESET 0x7FFFFFFF
#define R_00070C_CP_RB_RPTR_ADDR 0x00070C
#define S_00070C_RB_RPTR_SWAP(x) (((x) & 0x3) << 0)
#define G_00070C_RB_RPTR_SWAP(x) (((x) >> 0) & 0x3)
#define C_00070C_RB_RPTR_SWAP 0xFFFFFFFC
#define S_00070C_RB_RPTR_ADDR(x) (((x) & 0x3FFFFFFF) << 2)
#define G_00070C_RB_RPTR_ADDR(x) (((x) >> 2) & 0x3FFFFFFF)
#define C_00070C_RB_RPTR_ADDR 0x00000003
#define R_000740_CP_CSQ_CNTL 0x000740
#define S_000740_CSQ_CNT_PRIMARY(x) (((x) & 0xFF) << 0)
#define G_000740_CSQ_CNT_PRIMARY(x) (((x) >> 0) & 0xFF)
#define C_000740_CSQ_CNT_PRIMARY 0xFFFFFF00
#define S_000740_CSQ_CNT_INDIRECT(x) (((x) & 0xFF) << 8)
#define G_000740_CSQ_CNT_INDIRECT(x) (((x) >> 8) & 0xFF)
#define C_000740_CSQ_CNT_INDIRECT 0xFFFF00FF
#define S_000740_CSQ_MODE(x) (((x) & 0xF) << 28)
#define G_000740_CSQ_MODE(x) (((x) >> 28) & 0xF)
#define C_000740_CSQ_MODE 0x0FFFFFFF
#define R_000770_SCRATCH_UMSK 0x000770
#define S_000770_SCRATCH_UMSK(x) (((x) & 0x3F) << 0)
#define G_000770_SCRATCH_UMSK(x) (((x) >> 0) & 0x3F)
#define C_000770_SCRATCH_UMSK 0xFFFFFFC0
#define S_000770_SCRATCH_SWAP(x) (((x) & 0x3) << 16)
#define G_000770_SCRATCH_SWAP(x) (((x) >> 16) & 0x3)
#define C_000770_SCRATCH_SWAP 0xFFFCFFFF
#define R_000774_SCRATCH_ADDR 0x000774
#define S_000774_SCRATCH_ADDR(x) (((x) & 0x7FFFFFF) << 5)
#define G_000774_SCRATCH_ADDR(x) (((x) >> 5) & 0x7FFFFFF)
#define C_000774_SCRATCH_ADDR 0x0000001F
#define R_000E40_RBBM_STATUS 0x000E40
#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0)
#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F)
#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80
#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8)
#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1)
#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF
#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9)
#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1)
#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF
#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10)
#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1)
#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF
#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11)
#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1)
#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF
#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12)
#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1)
#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF
#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13)
#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1)
#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF
#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14)
#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1)
#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF
#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15)
#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1)
#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF
#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16)
#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1)
#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF
#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17)
#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1)
#define C_000E40_E2_BUSY 0xFFFDFFFF
#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18)
#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1)
#define C_000E40_RB2D_BUSY 0xFFFBFFFF
#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19)
#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1)
#define C_000E40_RB3D_BUSY 0xFFF7FFFF
#define S_000E40_SE_BUSY(x) (((x) & 0x1) << 20)
#define G_000E40_SE_BUSY(x) (((x) >> 20) & 0x1)
#define C_000E40_SE_BUSY 0xFFEFFFFF
#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21)
#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1)
#define C_000E40_RE_BUSY 0xFFDFFFFF
#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22)
#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1)
#define C_000E40_TAM_BUSY 0xFFBFFFFF
#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23)
#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1)
#define C_000E40_TDM_BUSY 0xFF7FFFFF
#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24)
#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1)
#define C_000E40_PB_BUSY 0xFEFFFFFF
#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31)
#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1)
#define C_000E40_GUI_ACTIVE 0x7FFFFFFF
 
#endif
/drivers/video/drm/radeon/r200.c
0,0 → 1,458
/*
* Copyright 2008 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
* Copyright 2009 Jerome Glisse.
*
* 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
* Jerome Glisse
*/
#include "drmP.h"
#include "drm.h"
#include "radeon_drm.h"
#include "radeon_reg.h"
#include "radeon.h"
 
#include "r200_reg_safe.h"
 
//#include "r100_track.h"
 
#if 0
static int r200_get_vtx_size_0(uint32_t vtx_fmt_0)
{
int vtx_size, i;
vtx_size = 2;
 
if (vtx_fmt_0 & R200_VTX_Z0)
vtx_size++;
if (vtx_fmt_0 & R200_VTX_W0)
vtx_size++;
/* blend weight */
if (vtx_fmt_0 & (0x7 << R200_VTX_WEIGHT_COUNT_SHIFT))
vtx_size += (vtx_fmt_0 >> R200_VTX_WEIGHT_COUNT_SHIFT) & 0x7;
if (vtx_fmt_0 & R200_VTX_PV_MATRIX_SEL)
vtx_size++;
if (vtx_fmt_0 & R200_VTX_N0)
vtx_size += 3;
if (vtx_fmt_0 & R200_VTX_POINT_SIZE)
vtx_size++;
if (vtx_fmt_0 & R200_VTX_DISCRETE_FOG)
vtx_size++;
if (vtx_fmt_0 & R200_VTX_SHININESS_0)
vtx_size++;
if (vtx_fmt_0 & R200_VTX_SHININESS_1)
vtx_size++;
for (i = 0; i < 8; i++) {
int color_size = (vtx_fmt_0 >> (11 + 2*i)) & 0x3;
switch (color_size) {
case 0: break;
case 1: vtx_size++; break;
case 2: vtx_size += 3; break;
case 3: vtx_size += 4; break;
}
}
if (vtx_fmt_0 & R200_VTX_XY1)
vtx_size += 2;
if (vtx_fmt_0 & R200_VTX_Z1)
vtx_size++;
if (vtx_fmt_0 & R200_VTX_W1)
vtx_size++;
if (vtx_fmt_0 & R200_VTX_N1)
vtx_size += 3;
return vtx_size;
}
 
static int r200_get_vtx_size_1(uint32_t vtx_fmt_1)
{
int vtx_size, i, tex_size;
vtx_size = 0;
for (i = 0; i < 6; i++) {
tex_size = (vtx_fmt_1 >> (i * 3)) & 0x7;
if (tex_size > 4)
continue;
vtx_size += tex_size;
}
return vtx_size;
}
 
int r200_packet0_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt,
unsigned idx, unsigned reg)
{
struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_reloc *reloc;
struct r100_cs_track *track;
volatile uint32_t *ib;
uint32_t tmp;
int r;
int i;
int face;
u32 tile_flags = 0;
 
ib = p->ib->ptr;
ib_chunk = &p->chunks[p->chunk_ib_idx];
track = (struct r100_cs_track *)p->track;
 
switch (reg) {
case RADEON_CRTC_GUI_TRIG_VLINE:
r = r100_cs_packet_parse_vline(p);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
break;
/* FIXME: only allow PACKET3 blit? easier to check for out of
* range access */
case RADEON_DST_PITCH_OFFSET:
case RADEON_SRC_PITCH_OFFSET:
r = r100_reloc_pitch_offset(p, pkt, idx, reg);
if (r)
return r;
break;
case RADEON_RB3D_DEPTHOFFSET:
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
track->zb.robj = reloc->robj;
track->zb.offset = ib_chunk->kdata[idx];
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
break;
case RADEON_RB3D_COLOROFFSET:
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
track->cb[0].robj = reloc->robj;
track->cb[0].offset = ib_chunk->kdata[idx];
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
break;
case R200_PP_TXOFFSET_0:
case R200_PP_TXOFFSET_1:
case R200_PP_TXOFFSET_2:
case R200_PP_TXOFFSET_3:
case R200_PP_TXOFFSET_4:
case R200_PP_TXOFFSET_5:
i = (reg - R200_PP_TXOFFSET_0) / 24;
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
track->textures[i].robj = reloc->robj;
break;
case R200_PP_CUBIC_OFFSET_F1_0:
case R200_PP_CUBIC_OFFSET_F2_0:
case R200_PP_CUBIC_OFFSET_F3_0:
case R200_PP_CUBIC_OFFSET_F4_0:
case R200_PP_CUBIC_OFFSET_F5_0:
case R200_PP_CUBIC_OFFSET_F1_1:
case R200_PP_CUBIC_OFFSET_F2_1:
case R200_PP_CUBIC_OFFSET_F3_1:
case R200_PP_CUBIC_OFFSET_F4_1:
case R200_PP_CUBIC_OFFSET_F5_1:
case R200_PP_CUBIC_OFFSET_F1_2:
case R200_PP_CUBIC_OFFSET_F2_2:
case R200_PP_CUBIC_OFFSET_F3_2:
case R200_PP_CUBIC_OFFSET_F4_2:
case R200_PP_CUBIC_OFFSET_F5_2:
case R200_PP_CUBIC_OFFSET_F1_3:
case R200_PP_CUBIC_OFFSET_F2_3:
case R200_PP_CUBIC_OFFSET_F3_3:
case R200_PP_CUBIC_OFFSET_F4_3:
case R200_PP_CUBIC_OFFSET_F5_3:
case R200_PP_CUBIC_OFFSET_F1_4:
case R200_PP_CUBIC_OFFSET_F2_4:
case R200_PP_CUBIC_OFFSET_F3_4:
case R200_PP_CUBIC_OFFSET_F4_4:
case R200_PP_CUBIC_OFFSET_F5_4:
case R200_PP_CUBIC_OFFSET_F1_5:
case R200_PP_CUBIC_OFFSET_F2_5:
case R200_PP_CUBIC_OFFSET_F3_5:
case R200_PP_CUBIC_OFFSET_F4_5:
case R200_PP_CUBIC_OFFSET_F5_5:
i = (reg - R200_PP_TXOFFSET_0) / 24;
face = (reg - ((i * 24) + R200_PP_TXOFFSET_0)) / 4;
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
track->textures[i].cube_info[face - 1].offset = ib_chunk->kdata[idx];
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
track->textures[i].cube_info[face - 1].robj = reloc->robj;
break;
case RADEON_RE_WIDTH_HEIGHT:
track->maxy = ((ib_chunk->kdata[idx] >> 16) & 0x7FF);
break;
case RADEON_RB3D_COLORPITCH:
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
 
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
tile_flags |= RADEON_COLOR_TILE_ENABLE;
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
 
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
tmp |= tile_flags;
ib[idx] = tmp;
 
track->cb[0].pitch = ib_chunk->kdata[idx] & RADEON_COLORPITCH_MASK;
break;
case RADEON_RB3D_DEPTHPITCH:
track->zb.pitch = ib_chunk->kdata[idx] & RADEON_DEPTHPITCH_MASK;
break;
case RADEON_RB3D_CNTL:
switch ((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
case 7:
case 8:
case 9:
case 11:
case 12:
track->cb[0].cpp = 1;
break;
case 3:
case 4:
case 15:
track->cb[0].cpp = 2;
break;
case 6:
track->cb[0].cpp = 4;
break;
default:
DRM_ERROR("Invalid color buffer format (%d) !\n",
((ib_chunk->kdata[idx] >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
return -EINVAL;
}
if (ib_chunk->kdata[idx] & RADEON_DEPTHXY_OFFSET_ENABLE) {
DRM_ERROR("No support for depth xy offset in kms\n");
return -EINVAL;
}
 
track->z_enabled = !!(ib_chunk->kdata[idx] & RADEON_Z_ENABLE);
break;
case RADEON_RB3D_ZSTENCILCNTL:
switch (ib_chunk->kdata[idx] & 0xf) {
case 0:
track->zb.cpp = 2;
break;
case 2:
case 3:
case 4:
case 5:
case 9:
case 11:
track->zb.cpp = 4;
break;
default:
break;
}
break;
case RADEON_RB3D_ZPASS_ADDR:
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
break;
case RADEON_PP_CNTL:
{
uint32_t temp = ib_chunk->kdata[idx] >> 4;
for (i = 0; i < track->num_texture; i++)
track->textures[i].enabled = !!(temp & (1 << i));
}
break;
case RADEON_SE_VF_CNTL:
track->vap_vf_cntl = ib_chunk->kdata[idx];
break;
case 0x210c:
/* VAP_VF_MAX_VTX_INDX */
track->max_indx = ib_chunk->kdata[idx] & 0x00FFFFFFUL;
break;
case R200_SE_VTX_FMT_0:
track->vtx_size = r200_get_vtx_size_0(ib_chunk->kdata[idx]);
break;
case R200_SE_VTX_FMT_1:
track->vtx_size += r200_get_vtx_size_1(ib_chunk->kdata[idx]);
break;
case R200_PP_TXSIZE_0:
case R200_PP_TXSIZE_1:
case R200_PP_TXSIZE_2:
case R200_PP_TXSIZE_3:
case R200_PP_TXSIZE_4:
case R200_PP_TXSIZE_5:
i = (reg - R200_PP_TXSIZE_0) / 32;
track->textures[i].width = (ib_chunk->kdata[idx] & RADEON_TEX_USIZE_MASK) + 1;
track->textures[i].height = ((ib_chunk->kdata[idx] & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
break;
case R200_PP_TXPITCH_0:
case R200_PP_TXPITCH_1:
case R200_PP_TXPITCH_2:
case R200_PP_TXPITCH_3:
case R200_PP_TXPITCH_4:
case R200_PP_TXPITCH_5:
i = (reg - R200_PP_TXPITCH_0) / 32;
track->textures[i].pitch = ib_chunk->kdata[idx] + 32;
break;
case R200_PP_TXFILTER_0:
case R200_PP_TXFILTER_1:
case R200_PP_TXFILTER_2:
case R200_PP_TXFILTER_3:
case R200_PP_TXFILTER_4:
case R200_PP_TXFILTER_5:
i = (reg - R200_PP_TXFILTER_0) / 32;
track->textures[i].num_levels = ((ib_chunk->kdata[idx] & R200_MAX_MIP_LEVEL_MASK)
>> R200_MAX_MIP_LEVEL_SHIFT);
tmp = (ib_chunk->kdata[idx] >> 23) & 0x7;
if (tmp == 2 || tmp == 6)
track->textures[i].roundup_w = false;
tmp = (ib_chunk->kdata[idx] >> 27) & 0x7;
if (tmp == 2 || tmp == 6)
track->textures[i].roundup_h = false;
break;
case R200_PP_TXMULTI_CTL_0:
case R200_PP_TXMULTI_CTL_1:
case R200_PP_TXMULTI_CTL_2:
case R200_PP_TXMULTI_CTL_3:
case R200_PP_TXMULTI_CTL_4:
case R200_PP_TXMULTI_CTL_5:
i = (reg - R200_PP_TXMULTI_CTL_0) / 32;
break;
case R200_PP_TXFORMAT_X_0:
case R200_PP_TXFORMAT_X_1:
case R200_PP_TXFORMAT_X_2:
case R200_PP_TXFORMAT_X_3:
case R200_PP_TXFORMAT_X_4:
case R200_PP_TXFORMAT_X_5:
i = (reg - R200_PP_TXFORMAT_X_0) / 32;
track->textures[i].txdepth = ib_chunk->kdata[idx] & 0x7;
tmp = (ib_chunk->kdata[idx] >> 16) & 0x3;
/* 2D, 3D, CUBE */
switch (tmp) {
case 0:
case 5:
case 6:
case 7:
track->textures[i].tex_coord_type = 0;
break;
case 1:
track->textures[i].tex_coord_type = 1;
break;
case 2:
track->textures[i].tex_coord_type = 2;
break;
}
break;
case R200_PP_TXFORMAT_0:
case R200_PP_TXFORMAT_1:
case R200_PP_TXFORMAT_2:
case R200_PP_TXFORMAT_3:
case R200_PP_TXFORMAT_4:
case R200_PP_TXFORMAT_5:
i = (reg - R200_PP_TXFORMAT_0) / 32;
if (ib_chunk->kdata[idx] & R200_TXFORMAT_NON_POWER2) {
track->textures[i].use_pitch = 1;
} else {
track->textures[i].use_pitch = 0;
track->textures[i].width = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
track->textures[i].height = 1 << ((ib_chunk->kdata[idx] >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
}
switch ((ib_chunk->kdata[idx] & RADEON_TXFORMAT_FORMAT_MASK)) {
case R200_TXFORMAT_I8:
case R200_TXFORMAT_RGB332:
case R200_TXFORMAT_Y8:
track->textures[i].cpp = 1;
break;
case R200_TXFORMAT_DXT1:
case R200_TXFORMAT_AI88:
case R200_TXFORMAT_ARGB1555:
case R200_TXFORMAT_RGB565:
case R200_TXFORMAT_ARGB4444:
case R200_TXFORMAT_VYUY422:
case R200_TXFORMAT_YVYU422:
case R200_TXFORMAT_LDVDU655:
case R200_TXFORMAT_DVDU88:
case R200_TXFORMAT_AVYU4444:
track->textures[i].cpp = 2;
break;
case R200_TXFORMAT_ARGB8888:
case R200_TXFORMAT_RGBA8888:
case R200_TXFORMAT_ABGR8888:
case R200_TXFORMAT_BGR111110:
case R200_TXFORMAT_LDVDU8888:
case R200_TXFORMAT_DXT23:
case R200_TXFORMAT_DXT45:
track->textures[i].cpp = 4;
break;
}
track->textures[i].cube_info[4].width = 1 << ((ib_chunk->kdata[idx] >> 16) & 0xf);
track->textures[i].cube_info[4].height = 1 << ((ib_chunk->kdata[idx] >> 20) & 0xf);
break;
case R200_PP_CUBIC_FACES_0:
case R200_PP_CUBIC_FACES_1:
case R200_PP_CUBIC_FACES_2:
case R200_PP_CUBIC_FACES_3:
case R200_PP_CUBIC_FACES_4:
case R200_PP_CUBIC_FACES_5:
tmp = ib_chunk->kdata[idx];
i = (reg - R200_PP_CUBIC_FACES_0) / 32;
for (face = 0; face < 4; face++) {
track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf);
}
break;
default:
printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
reg, idx);
return -EINVAL;
}
return 0;
}
#endif
 
int r200_init(struct radeon_device *rdev)
{
rdev->config.r100.reg_safe_bm = r200_reg_safe_bm;
rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r200_reg_safe_bm);
return 0;
}
/drivers/video/drm/radeon/r200_reg_safe.h
0,0 → 1,28
static const unsigned r200_reg_safe_bm[102] = {
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF,
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFE7FE1F, 0xF003FFFF, 0x7EFFFFFF, 0xFFFF803C,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFEFCE, 0xFFFEFFFF, 0xFFFFFFFE,
0x020E0FF0, 0xFFFC83FD, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFBFFFF, 0xEFFCFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xDFDFDFDF, 0x3FFDDFDF, 0xFFFFFFFF, 0xFFFFFF7F,
0xFFFFFFFF, 0x00FFFFFF, 0x00000000, 0x00000000,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFE3F, 0xFFFFFFEF,
};
/drivers/video/drm/radeon/r300.c
25,12 → 25,17
* Alex Deucher
* Jerome Glisse
*/
//#include <linux/seq_file.h>
#include <linux/seq_file.h>
#include "drmP.h"
#include "drm.h"
#include "radeon_reg.h"
#include "radeon.h"
#include "radeon_drm.h"
 
#include "r300d.h"
 
#include "r300_reg_safe.h"
 
/* r300,r350,rv350,rv370,rv380 depends on : */
void r100_hdp_reset(struct radeon_device *rdev);
int r100_cp_reset(struct radeon_device *rdev);
37,7 → 42,6
int r100_rb2d_reset(struct radeon_device *rdev);
int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
int r100_pci_gart_enable(struct radeon_device *rdev);
void r100_pci_gart_disable(struct radeon_device *rdev);
void r100_mc_setup(struct radeon_device *rdev);
void r100_mc_disable_clients(struct radeon_device *rdev);
int r100_gui_wait_for_idle(struct radeon_device *rdev);
44,14 → 48,11
int r100_cs_packet_parse(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt,
unsigned idx);
int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
struct radeon_cs_reloc **cs_reloc);
int r100_cs_packet_parse_vline(struct radeon_cs_parser *p);
int r100_cs_parse_packet0(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt,
const unsigned *auth, unsigned n,
radeon_packet0_check_t check);
void r100_cs_dump_packet(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt);
int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt,
struct radeon_object *robj);
80,30 → 81,61
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp | RADEON_PCIE_TX_GART_INVALIDATE_TLB);
(void)RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
}
mb();
}
 
int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
{
void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
 
if (i < 0 || i > rdev->gart.num_gpu_pages) {
return -EINVAL;
}
addr = (lower_32_bits(addr) >> 8) |
((upper_32_bits(addr) & 0xff) << 24) |
0xc;
/* on x86 we want this to be CPU endian, on powerpc
* on powerpc without HW swappers, it'll get swapped on way
* into VRAM - so no need for cpu_to_le32 on VRAM tables */
writel(addr, ((void __iomem *)ptr) + (i * 4));
return 0;
}
 
int rv370_pcie_gart_enable(struct radeon_device *rdev)
int rv370_pcie_gart_init(struct radeon_device *rdev)
{
uint32_t table_addr;
uint32_t tmp;
int r;
 
if (rdev->gart.table.vram.robj) {
WARN(1, "RV370 PCIE GART already initialized.\n");
return 0;
}
/* Initialize common gart structure */
r = radeon_gart_init(rdev);
if (r) {
if (r)
return r;
}
r = rv370_debugfs_pcie_gart_info_init(rdev);
if (r) {
if (r)
DRM_ERROR("Failed to register debugfs file for PCIE gart !\n");
rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
return radeon_gart_table_vram_alloc(rdev);
}
rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
r = radeon_gart_table_vram_alloc(rdev);
if (r) {
 
int rv370_pcie_gart_enable(struct radeon_device *rdev)
{
uint32_t table_addr;
uint32_t tmp;
int r;
 
if (rdev->gart.table.vram.robj == NULL) {
dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
return -EINVAL;
}
r = radeon_gart_table_vram_pin(rdev);
if (r)
return r;
}
/* discard memory request outside of configured range */
tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
125,7 → 157,7
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
rv370_pcie_gart_tlb_flush(rdev);
DRM_INFO("PCIE GART of %uM enabled (table at 0x%08X).\n",
rdev->mc.gtt_size >> 20, table_addr);
(unsigned)(rdev->mc.gtt_size >> 20), table_addr);
rdev->gart.ready = true;
return 0;
}
143,40 → 175,13
}
}
 
int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
void rv370_pcie_gart_fini(struct radeon_device *rdev)
{
void __iomem *ptr = (void *)rdev->gart.table.vram.ptr;
 
if (i < 0 || i > rdev->gart.num_gpu_pages) {
return -EINVAL;
}
addr = (((u32)addr) >> 8) | ((upper_32_bits(addr) & 0xff) << 4) | 0xC;
writel(cpu_to_le32(addr), ((void __iomem *)ptr) + (i * 4));
return 0;
}
 
int r300_gart_enable(struct radeon_device *rdev)
{
#if __OS_HAS_AGP
if (rdev->flags & RADEON_IS_AGP) {
if (rdev->family > CHIP_RV350) {
rv370_pcie_gart_disable(rdev);
} else {
r100_pci_gart_disable(rdev);
radeon_gart_table_vram_free(rdev);
radeon_gart_fini(rdev);
}
return 0;
}
#endif
if (rdev->flags & RADEON_IS_PCIE) {
rdev->asic->gart_disable = &rv370_pcie_gart_disable;
rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
return rv370_pcie_gart_enable(rdev);
}
return r100_pci_gart_enable(rdev);
}
 
 
/*
* MC
*/
197,16 → 202,6
/* Setup GPU memory space */
rdev->mc.vram_location = 0xFFFFFFFFUL;
rdev->mc.gtt_location = 0xFFFFFFFFUL;
if (rdev->flags & RADEON_IS_AGP) {
r = radeon_agp_init(rdev);
if (r) {
printk(KERN_WARNING "[drm] Disabling AGP\n");
rdev->flags &= ~RADEON_IS_AGP;
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
} else {
rdev->mc.gtt_location = rdev->mc.agp_base;
}
}
r = radeon_mc_setup(rdev);
if (r) {
return r;
224,15 → 219,7
 
void r300_mc_fini(struct radeon_device *rdev)
{
if (rdev->flags & RADEON_IS_PCIE) {
rv370_pcie_gart_disable(rdev);
radeon_gart_table_vram_free(rdev);
} else {
r100_pci_gart_disable(rdev);
radeon_gart_table_ram_free(rdev);
}
radeon_gart_fini(rdev);
}
 
 
/*
444,6 → 431,7
/* rv350,rv370,rv380 */
rdev->num_gb_pipes = 1;
}
rdev->num_z_pipes = 1;
gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16);
switch (rdev->num_gb_pipes) {
case 2:
482,7 → 470,8
printk(KERN_WARNING "Failed to wait MC idle while "
"programming pipes. Bad things might happen.\n");
}
DRM_INFO("radeon: %d pipes initialized.\n", rdev->num_gb_pipes);
DRM_INFO("radeon: %d quad pipes, %d Z pipes initialized.\n",
rdev->num_gb_pipes, rdev->num_z_pipes);
}
 
int r300_ga_reset(struct radeon_device *rdev)
583,35 → 572,12
} else {
rdev->mc.vram_width = 64;
}
rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
 
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
r100_vram_init_sizes(rdev);
}
 
 
/*
* Indirect registers accessor
*/
uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg)
{
uint32_t r;
 
WREG8(RADEON_PCIE_INDEX, ((reg) & 0xff));
(void)RREG32(RADEON_PCIE_INDEX);
r = RREG32(RADEON_PCIE_DATA);
return r;
}
 
void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
{
WREG8(RADEON_PCIE_INDEX, ((reg) & 0xff));
(void)RREG32(RADEON_PCIE_INDEX);
WREG32(RADEON_PCIE_DATA, (v));
(void)RREG32(RADEON_PCIE_DATA);
}
 
/*
* PCIE Lanes
*/
 
722,304 → 688,6
/*
* CS functions
*/
struct r300_cs_track_cb {
struct radeon_object *robj;
unsigned pitch;
unsigned cpp;
unsigned offset;
};
 
struct r300_cs_track_array {
struct radeon_object *robj;
unsigned esize;
};
 
struct r300_cs_track_texture {
struct radeon_object *robj;
unsigned pitch;
unsigned width;
unsigned height;
unsigned num_levels;
unsigned cpp;
unsigned tex_coord_type;
unsigned txdepth;
unsigned width_11;
unsigned height_11;
bool use_pitch;
bool enabled;
bool roundup_w;
bool roundup_h;
};
 
struct r300_cs_track {
unsigned num_cb;
unsigned maxy;
unsigned vtx_size;
unsigned vap_vf_cntl;
unsigned immd_dwords;
unsigned num_arrays;
unsigned max_indx;
struct r300_cs_track_array arrays[11];
struct r300_cs_track_cb cb[4];
struct r300_cs_track_cb zb;
struct r300_cs_track_texture textures[16];
bool z_enabled;
};
 
static inline void r300_cs_track_texture_print(struct r300_cs_track_texture *t)
{
DRM_ERROR("pitch %d\n", t->pitch);
DRM_ERROR("width %d\n", t->width);
DRM_ERROR("height %d\n", t->height);
DRM_ERROR("num levels %d\n", t->num_levels);
DRM_ERROR("depth %d\n", t->txdepth);
DRM_ERROR("bpp %d\n", t->cpp);
DRM_ERROR("coordinate type %d\n", t->tex_coord_type);
DRM_ERROR("width round to power of 2 %d\n", t->roundup_w);
DRM_ERROR("height round to power of 2 %d\n", t->roundup_h);
}
 
static inline int r300_cs_track_texture_check(struct radeon_device *rdev,
struct r300_cs_track *track)
{
struct radeon_object *robj;
unsigned long size;
unsigned u, i, w, h;
 
for (u = 0; u < 16; u++) {
if (!track->textures[u].enabled)
continue;
robj = track->textures[u].robj;
if (robj == NULL) {
DRM_ERROR("No texture bound to unit %u\n", u);
return -EINVAL;
}
size = 0;
for (i = 0; i <= track->textures[u].num_levels; i++) {
if (track->textures[u].use_pitch) {
w = track->textures[u].pitch / (1 << i);
} else {
w = track->textures[u].width / (1 << i);
if (rdev->family >= CHIP_RV515)
w |= track->textures[u].width_11;
if (track->textures[u].roundup_w)
w = roundup_pow_of_two(w);
}
h = track->textures[u].height / (1 << i);
if (rdev->family >= CHIP_RV515)
h |= track->textures[u].height_11;
if (track->textures[u].roundup_h)
h = roundup_pow_of_two(h);
size += w * h;
}
size *= track->textures[u].cpp;
switch (track->textures[u].tex_coord_type) {
case 0:
break;
case 1:
size *= (1 << track->textures[u].txdepth);
break;
case 2:
size *= 6;
break;
default:
DRM_ERROR("Invalid texture coordinate type %u for unit "
"%u\n", track->textures[u].tex_coord_type, u);
return -EINVAL;
}
if (size > radeon_object_size(robj)) {
DRM_ERROR("Texture of unit %u needs %lu bytes but is "
"%lu\n", u, size, radeon_object_size(robj));
r300_cs_track_texture_print(&track->textures[u]);
return -EINVAL;
}
}
return 0;
}
 
int r300_cs_track_check(struct radeon_device *rdev, struct r300_cs_track *track)
{
unsigned i;
unsigned long size;
unsigned prim_walk;
unsigned nverts;
 
for (i = 0; i < track->num_cb; i++) {
if (track->cb[i].robj == NULL) {
DRM_ERROR("[drm] No buffer for color buffer %d !\n", i);
return -EINVAL;
}
size = track->cb[i].pitch * track->cb[i].cpp * track->maxy;
size += track->cb[i].offset;
if (size > radeon_object_size(track->cb[i].robj)) {
DRM_ERROR("[drm] Buffer too small for color buffer %d "
"(need %lu have %lu) !\n", i, size,
radeon_object_size(track->cb[i].robj));
DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n",
i, track->cb[i].pitch, track->cb[i].cpp,
track->cb[i].offset, track->maxy);
return -EINVAL;
}
}
if (track->z_enabled) {
if (track->zb.robj == NULL) {
DRM_ERROR("[drm] No buffer for z buffer !\n");
return -EINVAL;
}
size = track->zb.pitch * track->zb.cpp * track->maxy;
size += track->zb.offset;
if (size > radeon_object_size(track->zb.robj)) {
DRM_ERROR("[drm] Buffer too small for z buffer "
"(need %lu have %lu) !\n", size,
radeon_object_size(track->zb.robj));
return -EINVAL;
}
}
prim_walk = (track->vap_vf_cntl >> 4) & 0x3;
nverts = (track->vap_vf_cntl >> 16) & 0xFFFF;
switch (prim_walk) {
case 1:
for (i = 0; i < track->num_arrays; i++) {
size = track->arrays[i].esize * track->max_indx * 4;
if (track->arrays[i].robj == NULL) {
DRM_ERROR("(PW %u) Vertex array %u no buffer "
"bound\n", prim_walk, i);
return -EINVAL;
}
if (size > radeon_object_size(track->arrays[i].robj)) {
DRM_ERROR("(PW %u) Vertex array %u need %lu dwords "
"have %lu dwords\n", prim_walk, i,
size >> 2,
radeon_object_size(track->arrays[i].robj) >> 2);
DRM_ERROR("Max indices %u\n", track->max_indx);
return -EINVAL;
}
}
break;
case 2:
for (i = 0; i < track->num_arrays; i++) {
size = track->arrays[i].esize * (nverts - 1) * 4;
if (track->arrays[i].robj == NULL) {
DRM_ERROR("(PW %u) Vertex array %u no buffer "
"bound\n", prim_walk, i);
return -EINVAL;
}
if (size > radeon_object_size(track->arrays[i].robj)) {
DRM_ERROR("(PW %u) Vertex array %u need %lu dwords "
"have %lu dwords\n", prim_walk, i, size >> 2,
radeon_object_size(track->arrays[i].robj) >> 2);
return -EINVAL;
}
}
break;
case 3:
size = track->vtx_size * nverts;
if (size != track->immd_dwords) {
DRM_ERROR("IMMD draw %u dwors but needs %lu dwords\n",
track->immd_dwords, size);
DRM_ERROR("VAP_VF_CNTL.NUM_VERTICES %u, VTX_SIZE %u\n",
nverts, track->vtx_size);
return -EINVAL;
}
break;
default:
DRM_ERROR("[drm] Invalid primitive walk %d for VAP_VF_CNTL\n",
prim_walk);
return -EINVAL;
}
return r300_cs_track_texture_check(rdev, track);
}
 
static inline void r300_cs_track_clear(struct r300_cs_track *track)
{
unsigned i;
 
track->num_cb = 4;
track->maxy = 4096;
for (i = 0; i < track->num_cb; i++) {
track->cb[i].robj = NULL;
track->cb[i].pitch = 8192;
track->cb[i].cpp = 16;
track->cb[i].offset = 0;
}
track->z_enabled = true;
track->zb.robj = NULL;
track->zb.pitch = 8192;
track->zb.cpp = 4;
track->zb.offset = 0;
track->vtx_size = 0x7F;
track->immd_dwords = 0xFFFFFFFFUL;
track->num_arrays = 11;
track->max_indx = 0x00FFFFFFUL;
for (i = 0; i < track->num_arrays; i++) {
track->arrays[i].robj = NULL;
track->arrays[i].esize = 0x7F;
}
for (i = 0; i < 16; i++) {
track->textures[i].pitch = 16536;
track->textures[i].width = 16536;
track->textures[i].height = 16536;
track->textures[i].width_11 = 1 << 11;
track->textures[i].height_11 = 1 << 11;
track->textures[i].num_levels = 12;
track->textures[i].txdepth = 16;
track->textures[i].cpp = 64;
track->textures[i].tex_coord_type = 1;
track->textures[i].robj = NULL;
/* CS IB emission code makes sure texture unit are disabled */
track->textures[i].enabled = false;
track->textures[i].roundup_w = true;
track->textures[i].roundup_h = true;
}
}
 
#endif
 
static const unsigned r300_reg_safe_bm[159] = {
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFBF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF,
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000,
0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFC78, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE009FF,
0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
0x00000000, 0x0000C100, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x0003FC01, 0xFFFFFFF8, 0xFE800B19,
};
 
#if 0
 
static int r300_packet0_check(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt,
unsigned idx, unsigned reg)
1026,19 → 694,19
{
struct radeon_cs_chunk *ib_chunk;
struct radeon_cs_reloc *reloc;
struct r300_cs_track *track;
struct r100_cs_track *track;
volatile uint32_t *ib;
uint32_t tmp;
uint32_t tmp, tile_flags = 0;
unsigned i;
int r;
 
ib = p->ib->ptr;
ib_chunk = &p->chunks[p->chunk_ib_idx];
track = (struct r300_cs_track*)p->track;
track = (struct r100_cs_track *)p->track;
switch(reg) {
case RADEON_DST_PITCH_OFFSET:
case RADEON_SRC_PITCH_OFFSET:
r = r100_cs_packet_next_reloc(p, &reloc);
case AVIVO_D1MODE_VLINE_START_END:
case RADEON_CRTC_GUI_TRIG_VLINE:
r = r100_cs_packet_parse_vline(p);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
1045,10 → 713,13
r100_cs_dump_packet(p, pkt);
return r;
}
tmp = ib_chunk->kdata[idx] & 0x003fffff;
tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp;
break;
case RADEON_DST_PITCH_OFFSET:
case RADEON_SRC_PITCH_OFFSET:
r = r100_reloc_pitch_offset(p, pkt, idx, reg);
if (r)
return r;
break;
case R300_RB3D_COLOROFFSET0:
case R300_RB3D_COLOROFFSET1:
case R300_RB3D_COLOROFFSET2:
1136,6 → 807,23
/* RB3D_COLORPITCH1 */
/* RB3D_COLORPITCH2 */
/* RB3D_COLORPITCH3 */
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
 
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
tile_flags |= R300_COLOR_TILE_ENABLE;
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
tile_flags |= R300_COLOR_MICROTILE_ENABLE;
 
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
tmp |= tile_flags;
ib[idx] = tmp;
 
i = (reg - 0x4E38) >> 2;
track->cb[i].pitch = ib_chunk->kdata[idx] & 0x3FFE;
switch (((ib_chunk->kdata[idx] >> 21) & 0xF)) {
1191,6 → 879,23
break;
case 0x4F24:
/* ZB_DEPTHPITCH */
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
 
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
tile_flags |= R300_DEPTHMACROTILE_ENABLE;
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
tile_flags |= R300_DEPTHMICROTILE_TILED;;
 
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
tmp |= tile_flags;
ib[idx] = tmp;
 
track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC;
break;
case 0x4104:
1222,42 → 927,41
tmp = (ib_chunk->kdata[idx] >> 25) & 0x3;
track->textures[i].tex_coord_type = tmp;
switch ((ib_chunk->kdata[idx] & 0x1F)) {
case 0:
case 2:
case 5:
case 18:
case 20:
case 21:
case R300_TX_FORMAT_X8:
case R300_TX_FORMAT_Y4X4:
case R300_TX_FORMAT_Z3Y3X2:
track->textures[i].cpp = 1;
break;
case 1:
case 3:
case 6:
case 7:
case 10:
case 11:
case 19:
case 22:
case 24:
case R300_TX_FORMAT_X16:
case R300_TX_FORMAT_Y8X8:
case R300_TX_FORMAT_Z5Y6X5:
case R300_TX_FORMAT_Z6Y5X5:
case R300_TX_FORMAT_W4Z4Y4X4:
case R300_TX_FORMAT_W1Z5Y5X5:
case R300_TX_FORMAT_DXT1:
case R300_TX_FORMAT_D3DMFT_CxV8U8:
case R300_TX_FORMAT_B8G8_B8G8:
case R300_TX_FORMAT_G8R8_G8B8:
track->textures[i].cpp = 2;
break;
case 4:
case 8:
case 9:
case 12:
case 13:
case 23:
case 25:
case 27:
case 30:
case R300_TX_FORMAT_Y16X16:
case R300_TX_FORMAT_Z11Y11X10:
case R300_TX_FORMAT_Z10Y11X11:
case R300_TX_FORMAT_W8Z8Y8X8:
case R300_TX_FORMAT_W2Z10Y10X10:
case 0x17:
case R300_TX_FORMAT_FL_I32:
case 0x1e:
case R300_TX_FORMAT_DXT3:
case R300_TX_FORMAT_DXT5:
track->textures[i].cpp = 4;
break;
case 14:
case 26:
case 28:
case R300_TX_FORMAT_W16Z16Y16X16:
case R300_TX_FORMAT_FL_R16G16B16A16:
case R300_TX_FORMAT_FL_I32A32:
track->textures[i].cpp = 8;
break;
case 29:
case R300_TX_FORMAT_FL_R32G32B32A32:
track->textures[i].cpp = 16;
break;
default:
1285,11 → 989,11
case 0x443C:
/* TX_FILTER0_[0-15] */
i = (reg - 0x4400) >> 2;
tmp = ib_chunk->kdata[idx] & 0x7;;
tmp = ib_chunk->kdata[idx] & 0x7;
if (tmp == 2 || tmp == 4 || tmp == 6) {
track->textures[i].roundup_w = false;
}
tmp = (ib_chunk->kdata[idx] >> 3) & 0x7;;
tmp = (ib_chunk->kdata[idx] >> 3) & 0x7;
if (tmp == 2 || tmp == 4 || tmp == 6) {
track->textures[i].roundup_h = false;
}
1350,6 → 1054,21
tmp = (ib_chunk->kdata[idx] >> 22) & 0xF;
track->textures[i].txdepth = tmp;
break;
case R300_ZB_ZPASS_ADDR:
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
ib[idx] = ib_chunk->kdata[idx] + ((u32)reloc->lobj.gpu_offset);
break;
case 0x4be8:
/* valid register only on RV530 */
if (p->rdev->family == CHIP_RV530)
break;
/* fallthrough do not move */
default:
printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
reg, idx);
1362,8 → 1081,9
struct radeon_cs_packet *pkt)
{
struct radeon_cs_chunk *ib_chunk;
 
struct radeon_cs_reloc *reloc;
struct r300_cs_track *track;
struct r100_cs_track *track;
volatile uint32_t *ib;
unsigned idx;
unsigned i, c;
1372,7 → 1092,7
ib = p->ib->ptr;
ib_chunk = &p->chunks[p->chunk_ib_idx];
idx = pkt->idx + 1;
track = (struct r300_cs_track*)p->track;
track = (struct r100_cs_track *)p->track;
switch(pkt->opcode) {
case PACKET3_3D_LOAD_VBPNTR:
c = ib_chunk->kdata[idx++] & 0x1F;
1439,7 → 1159,7
}
track->vap_vf_cntl = ib_chunk->kdata[idx+1];
track->immd_dwords = pkt->count - 1;
r = r300_cs_track_check(p->rdev, track);
r = r100_cs_track_check(p->rdev, track);
if (r) {
return r;
}
1454,7 → 1174,7
}
track->vap_vf_cntl = ib_chunk->kdata[idx];
track->immd_dwords = pkt->count;
r = r300_cs_track_check(p->rdev, track);
r = r100_cs_track_check(p->rdev, track);
if (r) {
return r;
}
1461,7 → 1181,7
break;
case PACKET3_3D_DRAW_VBUF:
track->vap_vf_cntl = ib_chunk->kdata[idx + 1];
r = r300_cs_track_check(p->rdev, track);
r = r100_cs_track_check(p->rdev, track);
if (r) {
return r;
}
1468,7 → 1188,7
break;
case PACKET3_3D_DRAW_VBUF_2:
track->vap_vf_cntl = ib_chunk->kdata[idx];
r = r300_cs_track_check(p->rdev, track);
r = r100_cs_track_check(p->rdev, track);
if (r) {
return r;
}
1475,7 → 1195,7
break;
case PACKET3_3D_DRAW_INDX:
track->vap_vf_cntl = ib_chunk->kdata[idx + 1];
r = r300_cs_track_check(p->rdev, track);
r = r100_cs_track_check(p->rdev, track);
if (r) {
return r;
}
1482,7 → 1202,7
break;
case PACKET3_3D_DRAW_INDX_2:
track->vap_vf_cntl = ib_chunk->kdata[idx];
r = r300_cs_track_check(p->rdev, track);
r = r100_cs_track_check(p->rdev, track);
if (r) {
return r;
}
1499,11 → 1219,12
int r300_cs_parse(struct radeon_cs_parser *p)
{
struct radeon_cs_packet pkt;
struct r300_cs_track track;
struct r100_cs_track *track;
int r;
 
r300_cs_track_clear(&track);
p->track = &track;
track = kzalloc(sizeof(*track), GFP_KERNEL);
r100_cs_track_clear(p->rdev, track);
p->track = track;
do {
r = r100_cs_packet_parse(p, &pkt, p->idx);
if (r) {
1532,14 → 1253,51
} while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
return 0;
}
 
#endif
 
int r300_init(struct radeon_device *rdev)
 
void r300_set_reg_safe(struct radeon_device *rdev)
{
rdev->config.r300.reg_safe_bm = r300_reg_safe_bm;
rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r300_reg_safe_bm);
}
 
int r300_init(struct radeon_device *rdev)
{
r300_set_reg_safe(rdev);
return 0;
}
 
void r300_mc_program(struct radeon_device *rdev)
{
struct r100_mc_save save;
int r;
 
r = r100_debugfs_mc_info_init(rdev);
if (r) {
dev_err(rdev->dev, "Failed to create r100_mc debugfs file.\n");
}
 
/* Stops all mc clients */
r100_mc_stop(rdev, &save);
if (rdev->flags & RADEON_IS_AGP) {
WREG32(R_00014C_MC_AGP_LOCATION,
S_00014C_MC_AGP_START(rdev->mc.gtt_start >> 16) |
S_00014C_MC_AGP_TOP(rdev->mc.gtt_end >> 16));
WREG32(R_000170_AGP_BASE, lower_32_bits(rdev->mc.agp_base));
WREG32(R_00015C_AGP_BASE_2,
upper_32_bits(rdev->mc.agp_base) & 0xff);
} else {
WREG32(R_00014C_MC_AGP_LOCATION, 0x0FFFFFFF);
WREG32(R_000170_AGP_BASE, 0);
WREG32(R_00015C_AGP_BASE_2, 0);
}
/* Wait for mc idle */
if (r300_mc_wait_for_idle(rdev))
DRM_INFO("Failed to wait MC idle before programming MC.\n");
/* Program MC, should be a 32bits limited address space */
WREG32(R_000148_MC_FB_LOCATION,
S_000148_MC_FB_START(rdev->mc.vram_start >> 16) |
S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16));
r100_mc_resume(rdev, &save);
}
/drivers/video/drm/radeon/r300_reg.h
27,9 → 27,11
#ifndef _R300_REG_H_
#define _R300_REG_H_
 
#define R300_SURF_TILE_MACRO (1<<16)
#define R300_SURF_TILE_MICRO (2<<16)
#define R300_SURF_TILE_BOTH (3<<16)
 
 
 
#define R300_MC_INIT_MISC_LAT_TIMER 0x180
# define R300_MC_MISC__MC_CPR_INIT_LAT_SHIFT 0
# define R300_MC_MISC__MC_VF_INIT_LAT_SHIFT 4
/drivers/video/drm/radeon/r300_reg_safe.h
0,0 → 1,42
static const unsigned r300_reg_safe_bm[159] = {
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF,
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000,
0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFC78, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE009FF,
0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
0x00000000, 0x0000C100, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x0003FC01, 0xFFFFFCF8, 0xFF800B19,
};
/drivers/video/drm/radeon/r300d.h
0,0 → 1,101
/*
* Copyright 2008 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
* Copyright 2009 Jerome Glisse.
*
* 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
* Jerome Glisse
*/
#ifndef __R300D_H__
#define __R300D_H__
 
#define CP_PACKET0 0x00000000
#define PACKET0_BASE_INDEX_SHIFT 0
#define PACKET0_BASE_INDEX_MASK (0x1ffff << 0)
#define PACKET0_COUNT_SHIFT 16
#define PACKET0_COUNT_MASK (0x3fff << 16)
#define CP_PACKET1 0x40000000
#define CP_PACKET2 0x80000000
#define PACKET2_PAD_SHIFT 0
#define PACKET2_PAD_MASK (0x3fffffff << 0)
#define CP_PACKET3 0xC0000000
#define PACKET3_IT_OPCODE_SHIFT 8
#define PACKET3_IT_OPCODE_MASK (0xff << 8)
#define PACKET3_COUNT_SHIFT 16
#define PACKET3_COUNT_MASK (0x3fff << 16)
/* PACKET3 op code */
#define PACKET3_NOP 0x10
#define PACKET3_3D_DRAW_VBUF 0x28
#define PACKET3_3D_DRAW_IMMD 0x29
#define PACKET3_3D_DRAW_INDX 0x2A
#define PACKET3_3D_LOAD_VBPNTR 0x2F
#define PACKET3_INDX_BUFFER 0x33
#define PACKET3_3D_DRAW_VBUF_2 0x34
#define PACKET3_3D_DRAW_IMMD_2 0x35
#define PACKET3_3D_DRAW_INDX_2 0x36
#define PACKET3_BITBLT_MULTI 0x9B
 
#define PACKET0(reg, n) (CP_PACKET0 | \
REG_SET(PACKET0_BASE_INDEX, (reg) >> 2) | \
REG_SET(PACKET0_COUNT, (n)))
#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
#define PACKET3(op, n) (CP_PACKET3 | \
REG_SET(PACKET3_IT_OPCODE, (op)) | \
REG_SET(PACKET3_COUNT, (n)))
 
#define PACKET_TYPE0 0
#define PACKET_TYPE1 1
#define PACKET_TYPE2 2
#define PACKET_TYPE3 3
 
#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2)
#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1)
#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
 
/* Registers */
#define R_000148_MC_FB_LOCATION 0x000148
#define S_000148_MC_FB_START(x) (((x) & 0xFFFF) << 0)
#define G_000148_MC_FB_START(x) (((x) >> 0) & 0xFFFF)
#define C_000148_MC_FB_START 0xFFFF0000
#define S_000148_MC_FB_TOP(x) (((x) & 0xFFFF) << 16)
#define G_000148_MC_FB_TOP(x) (((x) >> 16) & 0xFFFF)
#define C_000148_MC_FB_TOP 0x0000FFFF
#define R_00014C_MC_AGP_LOCATION 0x00014C
#define S_00014C_MC_AGP_START(x) (((x) & 0xFFFF) << 0)
#define G_00014C_MC_AGP_START(x) (((x) >> 0) & 0xFFFF)
#define C_00014C_MC_AGP_START 0xFFFF0000
#define S_00014C_MC_AGP_TOP(x) (((x) & 0xFFFF) << 16)
#define G_00014C_MC_AGP_TOP(x) (((x) >> 16) & 0xFFFF)
#define C_00014C_MC_AGP_TOP 0x0000FFFF
#define R_00015C_AGP_BASE_2 0x00015C
#define S_00015C_AGP_BASE_ADDR_2(x) (((x) & 0xF) << 0)
#define G_00015C_AGP_BASE_ADDR_2(x) (((x) >> 0) & 0xF)
#define C_00015C_AGP_BASE_ADDR_2 0xFFFFFFF0
#define R_000170_AGP_BASE 0x000170
#define S_000170_AGP_BASE_ADDR(x) (((x) & 0xFFFFFFFF) << 0)
#define G_000170_AGP_BASE_ADDR(x) (((x) >> 0) & 0xFFFFFFFF)
#define C_000170_AGP_BASE_ADDR 0x00000000
 
 
#endif
/drivers/video/drm/radeon/r420.c
0,0 → 1,385
/*
* Copyright 2008 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
* Copyright 2009 Jerome Glisse.
*
* 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
* Jerome Glisse
*/
#include <linux/seq_file.h>
#include "drmP.h"
#include "radeon_reg.h"
#include "radeon.h"
#include "atom.h"
#include "r420d.h"
 
int r420_mc_init(struct radeon_device *rdev)
{
int r;
 
/* Setup GPU memory space */
rdev->mc.vram_location = 0xFFFFFFFFUL;
rdev->mc.gtt_location = 0xFFFFFFFFUL;
r = radeon_mc_setup(rdev);
if (r) {
return r;
}
return 0;
}
 
void r420_pipes_init(struct radeon_device *rdev)
{
unsigned tmp;
unsigned gb_pipe_select;
unsigned num_pipes;
 
/* GA_ENHANCE workaround TCL deadlock issue */
WREG32(0x4274, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3));
/* add idle wait as per freedesktop.org bug 24041 */
if (r100_gui_wait_for_idle(rdev)) {
printk(KERN_WARNING "Failed to wait GUI idle while "
"programming pipes. Bad things might happen.\n");
}
/* get max number of pipes */
gb_pipe_select = RREG32(0x402C);
num_pipes = ((gb_pipe_select >> 12) & 3) + 1;
rdev->num_gb_pipes = num_pipes;
tmp = 0;
switch (num_pipes) {
default:
/* force to 1 pipe */
num_pipes = 1;
case 1:
tmp = (0 << 1);
break;
case 2:
tmp = (3 << 1);
break;
case 3:
tmp = (6 << 1);
break;
case 4:
tmp = (7 << 1);
break;
}
WREG32(0x42C8, (1 << num_pipes) - 1);
/* Sub pixel 1/12 so we can have 4K rendering according to doc */
tmp |= (1 << 4) | (1 << 0);
WREG32(0x4018, tmp);
if (r100_gui_wait_for_idle(rdev)) {
printk(KERN_WARNING "Failed to wait GUI idle while "
"programming pipes. Bad things might happen.\n");
}
 
tmp = RREG32(0x170C);
WREG32(0x170C, tmp | (1 << 31));
 
WREG32(R300_RB2D_DSTCACHE_MODE,
RREG32(R300_RB2D_DSTCACHE_MODE) |
R300_DC_AUTOFLUSH_ENABLE |
R300_DC_DC_DISABLE_IGNORE_PE);
 
if (r100_gui_wait_for_idle(rdev)) {
printk(KERN_WARNING "Failed to wait GUI idle while "
"programming pipes. Bad things might happen.\n");
}
 
if (rdev->family == CHIP_RV530) {
tmp = RREG32(RV530_GB_PIPE_SELECT2);
if ((tmp & 3) == 3)
rdev->num_z_pipes = 2;
else
rdev->num_z_pipes = 1;
} else
rdev->num_z_pipes = 1;
 
DRM_INFO("radeon: %d quad pipes, %d z pipes initialized.\n",
rdev->num_gb_pipes, rdev->num_z_pipes);
}
 
u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg)
{
u32 r;
 
WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg));
r = RREG32(R_0001FC_MC_IND_DATA);
return r;
}
 
void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v)
{
WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg) |
S_0001F8_MC_IND_WR_EN(1));
WREG32(R_0001FC_MC_IND_DATA, v);
}
 
static void r420_debugfs(struct radeon_device *rdev)
{
if (r100_debugfs_rbbm_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for RBBM !\n");
}
if (r420_debugfs_pipes_info_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for pipes !\n");
}
}
 
static void r420_clock_resume(struct radeon_device *rdev)
{
u32 sclk_cntl;
sclk_cntl = RREG32_PLL(R_00000D_SCLK_CNTL);
sclk_cntl |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1);
if (rdev->family == CHIP_R420)
sclk_cntl |= S_00000D_FORCE_PX(1) | S_00000D_FORCE_TX(1);
WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl);
}
 
static int r420_startup(struct radeon_device *rdev)
{
int r;
 
r300_mc_program(rdev);
/* Initialize GART (initialize after TTM so we can allocate
* memory through TTM but finalize after TTM) */
if (rdev->flags & RADEON_IS_PCIE) {
r = rv370_pcie_gart_enable(rdev);
if (r)
return r;
}
if (rdev->flags & RADEON_IS_PCI) {
r = r100_pci_gart_enable(rdev);
if (r)
return r;
}
r420_pipes_init(rdev);
/* Enable IRQ */
// rdev->irq.sw_int = true;
// r100_irq_set(rdev);
/* 1M ring buffer */
r = r100_cp_init(rdev, 1024 * 1024);
if (r) {
dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
return r;
}
// r = r100_wb_init(rdev);
// if (r) {
// dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
// }
// r = r100_ib_init(rdev);
// if (r) {
// dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
// return r;
// }
return 0;
}
 
int r420_resume(struct radeon_device *rdev)
{
/* Make sur GART are not working */
if (rdev->flags & RADEON_IS_PCIE)
rv370_pcie_gart_disable(rdev);
if (rdev->flags & RADEON_IS_PCI)
r100_pci_gart_disable(rdev);
/* Resume clock before doing reset */
r420_clock_resume(rdev);
/* Reset gpu before posting otherwise ATOM will enter infinite loop */
if (radeon_gpu_reset(rdev)) {
dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
RREG32(R_000E40_RBBM_STATUS),
RREG32(R_0007C0_CP_STAT));
}
/* check if cards are posted or not */
if (rdev->is_atom_bios) {
atom_asic_init(rdev->mode_info.atom_context);
} else {
radeon_combios_asic_init(rdev->ddev);
}
/* Resume clock after posting */
r420_clock_resume(rdev);
 
return r420_startup(rdev);
}
 
int r420_suspend(struct radeon_device *rdev)
{
r100_cp_disable(rdev);
// r100_wb_disable(rdev);
// r100_irq_disable(rdev);
if (rdev->flags & RADEON_IS_PCIE)
rv370_pcie_gart_disable(rdev);
if (rdev->flags & RADEON_IS_PCI)
r100_pci_gart_disable(rdev);
return 0;
}
 
void r420_fini(struct radeon_device *rdev)
{
r100_cp_fini(rdev);
// r100_wb_fini(rdev);
// r100_ib_fini(rdev);
radeon_gem_fini(rdev);
if (rdev->flags & RADEON_IS_PCIE)
rv370_pcie_gart_fini(rdev);
if (rdev->flags & RADEON_IS_PCI)
r100_pci_gart_fini(rdev);
// radeon_agp_fini(rdev);
// radeon_irq_kms_fini(rdev);
// radeon_fence_driver_fini(rdev);
// radeon_object_fini(rdev);
if (rdev->is_atom_bios) {
radeon_atombios_fini(rdev);
} else {
radeon_combios_fini(rdev);
}
kfree(rdev->bios);
rdev->bios = NULL;
}
 
int r420_init(struct radeon_device *rdev)
{
int r;
 
rdev->new_init_path = true;
/* Initialize scratch registers */
radeon_scratch_init(rdev);
/* Initialize surface registers */
radeon_surface_init(rdev);
/* TODO: disable VGA need to use VGA request */
/* BIOS*/
if (!radeon_get_bios(rdev)) {
if (ASIC_IS_AVIVO(rdev))
return -EINVAL;
}
if (rdev->is_atom_bios) {
r = radeon_atombios_init(rdev);
if (r) {
return r;
}
} else {
r = radeon_combios_init(rdev);
if (r) {
return r;
}
}
/* Reset gpu before posting otherwise ATOM will enter infinite loop */
if (radeon_gpu_reset(rdev)) {
dev_warn(rdev->dev,
"GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
RREG32(R_000E40_RBBM_STATUS),
RREG32(R_0007C0_CP_STAT));
}
/* check if cards are posted or not */
if (!radeon_card_posted(rdev) && rdev->bios) {
DRM_INFO("GPU not posted. posting now...\n");
if (rdev->is_atom_bios) {
atom_asic_init(rdev->mode_info.atom_context);
} else {
radeon_combios_asic_init(rdev->ddev);
}
}
/* Initialize clocks */
radeon_get_clock_info(rdev->ddev);
/* Get vram informations */
r300_vram_info(rdev);
/* Initialize memory controller (also test AGP) */
r = r420_mc_init(rdev);
if (r) {
return r;
}
r420_debugfs(rdev);
/* Fence driver */
// r = radeon_fence_driver_init(rdev);
// if (r) {
// return r;
// }
// r = radeon_irq_kms_init(rdev);
// if (r) {
// return r;
// }
/* Memory manager */
r = radeon_object_init(rdev);
if (r) {
return r;
}
if (rdev->flags & RADEON_IS_PCIE) {
r = rv370_pcie_gart_init(rdev);
if (r)
return r;
}
if (rdev->flags & RADEON_IS_PCI) {
r = r100_pci_gart_init(rdev);
if (r)
return r;
}
r300_set_reg_safe(rdev);
rdev->accel_working = true;
r = r420_startup(rdev);
if (r) {
/* Somethings want wront with the accel init stop accel */
dev_err(rdev->dev, "Disabling GPU acceleration\n");
r420_suspend(rdev);
// r100_cp_fini(rdev);
// r100_wb_fini(rdev);
// r100_ib_fini(rdev);
if (rdev->flags & RADEON_IS_PCIE)
rv370_pcie_gart_fini(rdev);
if (rdev->flags & RADEON_IS_PCI)
r100_pci_gart_fini(rdev);
// radeon_agp_fini(rdev);
// radeon_irq_kms_fini(rdev);
rdev->accel_working = false;
}
return 0;
}
 
/*
* Debugfs info
*/
#if defined(CONFIG_DEBUG_FS)
static int r420_debugfs_pipes_info(struct seq_file *m, void *data)
{
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
struct radeon_device *rdev = dev->dev_private;
uint32_t tmp;
 
tmp = RREG32(R400_GB_PIPE_SELECT);
seq_printf(m, "GB_PIPE_SELECT 0x%08x\n", tmp);
tmp = RREG32(R300_GB_TILE_CONFIG);
seq_printf(m, "GB_TILE_CONFIG 0x%08x\n", tmp);
tmp = RREG32(R300_DST_PIPE_CONFIG);
seq_printf(m, "DST_PIPE_CONFIG 0x%08x\n", tmp);
return 0;
}
 
static struct drm_info_list r420_pipes_info_list[] = {
{"r420_pipes_info", r420_debugfs_pipes_info, 0, NULL},
};
#endif
 
int r420_debugfs_pipes_info_init(struct radeon_device *rdev)
{
#if defined(CONFIG_DEBUG_FS)
return radeon_debugfs_add_files(rdev, r420_pipes_info_list, 1);
#else
return 0;
#endif
}
/drivers/video/drm/radeon/r420d.h
0,0 → 1,249
/*
* Copyright 2008 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
* Copyright 2009 Jerome Glisse.
*
* 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
* Jerome Glisse
*/
#ifndef R420D_H
#define R420D_H
 
#define R_0001F8_MC_IND_INDEX 0x0001F8
#define S_0001F8_MC_IND_ADDR(x) (((x) & 0x7F) << 0)
#define G_0001F8_MC_IND_ADDR(x) (((x) >> 0) & 0x7F)
#define C_0001F8_MC_IND_ADDR 0xFFFFFF80
#define S_0001F8_MC_IND_WR_EN(x) (((x) & 0x1) << 8)
#define G_0001F8_MC_IND_WR_EN(x) (((x) >> 8) & 0x1)
#define C_0001F8_MC_IND_WR_EN 0xFFFFFEFF
#define R_0001FC_MC_IND_DATA 0x0001FC
#define S_0001FC_MC_IND_DATA(x) (((x) & 0xFFFFFFFF) << 0)
#define G_0001FC_MC_IND_DATA(x) (((x) >> 0) & 0xFFFFFFFF)
#define C_0001FC_MC_IND_DATA 0x00000000
#define R_0007C0_CP_STAT 0x0007C0
#define S_0007C0_MRU_BUSY(x) (((x) & 0x1) << 0)
#define G_0007C0_MRU_BUSY(x) (((x) >> 0) & 0x1)
#define C_0007C0_MRU_BUSY 0xFFFFFFFE
#define S_0007C0_MWU_BUSY(x) (((x) & 0x1) << 1)
#define G_0007C0_MWU_BUSY(x) (((x) >> 1) & 0x1)
#define C_0007C0_MWU_BUSY 0xFFFFFFFD
#define S_0007C0_RSIU_BUSY(x) (((x) & 0x1) << 2)
#define G_0007C0_RSIU_BUSY(x) (((x) >> 2) & 0x1)
#define C_0007C0_RSIU_BUSY 0xFFFFFFFB
#define S_0007C0_RCIU_BUSY(x) (((x) & 0x1) << 3)
#define G_0007C0_RCIU_BUSY(x) (((x) >> 3) & 0x1)
#define C_0007C0_RCIU_BUSY 0xFFFFFFF7
#define S_0007C0_CSF_PRIMARY_BUSY(x) (((x) & 0x1) << 9)
#define G_0007C0_CSF_PRIMARY_BUSY(x) (((x) >> 9) & 0x1)
#define C_0007C0_CSF_PRIMARY_BUSY 0xFFFFFDFF
#define S_0007C0_CSF_INDIRECT_BUSY(x) (((x) & 0x1) << 10)
#define G_0007C0_CSF_INDIRECT_BUSY(x) (((x) >> 10) & 0x1)
#define C_0007C0_CSF_INDIRECT_BUSY 0xFFFFFBFF
#define S_0007C0_CSQ_PRIMARY_BUSY(x) (((x) & 0x1) << 11)
#define G_0007C0_CSQ_PRIMARY_BUSY(x) (((x) >> 11) & 0x1)
#define C_0007C0_CSQ_PRIMARY_BUSY 0xFFFFF7FF
#define S_0007C0_CSQ_INDIRECT_BUSY(x) (((x) & 0x1) << 12)
#define G_0007C0_CSQ_INDIRECT_BUSY(x) (((x) >> 12) & 0x1)
#define C_0007C0_CSQ_INDIRECT_BUSY 0xFFFFEFFF
#define S_0007C0_CSI_BUSY(x) (((x) & 0x1) << 13)
#define G_0007C0_CSI_BUSY(x) (((x) >> 13) & 0x1)
#define C_0007C0_CSI_BUSY 0xFFFFDFFF
#define S_0007C0_CSF_INDIRECT2_BUSY(x) (((x) & 0x1) << 14)
#define G_0007C0_CSF_INDIRECT2_BUSY(x) (((x) >> 14) & 0x1)
#define C_0007C0_CSF_INDIRECT2_BUSY 0xFFFFBFFF
#define S_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) & 0x1) << 15)
#define G_0007C0_CSQ_INDIRECT2_BUSY(x) (((x) >> 15) & 0x1)
#define C_0007C0_CSQ_INDIRECT2_BUSY 0xFFFF7FFF
#define S_0007C0_GUIDMA_BUSY(x) (((x) & 0x1) << 28)
#define G_0007C0_GUIDMA_BUSY(x) (((x) >> 28) & 0x1)
#define C_0007C0_GUIDMA_BUSY 0xEFFFFFFF
#define S_0007C0_VIDDMA_BUSY(x) (((x) & 0x1) << 29)
#define G_0007C0_VIDDMA_BUSY(x) (((x) >> 29) & 0x1)
#define C_0007C0_VIDDMA_BUSY 0xDFFFFFFF
#define S_0007C0_CMDSTRM_BUSY(x) (((x) & 0x1) << 30)
#define G_0007C0_CMDSTRM_BUSY(x) (((x) >> 30) & 0x1)
#define C_0007C0_CMDSTRM_BUSY 0xBFFFFFFF
#define S_0007C0_CP_BUSY(x) (((x) & 0x1) << 31)
#define G_0007C0_CP_BUSY(x) (((x) >> 31) & 0x1)
#define C_0007C0_CP_BUSY 0x7FFFFFFF
#define R_000E40_RBBM_STATUS 0x000E40
#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0)
#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F)
#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80
#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8)
#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1)
#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF
#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9)
#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1)
#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF
#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10)
#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1)
#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF
#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11)
#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1)
#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF
#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12)
#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1)
#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF
#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13)
#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1)
#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF
#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14)
#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1)
#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF
#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15)
#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1)
#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF
#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16)
#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1)
#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF
#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17)
#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1)
#define C_000E40_E2_BUSY 0xFFFDFFFF
#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18)
#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1)
#define C_000E40_RB2D_BUSY 0xFFFBFFFF
#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19)
#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1)
#define C_000E40_RB3D_BUSY 0xFFF7FFFF
#define S_000E40_VAP_BUSY(x) (((x) & 0x1) << 20)
#define G_000E40_VAP_BUSY(x) (((x) >> 20) & 0x1)
#define C_000E40_VAP_BUSY 0xFFEFFFFF
#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21)
#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1)
#define C_000E40_RE_BUSY 0xFFDFFFFF
#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22)
#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1)
#define C_000E40_TAM_BUSY 0xFFBFFFFF
#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23)
#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1)
#define C_000E40_TDM_BUSY 0xFF7FFFFF
#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24)
#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1)
#define C_000E40_PB_BUSY 0xFEFFFFFF
#define S_000E40_TIM_BUSY(x) (((x) & 0x1) << 25)
#define G_000E40_TIM_BUSY(x) (((x) >> 25) & 0x1)
#define C_000E40_TIM_BUSY 0xFDFFFFFF
#define S_000E40_GA_BUSY(x) (((x) & 0x1) << 26)
#define G_000E40_GA_BUSY(x) (((x) >> 26) & 0x1)
#define C_000E40_GA_BUSY 0xFBFFFFFF
#define S_000E40_CBA2D_BUSY(x) (((x) & 0x1) << 27)
#define G_000E40_CBA2D_BUSY(x) (((x) >> 27) & 0x1)
#define C_000E40_CBA2D_BUSY 0xF7FFFFFF
#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31)
#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1)
#define C_000E40_GUI_ACTIVE 0x7FFFFFFF
 
/* CLK registers */
#define R_00000D_SCLK_CNTL 0x00000D
#define S_00000D_SCLK_SRC_SEL(x) (((x) & 0x7) << 0)
#define G_00000D_SCLK_SRC_SEL(x) (((x) >> 0) & 0x7)
#define C_00000D_SCLK_SRC_SEL 0xFFFFFFF8
#define S_00000D_CP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 3)
#define G_00000D_CP_MAX_DYN_STOP_LAT(x) (((x) >> 3) & 0x1)
#define C_00000D_CP_MAX_DYN_STOP_LAT 0xFFFFFFF7
#define S_00000D_HDP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 4)
#define G_00000D_HDP_MAX_DYN_STOP_LAT(x) (((x) >> 4) & 0x1)
#define C_00000D_HDP_MAX_DYN_STOP_LAT 0xFFFFFFEF
#define S_00000D_TV_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 5)
#define G_00000D_TV_MAX_DYN_STOP_LAT(x) (((x) >> 5) & 0x1)
#define C_00000D_TV_MAX_DYN_STOP_LAT 0xFFFFFFDF
#define S_00000D_E2_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 6)
#define G_00000D_E2_MAX_DYN_STOP_LAT(x) (((x) >> 6) & 0x1)
#define C_00000D_E2_MAX_DYN_STOP_LAT 0xFFFFFFBF
#define S_00000D_SE_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 7)
#define G_00000D_SE_MAX_DYN_STOP_LAT(x) (((x) >> 7) & 0x1)
#define C_00000D_SE_MAX_DYN_STOP_LAT 0xFFFFFF7F
#define S_00000D_IDCT_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 8)
#define G_00000D_IDCT_MAX_DYN_STOP_LAT(x) (((x) >> 8) & 0x1)
#define C_00000D_IDCT_MAX_DYN_STOP_LAT 0xFFFFFEFF
#define S_00000D_VIP_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 9)
#define G_00000D_VIP_MAX_DYN_STOP_LAT(x) (((x) >> 9) & 0x1)
#define C_00000D_VIP_MAX_DYN_STOP_LAT 0xFFFFFDFF
#define S_00000D_RE_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 10)
#define G_00000D_RE_MAX_DYN_STOP_LAT(x) (((x) >> 10) & 0x1)
#define C_00000D_RE_MAX_DYN_STOP_LAT 0xFFFFFBFF
#define S_00000D_PB_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 11)
#define G_00000D_PB_MAX_DYN_STOP_LAT(x) (((x) >> 11) & 0x1)
#define C_00000D_PB_MAX_DYN_STOP_LAT 0xFFFFF7FF
#define S_00000D_TAM_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 12)
#define G_00000D_TAM_MAX_DYN_STOP_LAT(x) (((x) >> 12) & 0x1)
#define C_00000D_TAM_MAX_DYN_STOP_LAT 0xFFFFEFFF
#define S_00000D_TDM_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 13)
#define G_00000D_TDM_MAX_DYN_STOP_LAT(x) (((x) >> 13) & 0x1)
#define C_00000D_TDM_MAX_DYN_STOP_LAT 0xFFFFDFFF
#define S_00000D_RB_MAX_DYN_STOP_LAT(x) (((x) & 0x1) << 14)
#define G_00000D_RB_MAX_DYN_STOP_LAT(x) (((x) >> 14) & 0x1)
#define C_00000D_RB_MAX_DYN_STOP_LAT 0xFFFFBFFF
#define S_00000D_FORCE_DISP2(x) (((x) & 0x1) << 15)
#define G_00000D_FORCE_DISP2(x) (((x) >> 15) & 0x1)
#define C_00000D_FORCE_DISP2 0xFFFF7FFF
#define S_00000D_FORCE_CP(x) (((x) & 0x1) << 16)
#define G_00000D_FORCE_CP(x) (((x) >> 16) & 0x1)
#define C_00000D_FORCE_CP 0xFFFEFFFF
#define S_00000D_FORCE_HDP(x) (((x) & 0x1) << 17)
#define G_00000D_FORCE_HDP(x) (((x) >> 17) & 0x1)
#define C_00000D_FORCE_HDP 0xFFFDFFFF
#define S_00000D_FORCE_DISP1(x) (((x) & 0x1) << 18)
#define G_00000D_FORCE_DISP1(x) (((x) >> 18) & 0x1)
#define C_00000D_FORCE_DISP1 0xFFFBFFFF
#define S_00000D_FORCE_TOP(x) (((x) & 0x1) << 19)
#define G_00000D_FORCE_TOP(x) (((x) >> 19) & 0x1)
#define C_00000D_FORCE_TOP 0xFFF7FFFF
#define S_00000D_FORCE_E2(x) (((x) & 0x1) << 20)
#define G_00000D_FORCE_E2(x) (((x) >> 20) & 0x1)
#define C_00000D_FORCE_E2 0xFFEFFFFF
#define S_00000D_FORCE_SE(x) (((x) & 0x1) << 21)
#define G_00000D_FORCE_SE(x) (((x) >> 21) & 0x1)
#define C_00000D_FORCE_SE 0xFFDFFFFF
#define S_00000D_FORCE_IDCT(x) (((x) & 0x1) << 22)
#define G_00000D_FORCE_IDCT(x) (((x) >> 22) & 0x1)
#define C_00000D_FORCE_IDCT 0xFFBFFFFF
#define S_00000D_FORCE_VIP(x) (((x) & 0x1) << 23)
#define G_00000D_FORCE_VIP(x) (((x) >> 23) & 0x1)
#define C_00000D_FORCE_VIP 0xFF7FFFFF
#define S_00000D_FORCE_RE(x) (((x) & 0x1) << 24)
#define G_00000D_FORCE_RE(x) (((x) >> 24) & 0x1)
#define C_00000D_FORCE_RE 0xFEFFFFFF
#define S_00000D_FORCE_PB(x) (((x) & 0x1) << 25)
#define G_00000D_FORCE_PB(x) (((x) >> 25) & 0x1)
#define C_00000D_FORCE_PB 0xFDFFFFFF
#define S_00000D_FORCE_PX(x) (((x) & 0x1) << 26)
#define G_00000D_FORCE_PX(x) (((x) >> 26) & 0x1)
#define C_00000D_FORCE_PX 0xFBFFFFFF
#define S_00000D_FORCE_TX(x) (((x) & 0x1) << 27)
#define G_00000D_FORCE_TX(x) (((x) >> 27) & 0x1)
#define C_00000D_FORCE_TX 0xF7FFFFFF
#define S_00000D_FORCE_RB(x) (((x) & 0x1) << 28)
#define G_00000D_FORCE_RB(x) (((x) >> 28) & 0x1)
#define C_00000D_FORCE_RB 0xEFFFFFFF
#define S_00000D_FORCE_TV_SCLK(x) (((x) & 0x1) << 29)
#define G_00000D_FORCE_TV_SCLK(x) (((x) >> 29) & 0x1)
#define C_00000D_FORCE_TV_SCLK 0xDFFFFFFF
#define S_00000D_FORCE_SUBPIC(x) (((x) & 0x1) << 30)
#define G_00000D_FORCE_SUBPIC(x) (((x) >> 30) & 0x1)
#define C_00000D_FORCE_SUBPIC 0xBFFFFFFF
#define S_00000D_FORCE_OV0(x) (((x) & 0x1) << 31)
#define G_00000D_FORCE_OV0(x) (((x) >> 31) & 0x1)
#define C_00000D_FORCE_OV0 0x7FFFFFFF
 
#endif
/drivers/video/drm/radeon/r500_reg.h
350,6 → 350,7
#define AVIVO_D1CRTC_BLANK_CONTROL 0x6084
#define AVIVO_D1CRTC_INTERLACE_CONTROL 0x6088
#define AVIVO_D1CRTC_INTERLACE_STATUS 0x608c
#define AVIVO_D1CRTC_FRAME_COUNT 0x60a4
#define AVIVO_D1CRTC_STEREO_CONTROL 0x60c4
 
/* master controls */
438,13 → 439,15
# define AVIVO_DC_LB_DISP1_END_ADR_SHIFT 4
# define AVIVO_DC_LB_DISP1_END_ADR_MASK 0x7ff
 
#define R500_DxMODE_INT_MASK 0x6540
#define R500_D1MODE_INT_MASK (1<<0)
#define R500_D2MODE_INT_MASK (1<<8)
 
#define AVIVO_D1MODE_DATA_FORMAT 0x6528
# define AVIVO_D1MODE_INTERLEAVE_EN (1 << 0)
#define AVIVO_D1MODE_DESKTOP_HEIGHT 0x652C
#define AVIVO_D1MODE_VBLANK_STATUS 0x6534
# define AVIVO_VBLANK_ACK (1 << 4)
#define AVIVO_D1MODE_VLINE_START_END 0x6538
#define AVIVO_DxMODE_INT_MASK 0x6540
# define AVIVO_D1MODE_INT_MASK (1 << 0)
# define AVIVO_D2MODE_INT_MASK (1 << 8)
#define AVIVO_D1MODE_VIEWPORT_START 0x6580
#define AVIVO_D1MODE_VIEWPORT_SIZE 0x6584
#define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6588
474,6 → 477,7
#define AVIVO_D2CRTC_BLANK_CONTROL 0x6884
#define AVIVO_D2CRTC_INTERLACE_CONTROL 0x6888
#define AVIVO_D2CRTC_INTERLACE_STATUS 0x688c
#define AVIVO_D2CRTC_FRAME_COUNT 0x68a4
#define AVIVO_D2CRTC_STEREO_CONTROL 0x68c4
 
#define AVIVO_D2GRPH_ENABLE 0x6900
496,6 → 500,8
#define AVIVO_D2CUR_SIZE 0x6c10
#define AVIVO_D2CUR_POSITION 0x6c14
 
#define AVIVO_D2MODE_VBLANK_STATUS 0x6d34
#define AVIVO_D2MODE_VLINE_START_END 0x6d38
#define AVIVO_D2MODE_VIEWPORT_START 0x6d80
#define AVIVO_D2MODE_VIEWPORT_SIZE 0x6d84
#define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6d88
746,4 → 752,8
# define AVIVO_I2C_EN (1 << 0)
# define AVIVO_I2C_RESET (1 << 8)
 
#define AVIVO_DISP_INTERRUPT_STATUS 0x7edc
# define AVIVO_D1_VBLANK_INTERRUPT (1 << 4)
# define AVIVO_D2_VBLANK_INTERRUPT (1 << 5)
 
#endif
/drivers/video/drm/radeon/r520.c
31,8 → 31,6
 
/* r520,rv530,rv560,rv570,r580 depends on : */
void r100_hdp_reset(struct radeon_device *rdev);
int rv370_pcie_gart_enable(struct radeon_device *rdev);
void rv370_pcie_gart_disable(struct radeon_device *rdev);
void r420_pipes_init(struct radeon_device *rdev);
void rs600_mc_disable_clients(struct radeon_device *rdev);
void rs600_disable_vga(struct radeon_device *rdev);
47,6 → 45,7
void r520_gpu_init(struct radeon_device *rdev);
int r520_mc_wait_for_idle(struct radeon_device *rdev);
 
 
/*
* MC
*/
55,7 → 54,7
uint32_t tmp;
int r;
 
dbgprintf("%s\n",__FUNCTION__);
ENTER();
 
if (r100_debugfs_rbbm_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for RBBM !\n");
73,16 → 72,6
/* Setup GPU memory space */
rdev->mc.vram_location = 0xFFFFFFFFUL;
rdev->mc.gtt_location = 0xFFFFFFFFUL;
if (rdev->flags & RADEON_IS_AGP) {
r = radeon_agp_init(rdev);
if (r) {
printk(KERN_WARNING "[drm] Disabling AGP\n");
rdev->flags &= ~RADEON_IS_AGP;
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
} else {
rdev->mc.gtt_location = rdev->mc.agp_base;
}
}
r = radeon_mc_setup(rdev);
if (r) {
return r;
95,8 → 84,8
"programming pipes. Bad things might happen.\n");
}
/* Write VRAM size in case we are limiting it */
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size);
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1;
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(R520_MC_FB_TOP, tmp >> 16);
tmp |= REG_SET(R520_MC_FB_START, rdev->mc.vram_location >> 16);
WREG32_MC(R520_MC_FB_LOCATION, tmp);
115,7 → 104,7
WREG32_MC(R520_MC_AGP_BASE_2, 0);
}
 
dbgprintf("done: %s\n",__FUNCTION__);
LEAVE();
 
return 0;
}
122,9 → 111,6
 
void r520_mc_fini(struct radeon_device *rdev)
{
rv370_pcie_gart_disable(rdev);
radeon_gart_table_vram_free(rdev);
radeon_gart_fini(rdev);
}
 
 
155,7 → 141,7
void r520_gpu_init(struct radeon_device *rdev)
{
unsigned pipe_select_current, gb_pipe_select, tmp;
dbgprintf("%s\n",__FUNCTION__);
ENTER();
 
r100_hdp_reset(rdev);
rs600_disable_vga(rdev);
181,7 → 167,6
*/
/* workaround for RV530 */
if (rdev->family == CHIP_RV530) {
WREG32(0x4124, 1);
WREG32(0x4128, 0xFF);
}
r420_pipes_init(rdev);
204,7 → 189,7
static void r520_vram_get_type(struct radeon_device *rdev)
{
uint32_t tmp;
dbgprintf("%s\n",__FUNCTION__);
ENTER();
 
rdev->mc.vram_width = 128;
rdev->mc.vram_is_ddr = true;
232,164 → 217,20
 
void r520_vram_info(struct radeon_device *rdev)
{
fixed20_12 a;
 
r520_vram_get_type(rdev);
rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
 
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
r100_vram_init_sizes(rdev);
/* FIXME: we should enforce default clock in case GPU is not in
* default setup
*/
a.full = rfixed_const(100);
rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
}
 
 
int radeon_agp_init(struct radeon_device *rdev)
void r520_bandwidth_update(struct radeon_device *rdev)
{
 
dbgprintf("%s\n",__FUNCTION__);
 
#if __OS_HAS_AGP
struct radeon_agpmode_quirk *p = radeon_agpmode_quirk_list;
struct drm_agp_mode mode;
struct drm_agp_info info;
uint32_t agp_status;
int default_mode;
bool is_v3;
int ret;
 
/* Acquire AGP. */
if (!rdev->ddev->agp->acquired) {
ret = drm_agp_acquire(rdev->ddev);
if (ret) {
DRM_ERROR("Unable to acquire AGP: %d\n", ret);
return ret;
rv515_bandwidth_avivo_update(rdev);
}
}
 
ret = drm_agp_info(rdev->ddev, &info);
if (ret) {
DRM_ERROR("Unable to get AGP info: %d\n", ret);
return ret;
}
mode.mode = info.mode;
agp_status = (RREG32(RADEON_AGP_STATUS) | RADEON_AGPv3_MODE) & mode.mode;
is_v3 = !!(agp_status & RADEON_AGPv3_MODE);
 
if (is_v3) {
default_mode = (agp_status & RADEON_AGPv3_8X_MODE) ? 8 : 4;
} else {
if (agp_status & RADEON_AGP_4X_MODE) {
default_mode = 4;
} else if (agp_status & RADEON_AGP_2X_MODE) {
default_mode = 2;
} else {
default_mode = 1;
}
}
 
/* Apply AGPMode Quirks */
while (p && p->chip_device != 0) {
if (info.id_vendor == p->hostbridge_vendor &&
info.id_device == p->hostbridge_device &&
rdev->pdev->vendor == p->chip_vendor &&
rdev->pdev->device == p->chip_device &&
rdev->pdev->subsystem_vendor == p->subsys_vendor &&
rdev->pdev->subsystem_device == p->subsys_device) {
default_mode = p->default_mode;
}
++p;
}
 
if (radeon_agpmode > 0) {
if ((radeon_agpmode < (is_v3 ? 4 : 1)) ||
(radeon_agpmode > (is_v3 ? 8 : 4)) ||
(radeon_agpmode & (radeon_agpmode - 1))) {
DRM_ERROR("Illegal AGP Mode: %d (valid %s), leaving at %d\n",
radeon_agpmode, is_v3 ? "4, 8" : "1, 2, 4",
default_mode);
radeon_agpmode = default_mode;
} else {
DRM_INFO("AGP mode requested: %d\n", radeon_agpmode);
}
} else {
radeon_agpmode = default_mode;
}
 
mode.mode &= ~RADEON_AGP_MODE_MASK;
if (is_v3) {
switch (radeon_agpmode) {
case 8:
mode.mode |= RADEON_AGPv3_8X_MODE;
break;
case 4:
default:
mode.mode |= RADEON_AGPv3_4X_MODE;
break;
}
} else {
switch (radeon_agpmode) {
case 4:
mode.mode |= RADEON_AGP_4X_MODE;
break;
case 2:
mode.mode |= RADEON_AGP_2X_MODE;
break;
case 1:
default:
mode.mode |= RADEON_AGP_1X_MODE;
break;
}
}
 
mode.mode &= ~RADEON_AGP_FW_MODE; /* disable fw */
ret = drm_agp_enable(rdev->ddev, mode);
if (ret) {
DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode);
return ret;
}
 
rdev->mc.agp_base = rdev->ddev->agp->agp_info.aper_base;
rdev->mc.gtt_size = rdev->ddev->agp->agp_info.aper_size << 20;
 
/* workaround some hw issues */
if (rdev->family < CHIP_R200) {
WREG32(RADEON_AGP_CNTL, RREG32(RADEON_AGP_CNTL) | 0x000e0000);
}
return 0;
#else
return 0;
#endif
}
 
 
 
 
void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev);
 
 
 
 
int radeon_fence_driver_init(struct radeon_device *rdev)
{
unsigned long irq_flags;
int r;
 
// write_lock_irqsave(&rdev->fence_drv.lock, irq_flags);
r = radeon_scratch_get(rdev, &rdev->fence_drv.scratch_reg);
if (r) {
DRM_ERROR("Fence failed to get a scratch register.");
// write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
return r;
}
WREG32(rdev->fence_drv.scratch_reg, 0);
// atomic_set(&rdev->fence_drv.seq, 0);
// INIT_LIST_HEAD(&rdev->fence_drv.created);
// INIT_LIST_HEAD(&rdev->fence_drv.emited);
// INIT_LIST_HEAD(&rdev->fence_drv.signaled);
rdev->fence_drv.count_timeout = 0;
// init_waitqueue_head(&rdev->fence_drv.queue);
// write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
// if (radeon_debugfs_fence_init(rdev)) {
// DRM_ERROR("Failed to register debugfs file for fence !\n");
// }
return 0;
}
 
 
/drivers/video/drm/radeon/r600.c
67,7 → 67,7
"programming pipes. Bad things might happen.\n");
}
 
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1;
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(R600_MC_FB_TOP, tmp >> 24);
tmp |= REG_SET(R600_MC_FB_BASE, rdev->mc.vram_location >> 24);
WREG32(R600_MC_VM_FB_LOCATION, tmp);
140,7 → 140,8
void r600_vram_info(struct radeon_device *rdev)
{
r600_vram_get_type(rdev);
rdev->mc.vram_size = RREG32(R600_CONFIG_MEMSIZE);
rdev->mc.real_vram_size = RREG32(R600_CONFIG_MEMSIZE);
rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
 
/* Could aper size report 0 ? */
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
/drivers/video/drm/radeon/radeon.h
45,18 → 45,23
*/
 
#include <types.h>
#include <list.h>
#include <linux/list.h>
 
#include <pci.h>
 
#include <errno-base.h>
#include "drm_edid.h"
 
#include "radeon_family.h"
#include "radeon_mode.h"
#include "radeon_reg.h"
#include "r300.h"
 
#include <syscall.h>
 
/*
* Modules parameters.
*/
extern int radeon_no_wb;
extern int radeon_modeset;
extern int radeon_dynclks;
extern int radeon_r4xx_atom;
64,8 → 69,62
extern int radeon_vram_limit;
extern int radeon_gart_size;
extern int radeon_benchmarking;
extern int radeon_testing;
extern int radeon_connector_table;
extern int radeon_tv;
 
 
static inline uint8_t __raw_readb(const volatile void __iomem *addr)
{
return *(const volatile uint8_t __force *) addr;
}
 
static inline uint16_t __raw_readw(const volatile void __iomem *addr)
{
return *(const volatile uint16_t __force *) addr;
}
 
static inline uint32_t __raw_readl(const volatile void __iomem *addr)
{
return *(const volatile uint32_t __force *) addr;
}
 
#define readb __raw_readb
#define readw __raw_readw
#define readl __raw_readl
 
 
 
static inline void __raw_writeb(uint8_t b, volatile void __iomem *addr)
{
*(volatile uint8_t __force *) addr = b;
}
 
static inline void __raw_writew(uint16_t b, volatile void __iomem *addr)
{
*(volatile uint16_t __force *) addr = b;
}
 
static inline void __raw_writel(uint32_t b, volatile void __iomem *addr)
{
*(volatile uint32_t __force *) addr = b;
}
 
static inline void __raw_writeq(__u64 b, volatile void __iomem *addr)
{
*(volatile __u64 *)addr = b;
}
 
#define writeb __raw_writeb
#define writew __raw_writew
#define writel __raw_writel
#define writeq __raw_writeq
 
//#define writeb(b,addr) *(volatile uint8_t* ) addr = (uint8_t)b
//#define writew(b,addr) *(volatile uint16_t*) addr = (uint16_t)b
//#define writel(b,addr) *(volatile uint32_t*) addr = (uint32_t)b
 
 
/*
* Copy from radeon_drv.h so we don't have to include both and have conflicting
* symbol;
74,63 → 133,8
#define RADEON_IB_POOL_SIZE 16
#define RADEON_DEBUGFS_MAX_NUM_FILES 32
#define RADEONFB_CONN_LIMIT 4
#define RADEON_BIOS_NUM_SCRATCH 8
 
enum radeon_family {
CHIP_R100,
CHIP_RV100,
CHIP_RS100,
CHIP_RV200,
CHIP_RS200,
CHIP_R200,
CHIP_RV250,
CHIP_RS300,
CHIP_RV280,
CHIP_R300,
CHIP_R350,
CHIP_RV350,
CHIP_RV380,
CHIP_R420,
CHIP_R423,
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_RV610,
CHIP_RV630,
CHIP_RV620,
CHIP_RV635,
CHIP_RV670,
CHIP_RS780,
CHIP_RV770,
CHIP_RV730,
CHIP_RV710,
CHIP_LAST,
};
 
enum radeon_chip_flags {
RADEON_FAMILY_MASK = 0x0000ffffUL,
RADEON_FLAGS_MASK = 0xffff0000UL,
RADEON_IS_MOBILITY = 0x00010000UL,
RADEON_IS_IGP = 0x00020000UL,
RADEON_SINGLE_CRTC = 0x00040000UL,
RADEON_IS_AGP = 0x00080000UL,
RADEON_HAS_HIERZ = 0x00100000UL,
RADEON_IS_PCIE = 0x00200000UL,
RADEON_NEW_MEMMAP = 0x00400000UL,
RADEON_IS_PCI = 0x00800000UL,
RADEON_IS_IGPGART = 0x01000000UL,
};
 
 
/*
* Errata workarounds.
*/
149,10 → 153,21
*/
bool radeon_get_bios(struct radeon_device *rdev);
 
 
/*
* Dummy page
*/
struct radeon_dummy_page {
struct page *page;
dma_addr_t addr;
};
int radeon_dummy_page_init(struct radeon_device *rdev);
void radeon_dummy_page_fini(struct radeon_device *rdev);
 
 
/*
* Clocks
*/
 
struct radeon_clock {
struct radeon_pll p1pll;
struct radeon_pll p2pll;
163,6 → 178,7
uint32_t default_sclk;
};
 
 
/*
* Fences.
*/
201,7 → 217,15
struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
void radeon_fence_unref(struct radeon_fence **fence);
 
/*
* Tiling registers
*/
struct radeon_surface_reg {
struct radeon_object *robj;
};
 
#define RADEON_GEM_MAX_SURFACES 8
 
/*
* Radeon buffer.
*/
213,6 → 237,7
uint64_t gpu_offset;
unsigned rdomain;
unsigned wdomain;
uint32_t tiling_flags;
};
 
int radeon_object_init(struct radeon_device *rdev);
294,11 → 319,18
resource_size_t aper_size;
resource_size_t aper_base;
resource_size_t agp_base;
unsigned gtt_location;
unsigned gtt_size;
unsigned vram_location;
unsigned vram_size;
/* for some chips with <= 32MB we need to lie
* about vram size near mc fb location */
u64 mc_vram_size;
u64 gtt_location;
u64 gtt_size;
u64 gtt_start;
u64 gtt_end;
u64 vram_location;
u64 vram_start;
u64 vram_end;
unsigned vram_width;
u64 real_vram_size;
int vram_mtrr;
bool vram_is_ddr;
};
345,6 → 377,10
uint32_t length_dw;
};
 
/*
* locking -
* mutex protects scheduled_ibs, ready, alloc_bm
*/
struct radeon_ib_pool {
// struct mutex mutex;
struct radeon_object *robj;
370,6 → 406,16
bool ready;
};
 
struct r600_blit {
struct radeon_object *shader_obj;
u64 shader_gpu_addr;
u32 vs_offset, ps_offset;
u32 state_offset;
u32 state_len;
u32 vb_used, vb_total;
struct radeon_ib *vb_ib;
};
 
int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib);
void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib);
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib);
422,6 → 468,7
int chunk_relocs_idx;
struct radeon_ib *ib;
void *track;
unsigned family;
};
 
struct radeon_cs_packet {
456,6 → 503,38
uint64_t gpu_addr;
};
 
/**
* struct radeon_pm - power management datas
* @max_bandwidth: maximum bandwidth the gpu has (MByte/s)
* @igp_sideport_mclk: sideport memory clock Mhz (rs690,rs740,rs780,rs880)
* @igp_system_mclk: system clock Mhz (rs690,rs740,rs780,rs880)
* @igp_ht_link_clk: ht link clock Mhz (rs690,rs740,rs780,rs880)
* @igp_ht_link_width: ht link width in bits (rs690,rs740,rs780,rs880)
* @k8_bandwidth: k8 bandwidth the gpu has (MByte/s) (IGP)
* @sideport_bandwidth: sideport bandwidth the gpu has (MByte/s) (IGP)
* @ht_bandwidth: ht bandwidth the gpu has (MByte/s) (IGP)
* @core_bandwidth: core GPU bandwidth the gpu has (MByte/s) (IGP)
* @sclk: GPU clock Mhz (core bandwith depends of this clock)
* @needed_bandwidth: current bandwidth needs
*
* It keeps track of various data needed to take powermanagement decision.
* Bandwith need is used to determine minimun clock of the GPU and memory.
* Equation between gpu/memory clock and available bandwidth is hw dependent
* (type of memory, bus size, efficiency, ...)
*/
struct radeon_pm {
fixed20_12 max_bandwidth;
fixed20_12 igp_sideport_mclk;
fixed20_12 igp_system_mclk;
fixed20_12 igp_ht_link_clk;
fixed20_12 igp_ht_link_width;
fixed20_12 k8_bandwidth;
fixed20_12 sideport_bandwidth;
fixed20_12 ht_bandwidth;
fixed20_12 core_bandwidth;
fixed20_12 sclk;
fixed20_12 needed_bandwidth;
};
 
/*
* ASIC specific functions.
462,13 → 541,19
*/
struct radeon_asic {
int (*init)(struct radeon_device *rdev);
void (*fini)(struct radeon_device *rdev);
int (*resume)(struct radeon_device *rdev);
int (*suspend)(struct radeon_device *rdev);
void (*errata)(struct radeon_device *rdev);
void (*vram_info)(struct radeon_device *rdev);
void (*vga_set_state)(struct radeon_device *rdev, bool state);
int (*gpu_reset)(struct radeon_device *rdev);
int (*mc_init)(struct radeon_device *rdev);
void (*mc_fini)(struct radeon_device *rdev);
int (*wb_init)(struct radeon_device *rdev);
void (*wb_fini)(struct radeon_device *rdev);
int (*gart_init)(struct radeon_device *rdev);
void (*gart_fini)(struct radeon_device *rdev);
int (*gart_enable)(struct radeon_device *rdev);
void (*gart_disable)(struct radeon_device *rdev);
void (*gart_tlb_flush)(struct radeon_device *rdev);
476,9 → 561,14
int (*cp_init)(struct radeon_device *rdev, unsigned ring_size);
void (*cp_fini)(struct radeon_device *rdev);
void (*cp_disable)(struct radeon_device *rdev);
void (*cp_commit)(struct radeon_device *rdev);
void (*ring_start)(struct radeon_device *rdev);
int (*ring_test)(struct radeon_device *rdev);
void (*ring_ib_execute)(struct radeon_device *rdev, struct radeon_ib *ib);
int (*ib_test)(struct radeon_device *rdev);
int (*irq_set)(struct radeon_device *rdev);
int (*irq_process)(struct radeon_device *rdev);
u32 (*get_vblank_counter)(struct radeon_device *rdev, int crtc);
void (*fence_ring_emit)(struct radeon_device *rdev, struct radeon_fence *fence);
int (*cs_parse)(struct radeon_cs_parser *p);
int (*copy_blit)(struct radeon_device *rdev,
500,14 → 590,75
void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock);
void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes);
void (*set_clock_gating)(struct radeon_device *rdev, int enable);
int (*set_surface_reg)(struct radeon_device *rdev, int reg,
uint32_t tiling_flags, uint32_t pitch,
uint32_t offset, uint32_t obj_size);
int (*clear_surface_reg)(struct radeon_device *rdev, int reg);
void (*bandwidth_update)(struct radeon_device *rdev);
};
 
/*
* Asic structures
*/
struct r100_asic {
const unsigned *reg_safe_bm;
unsigned reg_safe_bm_size;
};
 
struct r300_asic {
const unsigned *reg_safe_bm;
unsigned reg_safe_bm_size;
};
 
struct r600_asic {
unsigned max_pipes;
unsigned max_tile_pipes;
unsigned max_simds;
unsigned max_backends;
unsigned max_gprs;
unsigned max_threads;
unsigned max_stack_entries;
unsigned max_hw_contexts;
unsigned max_gs_threads;
unsigned sx_max_export_size;
unsigned sx_max_export_pos_size;
unsigned sx_max_export_smx_size;
unsigned sq_num_cf_insts;
};
 
struct rv770_asic {
unsigned max_pipes;
unsigned max_tile_pipes;
unsigned max_simds;
unsigned max_backends;
unsigned max_gprs;
unsigned max_threads;
unsigned max_stack_entries;
unsigned max_hw_contexts;
unsigned max_gs_threads;
unsigned sx_max_export_size;
unsigned sx_max_export_pos_size;
unsigned sx_max_export_smx_size;
unsigned sq_num_cf_insts;
unsigned sx_num_of_sets;
unsigned sc_prim_fifo_size;
unsigned sc_hiz_tile_fifo_size;
unsigned sc_earlyz_tile_fifo_fize;
};
 
union radeon_asic_config {
struct r300_asic r300;
struct r100_asic r100;
struct r600_asic r600;
struct rv770_asic rv770;
};
 
 
/*
 
 
 
 
/*
* Core structure, functions and helpers.
*/
524,6 → 675,7
int usec_timeout;
enum radeon_pll_errata pll_errata;
int num_gb_pipes;
int num_z_pipes;
int disp_priority;
/* BIOS */
uint8_t *bios;
534,20 → 686,15
struct fb_info *fbdev_info;
struct radeon_object *fbdev_robj;
struct radeon_framebuffer *fbdev_rfb;
 
/* Register mmio */
unsigned long rmmio_base;
unsigned long rmmio_size;
void *rmmio;
 
radeon_rreg_t mm_rreg;
radeon_wreg_t mm_wreg;
radeon_rreg_t mc_rreg;
radeon_wreg_t mc_wreg;
radeon_rreg_t pll_rreg;
radeon_wreg_t pll_wreg;
radeon_rreg_t pcie_rreg;
radeon_wreg_t pcie_wreg;
uint32_t pcie_reg_mask;
radeon_rreg_t pciep_rreg;
radeon_wreg_t pciep_wreg;
struct radeon_clock clock;
562,11 → 709,21
// struct radeon_irq irq;
struct radeon_asic *asic;
struct radeon_gem gem;
struct radeon_pm pm;
uint32_t bios_scratch[RADEON_BIOS_NUM_SCRATCH];
// struct mutex cs_mutex;
struct radeon_wb wb;
struct radeon_dummy_page dummy_page;
bool gpu_lockup;
bool shutdown;
bool suspend;
bool need_dma32;
bool new_init_path;
bool accel_working;
struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES];
const struct firmware *me_fw; /* all family ME firmware */
const struct firmware *pfp_fw; /* r6/700 PFP firmware */
struct r600_blit r600_blit;
};
 
int radeon_device_init(struct radeon_device *rdev,
576,70 → 733,41
void radeon_device_fini(struct radeon_device *rdev);
int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
 
#define __iomem
#define __force
/* r600 blit */
int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes);
void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence);
void r600_kms_blit_copy(struct radeon_device *rdev,
u64 src_gpu_addr, u64 dst_gpu_addr,
int size_bytes);
 
 
 
static inline uint8_t __raw_readb(const volatile void __iomem *addr)
static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
{
return *(const volatile uint8_t __force *) addr;
if (reg < 0x10000)
return readl(((void __iomem *)rdev->rmmio) + reg);
else {
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
}
 
static inline uint16_t __raw_readw(const volatile void __iomem *addr)
{
return *(const volatile uint16_t __force *) addr;
}
 
static inline uint32_t __raw_readl(const volatile void __iomem *addr)
static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
{
return *(const volatile uint32_t __force *) addr;
if (reg < 0x10000)
writel(v, ((void __iomem *)rdev->rmmio) + reg);
else {
writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
}
 
#define readb __raw_readb
#define readw __raw_readw
#define readl __raw_readl
 
 
 
static inline void __raw_writeb(uint8_t b, volatile void __iomem *addr)
{
*(volatile uint8_t __force *) addr = b;
}
 
static inline void __raw_writew(uint16_t b, volatile void __iomem *addr)
{
*(volatile uint16_t __force *) addr = b;
}
 
static inline void __raw_writel(uint32_t b, volatile void __iomem *addr)
{
*(volatile uint32_t __force *) addr = b;
}
 
static inline void __raw_writeq(__u64 b, volatile void __iomem *addr)
{
*(volatile __u64 *)addr = b;
}
 
#define writeb __raw_writeb
#define writew __raw_writew
#define writel __raw_writel
#define writeq __raw_writeq
 
//#define writeb(b,addr) *(volatile uint8_t* ) addr = (uint8_t)b
//#define writew(b,addr) *(volatile uint16_t*) addr = (uint16_t)b
//#define writel(b,addr) *(volatile uint32_t*) addr = (uint32_t)b
 
 
 
/*
* Registers read & write functions.
*/
#define RREG8(reg) readb(((void __iomem *)rdev->rmmio) + (reg))
#define WREG8(reg, v) writeb(v, ((void __iomem *)rdev->rmmio) + (reg))
#define RREG32(reg) rdev->mm_rreg(rdev, (reg))
#define WREG32(reg, v) rdev->mm_wreg(rdev, (reg), (v))
#define RREG32(reg) r100_mm_rreg(rdev, (reg))
#define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v))
#define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
#define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
#define RREG32_PLL(reg) rdev->pll_rreg(rdev, (reg))
646,8 → 774,8
#define WREG32_PLL(reg, v) rdev->pll_wreg(rdev, (reg), (v))
#define RREG32_MC(reg) rdev->mc_rreg(rdev, (reg))
#define WREG32_MC(reg, v) rdev->mc_wreg(rdev, (reg), (v))
#define RREG32_PCIE(reg) rdev->pcie_rreg(rdev, (reg))
#define WREG32_PCIE(reg, v) rdev->pcie_wreg(rdev, (reg), (v))
#define RREG32_PCIE(reg) rv370_pcie_rreg(rdev, (reg))
#define WREG32_PCIE(reg, v) rv370_pcie_wreg(rdev, (reg), (v))
#define WREG32_P(reg, val, mask) \
do { \
uint32_t tmp_ = RREG32(reg); \
663,7 → 791,34
WREG32_PLL(reg, tmp_); \
} while (0)
 
/*
* Indirect registers accessor
*/
static inline uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg)
{
uint32_t r;
 
WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask));
r = RREG32(RADEON_PCIE_DATA);
return r;
}
 
static inline void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
{
WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask));
WREG32(RADEON_PCIE_DATA, (v));
}
 
void r100_pll_errata_after_index(struct radeon_device *rdev);
 
 
 
 
 
 
 
 
 
#define radeon_PCI_IDS \
{0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
{0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
1075,6 → 1230,8
/*
* ASICs helpers.
*/
#define ASIC_IS_RN50(rdev) ((rdev->pdev->device == 0x515e) || \
(rdev->pdev->device == 0x5969))
#define ASIC_IS_RV100(rdev) ((rdev->family == CHIP_RV100) || \
(rdev->family == CHIP_RV200) || \
(rdev->family == CHIP_RS100) || \
1175,14 → 1332,20
* ASICs macro.
*/
#define radeon_init(rdev) (rdev)->asic->init((rdev))
#define radeon_fini(rdev) (rdev)->asic->fini((rdev))
#define radeon_resume(rdev) (rdev)->asic->resume((rdev))
#define radeon_suspend(rdev) (rdev)->asic->suspend((rdev))
#define radeon_cs_parse(p) rdev->asic->cs_parse((p))
#define radeon_errata(rdev) (rdev)->asic->errata((rdev))
#define radeon_vram_info(rdev) (rdev)->asic->vram_info((rdev))
#define radeon_vga_set_state(rdev, state) (rdev)->asic->vga_set_state((rdev), (state))
#define radeon_gpu_reset(rdev) (rdev)->asic->gpu_reset((rdev))
#define radeon_mc_init(rdev) (rdev)->asic->mc_init((rdev))
#define radeon_mc_fini(rdev) (rdev)->asic->mc_fini((rdev))
#define radeon_wb_init(rdev) (rdev)->asic->wb_init((rdev))
#define radeon_wb_fini(rdev) (rdev)->asic->wb_fini((rdev))
#define radeon_gpu_gart_init(rdev) (rdev)->asic->gart_init((rdev))
#define radeon_gpu_gart_fini(rdev) (rdev)->asic->gart_fini((rdev))
#define radeon_gart_enable(rdev) (rdev)->asic->gart_enable((rdev))
#define radeon_gart_disable(rdev) (rdev)->asic->gart_disable((rdev))
#define radeon_gart_tlb_flush(rdev) (rdev)->asic->gart_tlb_flush((rdev))
1190,9 → 1353,14
#define radeon_cp_init(rdev,rsize) (rdev)->asic->cp_init((rdev), (rsize))
#define radeon_cp_fini(rdev) (rdev)->asic->cp_fini((rdev))
#define radeon_cp_disable(rdev) (rdev)->asic->cp_disable((rdev))
#define radeon_cp_commit(rdev) (rdev)->asic->cp_commit((rdev))
#define radeon_ring_start(rdev) (rdev)->asic->ring_start((rdev))
#define radeon_ring_test(rdev) (rdev)->asic->ring_test((rdev))
#define radeon_ring_ib_execute(rdev, ib) (rdev)->asic->ring_ib_execute((rdev), (ib))
#define radeon_ib_test(rdev) (rdev)->asic->ib_test((rdev))
#define radeon_irq_set(rdev) (rdev)->asic->irq_set((rdev))
#define radeon_irq_process(rdev) (rdev)->asic->irq_process((rdev))
#define radeon_get_vblank_counter(rdev, crtc) (rdev)->asic->get_vblank_counter((rdev), (crtc))
#define radeon_fence_ring_emit(rdev, fence) (rdev)->asic->fence_ring_emit((rdev), (fence))
#define radeon_copy_blit(rdev, s, d, np, f) (rdev)->asic->copy_blit((rdev), (s), (d), (np), (f))
#define radeon_copy_dma(rdev, s, d, np, f) (rdev)->asic->copy_dma((rdev), (s), (d), (np), (f))
1201,8 → 1369,102
#define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e))
#define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l))
#define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e))
#define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s)))
#define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r)))
#define radeon_bandwidth_update(rdev) (rdev)->asic->bandwidth_update((rdev))
 
/* Common functions */
extern int radeon_gart_table_vram_pin(struct radeon_device *rdev);
extern int radeon_modeset_init(struct radeon_device *rdev);
extern void radeon_modeset_fini(struct radeon_device *rdev);
extern bool radeon_card_posted(struct radeon_device *rdev);
extern int radeon_clocks_init(struct radeon_device *rdev);
extern void radeon_clocks_fini(struct radeon_device *rdev);
extern void radeon_scratch_init(struct radeon_device *rdev);
extern void radeon_surface_init(struct radeon_device *rdev);
extern int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data);
 
/* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */
struct r100_mc_save {
u32 GENMO_WT;
u32 CRTC_EXT_CNTL;
u32 CRTC_GEN_CNTL;
u32 CRTC2_GEN_CNTL;
u32 CUR_OFFSET;
u32 CUR2_OFFSET;
};
extern void r100_cp_disable(struct radeon_device *rdev);
extern int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
extern void r100_cp_fini(struct radeon_device *rdev);
extern void r100_pci_gart_tlb_flush(struct radeon_device *rdev);
extern int r100_pci_gart_init(struct radeon_device *rdev);
extern void r100_pci_gart_fini(struct radeon_device *rdev);
extern int r100_pci_gart_enable(struct radeon_device *rdev);
extern void r100_pci_gart_disable(struct radeon_device *rdev);
extern int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
extern int r100_debugfs_mc_info_init(struct radeon_device *rdev);
extern int r100_gui_wait_for_idle(struct radeon_device *rdev);
extern void r100_ib_fini(struct radeon_device *rdev);
extern int r100_ib_init(struct radeon_device *rdev);
extern void r100_irq_disable(struct radeon_device *rdev);
extern int r100_irq_set(struct radeon_device *rdev);
extern void r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save);
extern void r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save);
extern void r100_vram_init_sizes(struct radeon_device *rdev);
extern void r100_wb_disable(struct radeon_device *rdev);
extern void r100_wb_fini(struct radeon_device *rdev);
extern int r100_wb_init(struct radeon_device *rdev);
 
/* r300,r350,rv350,rv370,rv380 */
extern void r300_set_reg_safe(struct radeon_device *rdev);
extern void r300_mc_program(struct radeon_device *rdev);
extern void r300_vram_info(struct radeon_device *rdev);
extern int rv370_pcie_gart_init(struct radeon_device *rdev);
extern void rv370_pcie_gart_fini(struct radeon_device *rdev);
extern int rv370_pcie_gart_enable(struct radeon_device *rdev);
extern void rv370_pcie_gart_disable(struct radeon_device *rdev);
 
/* r420,r423,rv410 */
extern u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg);
extern void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v);
extern int r420_debugfs_pipes_info_init(struct radeon_device *rdev);
 
/* rv515 */
extern void rv515_bandwidth_avivo_update(struct radeon_device *rdev);
 
/* rs690, rs740 */
extern void rs690_line_buffer_adjust(struct radeon_device *rdev,
struct drm_display_mode *mode1,
struct drm_display_mode *mode2);
 
/* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */
extern bool r600_card_posted(struct radeon_device *rdev);
extern void r600_cp_stop(struct radeon_device *rdev);
extern void r600_ring_init(struct radeon_device *rdev, unsigned ring_size);
extern int r600_cp_resume(struct radeon_device *rdev);
extern int r600_count_pipe_bits(uint32_t val);
extern int r600_gart_clear_page(struct radeon_device *rdev, int i);
extern int r600_mc_wait_for_idle(struct radeon_device *rdev);
extern int r600_pcie_gart_init(struct radeon_device *rdev);
extern void r600_pcie_gart_tlb_flush(struct radeon_device *rdev);
extern int r600_ib_test(struct radeon_device *rdev);
extern int r600_ring_test(struct radeon_device *rdev);
extern int r600_wb_init(struct radeon_device *rdev);
extern void r600_wb_fini(struct radeon_device *rdev);
extern void r600_scratch_init(struct radeon_device *rdev);
extern int r600_blit_init(struct radeon_device *rdev);
extern void r600_blit_fini(struct radeon_device *rdev);
extern int r600_cp_init_microcode(struct radeon_device *rdev);
extern int r600_gpu_reset(struct radeon_device *rdev);
 
 
 
 
 
 
 
 
 
#define DRM_UDELAY(d) udelay(d)
 
resource_size_t
1212,4 → 1474,6
 
bool set_mode(struct drm_device *dev, int width, int height);
 
 
 
#endif
/drivers/video/drm/radeon/radeon_asic.h
42,16 → 42,21
* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
*/
int r100_init(struct radeon_device *rdev);
int r200_init(struct radeon_device *rdev);
uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg);
void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
void r100_errata(struct radeon_device *rdev);
void r100_vram_info(struct radeon_device *rdev);
void r100_vga_set_state(struct radeon_device *rdev, bool state);
int r100_gpu_reset(struct radeon_device *rdev);
int r100_mc_init(struct radeon_device *rdev);
void r100_mc_fini(struct radeon_device *rdev);
u32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc);
int r100_wb_init(struct radeon_device *rdev);
void r100_wb_fini(struct radeon_device *rdev);
int r100_gart_enable(struct radeon_device *rdev);
int r100_pci_gart_init(struct radeon_device *rdev);
void r100_pci_gart_fini(struct radeon_device *rdev);
int r100_pci_gart_enable(struct radeon_device *rdev);
void r100_pci_gart_disable(struct radeon_device *rdev);
void r100_pci_gart_tlb_flush(struct radeon_device *rdev);
int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
58,6 → 63,7
int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
void r100_cp_fini(struct radeon_device *rdev);
void r100_cp_disable(struct radeon_device *rdev);
void r100_cp_commit(struct radeon_device *rdev);
void r100_ring_start(struct radeon_device *rdev);
int r100_irq_set(struct radeon_device *rdev);
int r100_irq_process(struct radeon_device *rdev);
71,8 → 77,15
uint64_t dst_offset,
unsigned num_pages,
struct radeon_fence *fence);
int r100_set_surface_reg(struct radeon_device *rdev, int reg,
uint32_t tiling_flags, uint32_t pitch,
uint32_t offset, uint32_t obj_size);
int r100_clear_surface_reg(struct radeon_device *rdev, int reg);
void r100_bandwidth_update(struct radeon_device *rdev);
void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
int r100_ib_test(struct radeon_device *rdev);
int r100_ring_test(struct radeon_device *rdev);
 
 
static struct radeon_asic r100_asic = {
.init = &r100_init,
.errata = &r100_errata,
82,7 → 95,7
.mc_fini = &r100_mc_fini,
// .wb_init = &r100_wb_init,
// .wb_fini = &r100_wb_fini,
.gart_enable = &r100_gart_enable,
.gart_enable = &r100_pci_gart_enable,
.gart_disable = &r100_pci_gart_disable,
.gart_tlb_flush = &r100_pci_gart_tlb_flush,
.gart_set_page = &r100_pci_gart_set_page,
101,6 → 114,9
// .set_memory_clock = NULL,
// .set_pcie_lanes = NULL,
// .set_clock_gating = &radeon_legacy_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r100_bandwidth_update,
};
 
 
117,7 → 133,9
void r300_fence_ring_emit(struct radeon_device *rdev,
struct radeon_fence *fence);
int r300_cs_parse(struct radeon_cs_parser *p);
int r300_gart_enable(struct radeon_device *rdev);
int rv370_pcie_gart_init(struct radeon_device *rdev);
void rv370_pcie_gart_fini(struct radeon_device *rdev);
int rv370_pcie_gart_enable(struct radeon_device *rdev);
void rv370_pcie_gart_disable(struct radeon_device *rdev);
void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev);
int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
130,17 → 148,17
unsigned num_pages,
struct radeon_fence *fence);
 
 
static struct radeon_asic r300_asic = {
.init = &r300_init,
.errata = &r300_errata,
.vram_info = &r300_vram_info,
.vga_set_state = &r100_vga_set_state,
.gpu_reset = &r300_gpu_reset,
.mc_init = &r300_mc_init,
.mc_fini = &r300_mc_fini,
// .wb_init = &r100_wb_init,
// .wb_fini = &r100_wb_fini,
.gart_enable = &r300_gart_enable,
.gart_enable = &r100_pci_gart_enable,
.gart_disable = &r100_pci_gart_disable,
.gart_tlb_flush = &r100_pci_gart_tlb_flush,
.gart_set_page = &r100_pci_gart_set_page,
159,32 → 177,38
// .set_memory_clock = NULL,
// .set_pcie_lanes = &rv370_set_pcie_lanes,
// .set_clock_gating = &radeon_legacy_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r100_bandwidth_update,
};
 
 
/*
* r420,r423,rv410
*/
void r420_errata(struct radeon_device *rdev);
void r420_vram_info(struct radeon_device *rdev);
int r420_mc_init(struct radeon_device *rdev);
void r420_mc_fini(struct radeon_device *rdev);
extern int r420_init(struct radeon_device *rdev);
extern void r420_fini(struct radeon_device *rdev);
extern int r420_suspend(struct radeon_device *rdev);
extern int r420_resume(struct radeon_device *rdev);
static struct radeon_asic r420_asic = {
.init = &r300_init,
.errata = &r420_errata,
.vram_info = &r420_vram_info,
.init = &r420_init,
.fini = &r420_fini,
.suspend = &r420_suspend,
.resume = &r420_resume,
.errata = NULL,
.vram_info = NULL,
.vga_set_state = &r100_vga_set_state,
.gpu_reset = &r300_gpu_reset,
.mc_init = &r420_mc_init,
.mc_fini = &r420_mc_fini,
// .wb_init = &r100_wb_init,
// .wb_fini = &r100_wb_fini,
.gart_enable = &r300_gart_enable,
.gart_disable = &rv370_pcie_gart_disable,
.mc_init = NULL,
.mc_fini = NULL,
.wb_init = NULL,
.wb_fini = NULL,
.gart_enable = NULL,
.gart_disable = NULL,
.gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
.gart_set_page = &rv370_pcie_gart_set_page,
.cp_init = &r100_cp_init,
// .cp_fini = &r100_cp_fini,
// .cp_disable = &r100_cp_disable,
.cp_init = NULL,
.cp_fini = NULL,
.cp_disable = NULL,
.ring_start = &r300_ring_start,
// .irq_set = &r100_irq_set,
// .irq_process = &r100_irq_process,
197,6 → 221,9
// .set_memory_clock = &radeon_atom_set_memory_clock,
// .set_pcie_lanes = &rv370_set_pcie_lanes,
// .set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r100_bandwidth_update,
};
 
 
207,6 → 234,8
void rs400_vram_info(struct radeon_device *rdev);
int rs400_mc_init(struct radeon_device *rdev);
void rs400_mc_fini(struct radeon_device *rdev);
int rs400_gart_init(struct radeon_device *rdev);
void rs400_gart_fini(struct radeon_device *rdev);
int rs400_gart_enable(struct radeon_device *rdev);
void rs400_gart_disable(struct radeon_device *rdev);
void rs400_gart_tlb_flush(struct radeon_device *rdev);
217,11 → 246,14
.init = &r300_init,
.errata = &rs400_errata,
.vram_info = &rs400_vram_info,
.vga_set_state = &r100_vga_set_state,
.gpu_reset = &r300_gpu_reset,
.mc_init = &rs400_mc_init,
.mc_fini = &rs400_mc_fini,
// .wb_init = &r100_wb_init,
// .wb_fini = &r100_wb_fini,
.gart_init = &rs400_gart_init,
.gart_fini = &rs400_gart_fini,
.gart_enable = &rs400_gart_enable,
.gart_disable = &rs400_gart_disable,
.gart_tlb_flush = &rs400_gart_tlb_flush,
229,6 → 261,7
.cp_init = &r100_cp_init,
// .cp_fini = &r100_cp_fini,
// .cp_disable = &r100_cp_disable,
.cp_commit = &r100_cp_commit,
.ring_start = &r300_ring_start,
// .irq_set = &r100_irq_set,
// .irq_process = &r100_irq_process,
241,6 → 274,9
// .set_memory_clock = NULL,
// .set_pcie_lanes = NULL,
// .set_clock_gating = &radeon_legacy_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r100_bandwidth_update,
};
 
 
247,11 → 283,16
/*
* rs600.
*/
int rs600_init(struct radeon_device *rdev);
void rs600_errata(struct radeon_device *rdev);
void rs600_vram_info(struct radeon_device *rdev);
int rs600_mc_init(struct radeon_device *rdev);
void rs600_mc_fini(struct radeon_device *rdev);
int rs600_irq_set(struct radeon_device *rdev);
int rs600_irq_process(struct radeon_device *rdev);
u32 rs600_get_vblank_counter(struct radeon_device *rdev, int crtc);
int rs600_gart_init(struct radeon_device *rdev);
void rs600_gart_fini(struct radeon_device *rdev);
int rs600_gart_enable(struct radeon_device *rdev);
void rs600_gart_disable(struct radeon_device *rdev);
void rs600_gart_tlb_flush(struct radeon_device *rdev);
258,16 → 299,19
int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg);
void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 
void rs600_bandwidth_update(struct radeon_device *rdev);
static struct radeon_asic rs600_asic = {
.init = &r300_init,
.init = &rs600_init,
.errata = &rs600_errata,
.vram_info = &rs600_vram_info,
.vga_set_state = &r100_vga_set_state,
.gpu_reset = &r300_gpu_reset,
.mc_init = &rs600_mc_init,
.mc_fini = &rs600_mc_fini,
// .wb_init = &r100_wb_init,
// .wb_fini = &r100_wb_fini,
.gart_init = &rs600_gart_init,
.gart_fini = &rs600_gart_fini,
.gart_enable = &rs600_gart_enable,
.gart_disable = &rs600_gart_disable,
.gart_tlb_flush = &rs600_gart_tlb_flush,
275,6 → 319,7
.cp_init = &r100_cp_init,
// .cp_fini = &r100_cp_fini,
// .cp_disable = &r100_cp_disable,
.cp_commit = &r100_cp_commit,
.ring_start = &r300_ring_start,
// .irq_set = &rs600_irq_set,
// .irq_process = &r100_irq_process,
287,6 → 332,7
// .set_memory_clock = &radeon_atom_set_memory_clock,
// .set_pcie_lanes = NULL,
// .set_clock_gating = &radeon_atom_set_clock_gating,
.bandwidth_update = &rs600_bandwidth_update,
};
 
 
299,15 → 345,19
void rs690_mc_fini(struct radeon_device *rdev);
uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg);
void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
void rs690_bandwidth_update(struct radeon_device *rdev);
static struct radeon_asic rs690_asic = {
.init = &r300_init,
.init = &rs600_init,
.errata = &rs690_errata,
.vram_info = &rs690_vram_info,
.vga_set_state = &r100_vga_set_state,
.gpu_reset = &r300_gpu_reset,
.mc_init = &rs690_mc_init,
.mc_fini = &rs690_mc_fini,
// .wb_init = &r100_wb_init,
// .wb_fini = &r100_wb_fini,
.gart_init = &rs400_gart_init,
.gart_fini = &rs400_gart_fini,
.gart_enable = &rs400_gart_enable,
.gart_disable = &rs400_gart_disable,
.gart_tlb_flush = &rs400_gart_tlb_flush,
315,6 → 365,7
.cp_init = &r100_cp_init,
// .cp_fini = &r100_cp_fini,
// .cp_disable = &r100_cp_disable,
.cp_commit = &r100_cp_commit,
.ring_start = &r300_ring_start,
// .irq_set = &rs600_irq_set,
// .irq_process = &r100_irq_process,
327,8 → 378,12
// .set_memory_clock = &radeon_atom_set_memory_clock,
// .set_pcie_lanes = NULL,
// .set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &rs690_bandwidth_update,
};
 
 
/*
* rv515
*/
343,18 → 398,20
void rv515_ring_start(struct radeon_device *rdev);
uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 
 
void rv515_bandwidth_update(struct radeon_device *rdev);
static struct radeon_asic rv515_asic = {
.init = &rv515_init,
.errata = &rv515_errata,
.vram_info = &rv515_vram_info,
.vga_set_state = &r100_vga_set_state,
.gpu_reset = &rv515_gpu_reset,
.mc_init = &rv515_mc_init,
.mc_fini = &rv515_mc_fini,
// .wb_init = &r100_wb_init,
// .wb_fini = &r100_wb_fini,
.gart_enable = &r300_gart_enable,
.gart_init = &rv370_pcie_gart_init,
.gart_fini = &rv370_pcie_gart_fini,
.gart_enable = &rv370_pcie_gart_enable,
.gart_disable = &rv370_pcie_gart_disable,
.gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
.gart_set_page = &rv370_pcie_gart_set_page,
361,6 → 418,7
.cp_init = &r100_cp_init,
// .cp_fini = &r100_cp_fini,
// .cp_disable = &r100_cp_disable,
.cp_commit = &r100_cp_commit,
.ring_start = &rv515_ring_start,
// .irq_set = &r100_irq_set,
// .irq_process = &r100_irq_process,
373,6 → 431,9
// .set_memory_clock = &radeon_atom_set_memory_clock,
// .set_pcie_lanes = &rv370_set_pcie_lanes,
// .set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &rv515_bandwidth_update,
};
 
 
383,17 → 444,20
void r520_vram_info(struct radeon_device *rdev);
int r520_mc_init(struct radeon_device *rdev);
void r520_mc_fini(struct radeon_device *rdev);
 
void r520_bandwidth_update(struct radeon_device *rdev);
static struct radeon_asic r520_asic = {
.init = &rv515_init,
.errata = &r520_errata,
.vram_info = &r520_vram_info,
.vga_set_state = &r100_vga_set_state,
.gpu_reset = &rv515_gpu_reset,
.mc_init = &r520_mc_init,
.mc_fini = &r520_mc_fini,
// .wb_init = &r100_wb_init,
// .wb_fini = &r100_wb_fini,
.gart_enable = &r300_gart_enable,
.gart_init = &rv370_pcie_gart_init,
.gart_fini = &rv370_pcie_gart_fini,
.gart_enable = &rv370_pcie_gart_enable,
.gart_disable = &rv370_pcie_gart_disable,
.gart_tlb_flush = &rv370_pcie_gart_tlb_flush,
.gart_set_page = &rv370_pcie_gart_set_page,
400,6 → 464,7
.cp_init = &r100_cp_init,
// .cp_fini = &r100_cp_fini,
// .cp_disable = &r100_cp_disable,
.cp_commit = &r100_cp_commit,
.ring_start = &rv515_ring_start,
// .irq_set = &r100_irq_set,
// .irq_process = &r100_irq_process,
412,11 → 477,23
// .set_memory_clock = &radeon_atom_set_memory_clock,
// .set_pcie_lanes = &rv370_set_pcie_lanes,
// .set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r520_bandwidth_update,
};
 
/*
* r600,rv610,rv630,rv620,rv635,rv670,rs780,rv770,rv730,rv710
*/
int r600_init(struct radeon_device *rdev);
void r600_fini(struct radeon_device *rdev);
int r600_suspend(struct radeon_device *rdev);
int r600_resume(struct radeon_device *rdev);
void r600_vga_set_state(struct radeon_device *rdev, bool state);
int r600_wb_init(struct radeon_device *rdev);
void r600_wb_fini(struct radeon_device *rdev);
void r600_cp_commit(struct radeon_device *rdev);
void r600_pcie_gart_tlb_flush(struct radeon_device *rdev);
uint32_t r600_pciep_rreg(struct radeon_device *rdev, uint32_t reg);
void r600_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 
/drivers/video/drm/radeon/radeon_atombios.c
103,7 → 103,8
static bool radeon_atom_apply_quirks(struct drm_device *dev,
uint32_t supported_device,
int *connector_type,
struct radeon_i2c_bus_rec *i2c_bus)
struct radeon_i2c_bus_rec *i2c_bus,
uint16_t *line_mux)
{
 
/* Asus M2A-VM HDMI board lists the DVI port as HDMI */
127,9 → 128,11
if ((dev->pdev->device == 0x5653) &&
(dev->pdev->subsystem_vendor == 0x1462) &&
(dev->pdev->subsystem_device == 0x0291)) {
if (*connector_type == DRM_MODE_CONNECTOR_LVDS)
if (*connector_type == DRM_MODE_CONNECTOR_LVDS) {
i2c_bus->valid = false;
*line_mux = 53;
}
}
 
/* Funky macbooks */
if ((dev->pdev->device == 0x71C5) &&
140,23 → 143,34
return false;
}
 
/* some BIOSes seem to report DAC on HDMI - they hurt me with their lies */
if ((*connector_type == DRM_MODE_CONNECTOR_HDMIA) ||
(*connector_type == DRM_MODE_CONNECTOR_HDMIB)) {
if (supported_device & (ATOM_DEVICE_CRT_SUPPORT)) {
return false;
}
}
 
/* ASUS HD 3600 XT board lists the DVI port as HDMI */
if ((dev->pdev->device == 0x9598) &&
(dev->pdev->subsystem_vendor == 0x1043) &&
(dev->pdev->subsystem_device == 0x01da)) {
if (*connector_type == DRM_MODE_CONNECTOR_HDMIB) {
*connector_type = DRM_MODE_CONNECTOR_DVID;
if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
*connector_type = DRM_MODE_CONNECTOR_DVII;
}
}
 
/* ASUS HD 3450 board lists the DVI port as HDMI */
if ((dev->pdev->device == 0x95C5) &&
(dev->pdev->subsystem_vendor == 0x1043) &&
(dev->pdev->subsystem_device == 0x01e2)) {
if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
*connector_type = DRM_MODE_CONNECTOR_DVII;
}
}
 
/* some BIOSes seem to report DAC on HDMI - usually this is a board with
* HDMI + VGA reporting as HDMI
*/
if (*connector_type == DRM_MODE_CONNECTOR_HDMIA) {
if (supported_device & (ATOM_DEVICE_CRT_SUPPORT)) {
*connector_type = DRM_MODE_CONNECTOR_VGA;
*line_mux = 0;
}
}
 
return true;
}
 
189,11 → 203,11
DRM_MODE_CONNECTOR_Composite,
DRM_MODE_CONNECTOR_SVIDEO,
DRM_MODE_CONNECTOR_Unknown,
DRM_MODE_CONNECTOR_Unknown,
DRM_MODE_CONNECTOR_9PinDIN,
DRM_MODE_CONNECTOR_Unknown,
DRM_MODE_CONNECTOR_HDMIA,
DRM_MODE_CONNECTOR_HDMIB,
DRM_MODE_CONNECTOR_HDMIB,
DRM_MODE_CONNECTOR_LVDS,
DRM_MODE_CONNECTOR_9PinDIN,
DRM_MODE_CONNECTOR_Unknown,
215,7 → 229,7
ATOM_OBJECT_HEADER *obj_header;
int i, j, path_size, device_support;
int connector_type;
uint16_t igp_lane_info;
uint16_t igp_lane_info, conn_id;
bool linkb;
struct radeon_i2c_bus_rec ddc_bus;
 
367,10 → 381,6
&& record->
ucRecordType <=
ATOM_MAX_OBJECT_RECORD_NUMBER) {
DRM_ERROR
("record type %d\n",
record->
ucRecordType);
switch (record->
ucRecordType) {
case ATOM_I2C_RECORD_TYPE:
406,10 → 416,16
else
ddc_bus = radeon_lookup_gpio(dev, line_mux);
 
conn_id = le16_to_cpu(path->usConnObjectId);
 
if (!radeon_atom_apply_quirks
(dev, le16_to_cpu(path->usDeviceTag), &connector_type,
&ddc_bus, &conn_id))
continue;
 
radeon_add_atom_connector(dev,
conn_id,
le16_to_cpu(path->
usConnObjectId),
le16_to_cpu(path->
usDeviceTag),
connector_type, &ddc_bus,
linkb, igp_lane_info);
424,7 → 440,7
 
struct bios_connector {
bool valid;
uint8_t line_mux;
uint16_t line_mux;
uint16_t devices;
int connector_type;
struct radeon_i2c_bus_rec ddc_bus;
468,11 → 484,6
continue;
}
 
if (i == ATOM_DEVICE_TV1_INDEX) {
DRM_DEBUG("Skipping TV Out\n");
continue;
}
 
bios_connectors[i].connector_type =
supported_devices_connector_convert[ci.sucConnectorInfo.
sbfAccess.
526,7 → 537,7
 
if (!radeon_atom_apply_quirks
(dev, (1 << i), &bios_connectors[i].connector_type,
&bios_connectors[i].ddc_bus))
&bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux))
continue;
 
bios_connectors[i].valid = true;
708,9 → 719,8
return false;
}
 
struct radeon_encoder_int_tmds *radeon_atombios_get_tmds_info(struct
radeon_encoder
*encoder)
bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds)
{
struct drm_device *dev = encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
721,7 → 731,6
uint8_t frev, crev;
uint16_t maxfreq;
int i;
struct radeon_encoder_int_tmds *tmds = NULL;
 
atom_parse_data_header(mode_info->atom_context, index, NULL, &frev,
&crev, &data_offset);
731,12 → 740,6
data_offset);
 
if (tmds_info) {
tmds =
kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
 
if (!tmds)
return NULL;
 
maxfreq = le16_to_cpu(tmds_info->usMaxFrequency);
for (i = 0; i < 4; i++) {
tmds->tmds_pll[i].freq =
762,8 → 765,9
break;
}
}
return true;
}
return tmds;
return false;
}
 
union lvds_info {
855,6 → 859,72
return p_dac;
}
 
bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
SET_CRTC_TIMING_PARAMETERS_PS_ALLOCATION *crtc_timing,
int32_t *pixel_clock)
{
struct radeon_mode_info *mode_info = &rdev->mode_info;
ATOM_ANALOG_TV_INFO *tv_info;
ATOM_ANALOG_TV_INFO_V1_2 *tv_info_v1_2;
ATOM_DTD_FORMAT *dtd_timings;
int data_index = GetIndexIntoMasterTable(DATA, AnalogTV_Info);
u8 frev, crev;
uint16_t data_offset;
 
atom_parse_data_header(mode_info->atom_context, data_index, NULL, &frev, &crev, &data_offset);
 
switch (crev) {
case 1:
tv_info = (ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset);
if (index > MAX_SUPPORTED_TV_TIMING)
return false;
 
crtc_timing->usH_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
crtc_timing->usH_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
crtc_timing->usH_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
crtc_timing->usH_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncWidth);
 
crtc_timing->usV_Total = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Total);
crtc_timing->usV_Disp = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_Disp);
crtc_timing->usV_SyncStart = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncStart);
crtc_timing->usV_SyncWidth = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_V_SyncWidth);
 
crtc_timing->susModeMiscInfo = tv_info->aModeTimings[index].susModeMiscInfo;
 
crtc_timing->ucOverscanRight = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanRight);
crtc_timing->ucOverscanLeft = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanLeft);
crtc_timing->ucOverscanBottom = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanBottom);
crtc_timing->ucOverscanTop = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_OverscanTop);
*pixel_clock = le16_to_cpu(tv_info->aModeTimings[index].usPixelClock) * 10;
 
if (index == 1) {
/* PAL timings appear to have wrong values for totals */
crtc_timing->usH_Total -= 1;
crtc_timing->usV_Total -= 1;
}
break;
case 2:
tv_info_v1_2 = (ATOM_ANALOG_TV_INFO_V1_2 *)(mode_info->atom_context->bios + data_offset);
if (index > MAX_SUPPORTED_TV_TIMING_V1_2)
return false;
 
dtd_timings = &tv_info_v1_2->aModeTimings[index];
crtc_timing->usH_Total = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHBlanking_Time);
crtc_timing->usH_Disp = le16_to_cpu(dtd_timings->usHActive);
crtc_timing->usH_SyncStart = le16_to_cpu(dtd_timings->usHActive) + le16_to_cpu(dtd_timings->usHSyncOffset);
crtc_timing->usH_SyncWidth = le16_to_cpu(dtd_timings->usHSyncWidth);
crtc_timing->usV_Total = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVBlanking_Time);
crtc_timing->usV_Disp = le16_to_cpu(dtd_timings->usVActive);
crtc_timing->usV_SyncStart = le16_to_cpu(dtd_timings->usVActive) + le16_to_cpu(dtd_timings->usVSyncOffset);
crtc_timing->usV_SyncWidth = le16_to_cpu(dtd_timings->usVSyncWidth);
 
crtc_timing->susModeMiscInfo.usAccess = le16_to_cpu(dtd_timings->susModeMiscInfo.usAccess);
*pixel_clock = le16_to_cpu(dtd_timings->usPixClk) * 10;
break;
}
return true;
}
 
struct radeon_encoder_tv_dac *
radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder)
{
945,10 → 1015,10
uint32_t bios_2_scratch, bios_6_scratch;
 
if (rdev->family >= CHIP_R600) {
bios_2_scratch = RREG32(R600_BIOS_0_SCRATCH);
bios_2_scratch = RREG32(R600_BIOS_2_SCRATCH);
bios_6_scratch = RREG32(R600_BIOS_6_SCRATCH);
} else {
bios_2_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
bios_2_scratch = RREG32(RADEON_BIOS_2_SCRATCH);
bios_6_scratch = RREG32(RADEON_BIOS_6_SCRATCH);
}
 
968,6 → 1038,34
 
}
 
void radeon_save_bios_scratch_regs(struct radeon_device *rdev)
{
uint32_t scratch_reg;
int i;
 
if (rdev->family >= CHIP_R600)
scratch_reg = R600_BIOS_0_SCRATCH;
else
scratch_reg = RADEON_BIOS_0_SCRATCH;
 
for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++)
rdev->bios_scratch[i] = RREG32(scratch_reg + (i * 4));
}
 
void radeon_restore_bios_scratch_regs(struct radeon_device *rdev)
{
uint32_t scratch_reg;
int i;
 
if (rdev->family >= CHIP_R600)
scratch_reg = R600_BIOS_0_SCRATCH;
else
scratch_reg = RADEON_BIOS_0_SCRATCH;
 
for (i = 0; i < RADEON_BIOS_NUM_SCRATCH; i++)
WREG32(scratch_reg + (i * 4), rdev->bios_scratch[i]);
}
 
void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock)
{
struct drm_device *dev = encoder->dev;
/drivers/video/drm/radeon/radeon_bios.c
35,7 → 35,7
*/
static bool radeon_read_bios(struct radeon_device *rdev)
{
uint8_t *bios;
uint8_t __iomem *bios;
size_t size;
 
rdev->bios = NULL;
48,7 → 48,7
// pci_unmap_rom(rdev->pdev, bios);
return false;
}
rdev->bios = malloc(size);
rdev->bios = kmalloc(size, GFP_KERNEL);
if (rdev->bios == NULL) {
// pci_unmap_rom(rdev->pdev, bios);
return false;
58,7 → 58,6
return true;
}
 
 
static bool r700_read_disabled_bios(struct radeon_device *rdev)
{
uint32_t viph_control;
352,14 → 351,11
return legacy_read_disabled_bios(rdev);
}
 
 
bool radeon_get_bios(struct radeon_device *rdev)
{
bool r;
uint16_t tmp;
 
dbgprintf("%s\n\r",__FUNCTION__);
 
r = radeon_read_bios(rdev);
if (r == false) {
r = radeon_read_disabled_bios(rdev);
385,7 → 381,7
rdev->is_atom_bios = false;
}
 
dbgprintf("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM");
DRM_DEBUG("%sBIOS detected\n", rdev->is_atom_bios ? "ATOM" : "COM");
return true;
free_bios:
kfree(rdev->bios);
/drivers/video/drm/radeon/radeon_clocks.c
102,10 → 102,12
p1pll->reference_div = 12;
if (p2pll->reference_div < 2)
p2pll->reference_div = 12;
if (rdev->family < CHIP_RS600) {
if (spll->reference_div < 2)
spll->reference_div =
RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) &
RADEON_M_SPLL_REF_DIV_MASK;
}
if (mpll->reference_div < 2)
mpll->reference_div = spll->reference_div;
} else {
/drivers/video/drm/radeon/radeon_combios.c
685,23 → 685,15
0x00780000, /* rs480 */
};
 
static struct radeon_encoder_tv_dac
*radeon_legacy_get_tv_dac_info_from_table(struct radeon_device *rdev)
static void radeon_legacy_get_tv_dac_info_from_table(struct radeon_device *rdev,
struct radeon_encoder_tv_dac *tv_dac)
{
struct radeon_encoder_tv_dac *tv_dac = NULL;
 
tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);
 
if (!tv_dac)
return NULL;
 
tv_dac->ps2_tvdac_adj = default_tvdac_adj[rdev->family];
if ((rdev->flags & RADEON_IS_MOBILITY) && (rdev->family == CHIP_RV250))
tv_dac->ps2_tvdac_adj = 0x00880000;
tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj;
tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj;
 
return tv_dac;
return;
}
 
struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct
713,19 → 705,18
uint16_t dac_info;
uint8_t rev, bg, dac;
struct radeon_encoder_tv_dac *tv_dac = NULL;
int found = 0;
 
tv_dac = kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);
if (!tv_dac)
return NULL;
 
if (rdev->bios == NULL)
return radeon_legacy_get_tv_dac_info_from_table(rdev);
goto out;
 
/* first check TV table */
dac_info = combios_get_table_offset(dev, COMBIOS_TV_INFO_TABLE);
if (dac_info) {
tv_dac =
kzalloc(sizeof(struct radeon_encoder_tv_dac), GFP_KERNEL);
 
if (!tv_dac)
return NULL;
 
rev = RBIOS8(dac_info + 0x3);
if (rev > 4) {
bg = RBIOS8(dac_info + 0xc) & 0xf;
739,6 → 730,7
bg = RBIOS8(dac_info + 0x10) & 0xf;
dac = RBIOS8(dac_info + 0x11) & 0xf;
tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
found = 1;
} else if (rev > 1) {
bg = RBIOS8(dac_info + 0xc) & 0xf;
dac = (RBIOS8(dac_info + 0xc) >> 4) & 0xf;
751,22 → 743,16
bg = RBIOS8(dac_info + 0xe) & 0xf;
dac = (RBIOS8(dac_info + 0xe) >> 4) & 0xf;
tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20);
found = 1;
}
 
tv_dac->tv_std = radeon_combios_get_tv_info(encoder);
 
} else {
}
if (!found) {
/* then check CRT table */
dac_info =
combios_get_table_offset(dev, COMBIOS_CRT_INFO_TABLE);
if (dac_info) {
tv_dac =
kzalloc(sizeof(struct radeon_encoder_tv_dac),
GFP_KERNEL);
 
if (!tv_dac)
return NULL;
 
rev = RBIOS8(dac_info) & 0x3;
if (rev < 2) {
bg = RBIOS8(dac_info + 0x3) & 0xf;
775,6 → 761,7
(bg << 16) | (dac << 20);
tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj;
tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj;
found = 1;
} else {
bg = RBIOS8(dac_info + 0x4) & 0xf;
dac = RBIOS8(dac_info + 0x5) & 0xf;
782,12 → 769,15
(bg << 16) | (dac << 20);
tv_dac->pal_tvdac_adj = tv_dac->ps2_tvdac_adj;
tv_dac->ntsc_tvdac_adj = tv_dac->ps2_tvdac_adj;
found = 1;
}
} else {
DRM_INFO("No TV DAC info found in BIOS\n");
return radeon_legacy_get_tv_dac_info_from_table(rdev);
}
}
out:
if (!found) /* fallback to defaults */
radeon_legacy_get_tv_dac_info_from_table(rdev, tv_dac);
 
return tv_dac;
}
873,8 → 863,10
int tmp, i;
struct radeon_encoder_lvds *lvds = NULL;
 
if (rdev->bios == NULL)
return radeon_legacy_get_lvds_info_from_regs(rdev);
if (rdev->bios == NULL) {
lvds = radeon_legacy_get_lvds_info_from_regs(rdev);
goto out;
}
 
lcd_info = combios_get_table_offset(dev, COMBIOS_LCD_INFO_TABLE);
 
975,11 → 967,13
lvds->native_mode.flags = 0;
}
}
encoder->native_mode = lvds->native_mode;
} else {
DRM_INFO("No panel info found in BIOS\n");
return radeon_legacy_get_lvds_info_from_regs(rdev);
lvds = radeon_legacy_get_lvds_info_from_regs(rdev);
}
out:
if (lvds)
encoder->native_mode = lvds->native_mode;
return lvds;
}
 
1004,17 → 998,13
{{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /* CHIP_RS480 */
};
 
static struct radeon_encoder_int_tmds
*radeon_legacy_get_tmds_info_from_table(struct radeon_device *rdev)
bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds)
{
struct drm_device *dev = encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
int i;
struct radeon_encoder_int_tmds *tmds = NULL;
 
tmds = kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
 
if (!tmds)
return NULL;
 
for (i = 0; i < 4; i++) {
tmds->tmds_pll[i].value =
default_tmds_pll[rdev->family][i].value;
1021,12 → 1011,11
tmds->tmds_pll[i].freq = default_tmds_pll[rdev->family][i].freq;
}
 
return tmds;
return true;
}
 
struct radeon_encoder_int_tmds *radeon_combios_get_tmds_info(struct
radeon_encoder
*encoder)
bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds)
{
struct drm_device *dev = encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
1033,20 → 1022,14
uint16_t tmds_info;
int i, n;
uint8_t ver;
struct radeon_encoder_int_tmds *tmds = NULL;
 
if (rdev->bios == NULL)
return radeon_legacy_get_tmds_info_from_table(rdev);
return false;
 
tmds_info = combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE);
 
if (tmds_info) {
tmds =
kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
 
if (!tmds)
return NULL;
 
ver = RBIOS8(tmds_info);
DRM_INFO("DFP table revision: %d\n", ver);
if (ver == 3) {
1083,6 → 1066,23
}
} else
DRM_INFO("No TMDS info found in BIOS\n");
return true;
}
 
struct radeon_encoder_int_tmds *radeon_combios_get_tmds_info(struct radeon_encoder *encoder)
{
struct radeon_encoder_int_tmds *tmds = NULL;
bool ret;
 
tmds = kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
 
if (!tmds)
return NULL;
 
ret = radeon_legacy_get_tmds_info_from_combios(encoder, tmds);
if (ret == false)
radeon_legacy_get_tmds_info_from_table(encoder, tmds);
 
return tmds;
}
 
/drivers/video/drm/radeon/radeon_connectors.c
28,6 → 28,7
#include "drm_crtc_helper.h"
#include "radeon_drm.h"
#include "radeon.h"
#include "atom.h"
 
extern void
radeon_combios_connected_scratch_regs(struct drm_connector *connector,
38,6 → 39,15
struct drm_encoder *encoder,
bool connected);
 
static void radeon_property_change_mode(struct drm_encoder *encoder)
{
struct drm_crtc *crtc = encoder->crtc;
 
if (crtc && crtc->enabled) {
drm_crtc_helper_set_mode(crtc, &crtc->mode,
crtc->x, crtc->y, crtc->fb);
}
}
static void
radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_connector_status status)
{
77,6 → 87,27
}
}
 
struct drm_encoder *radeon_find_encoder(struct drm_connector *connector, int encoder_type)
{
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 (encoder->encoder_type == encoder_type)
return encoder;
}
return NULL;
}
 
struct drm_encoder *radeon_best_single_encoder(struct drm_connector *connector)
{
int enc_id = connector->encoder_ids[0];
83,8 → 114,6
struct drm_mode_object *obj;
struct drm_encoder *encoder;
 
ENTRY();
 
/* pick the encoder ids */
if (enc_id) {
obj = drm_mode_object_find(connector->dev, enc_id, DRM_MODE_OBJECT_ENCODER);
96,6 → 125,53
return NULL;
}
 
/*
* radeon_connector_analog_encoder_conflict_solve
* - search for other connectors sharing this encoder
* if priority is true, then set them disconnected if this is connected
* if priority is false, set us disconnected if they are connected
*/
static enum drm_connector_status
radeon_connector_analog_encoder_conflict_solve(struct drm_connector *connector,
struct drm_encoder *encoder,
enum drm_connector_status current_status,
bool priority)
{
struct drm_device *dev = connector->dev;
struct drm_connector *conflict;
int i;
 
list_for_each_entry(conflict, &dev->mode_config.connector_list, head) {
if (conflict == connector)
continue;
 
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
if (conflict->encoder_ids[i] == 0)
break;
 
/* if the IDs match */
if (conflict->encoder_ids[i] == encoder->base.id) {
if (conflict->status != connector_status_connected)
continue;
 
if (priority == true) {
DRM_INFO("1: conflicting encoders switching off %s\n", drm_get_connector_name(conflict));
DRM_INFO("in favor of %s\n", drm_get_connector_name(connector));
conflict->status = connector_status_disconnected;
radeon_connector_update_scratch_regs(conflict, connector_status_disconnected);
} else {
DRM_INFO("2: conflicting encoders switching off %s\n", drm_get_connector_name(connector));
DRM_INFO("in favor of %s\n", drm_get_connector_name(conflict));
current_status = connector_status_disconnected;
}
break;
}
}
}
return current_status;
 
}
 
static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
128,13 → 204,172
return mode;
}
 
static void radeon_add_common_modes(struct drm_encoder *encoder, struct drm_connector *connector)
{
struct drm_device *dev = encoder->dev;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct drm_display_mode *mode = NULL;
struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
int i;
struct mode_size {
int w;
int h;
} common_modes[17] = {
{ 640, 480},
{ 720, 480},
{ 800, 600},
{ 848, 480},
{1024, 768},
{1152, 768},
{1280, 720},
{1280, 800},
{1280, 854},
{1280, 960},
{1280, 1024},
{1440, 900},
{1400, 1050},
{1680, 1050},
{1600, 1200},
{1920, 1080},
{1920, 1200}
};
 
for (i = 0; i < 17; i++) {
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
if (common_modes[i].w > native_mode->panel_xres ||
common_modes[i].h > native_mode->panel_yres ||
(common_modes[i].w == native_mode->panel_xres &&
common_modes[i].h == native_mode->panel_yres))
continue;
}
if (common_modes[i].w < 320 || common_modes[i].h < 200)
continue;
 
mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h, 60, false, false);
drm_mode_probed_add(connector, mode);
}
}
 
int radeon_connector_set_property(struct drm_connector *connector, struct drm_property *property,
uint64_t val)
{
struct drm_device *dev = connector->dev;
struct radeon_device *rdev = dev->dev_private;
struct drm_encoder *encoder;
struct radeon_encoder *radeon_encoder;
 
if (property == rdev->mode_info.coherent_mode_property) {
struct radeon_encoder_atom_dig *dig;
 
/* need to find digital encoder on connector */
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
if (!encoder)
return 0;
 
radeon_encoder = to_radeon_encoder(encoder);
 
if (!radeon_encoder->enc_priv)
return 0;
 
dig = radeon_encoder->enc_priv;
dig->coherent_mode = val ? true : false;
radeon_property_change_mode(&radeon_encoder->base);
}
 
if (property == rdev->mode_info.tv_std_property) {
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TVDAC);
if (!encoder) {
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_DAC);
}
 
if (!encoder)
return 0;
 
radeon_encoder = to_radeon_encoder(encoder);
if (!radeon_encoder->enc_priv)
return 0;
if (rdev->is_atom_bios) {
struct radeon_encoder_atom_dac *dac_int;
dac_int = radeon_encoder->enc_priv;
dac_int->tv_std = val;
} else {
struct radeon_encoder_tv_dac *dac_int;
dac_int = radeon_encoder->enc_priv;
dac_int->tv_std = val;
}
radeon_property_change_mode(&radeon_encoder->base);
}
 
if (property == rdev->mode_info.load_detect_property) {
struct radeon_connector *radeon_connector =
to_radeon_connector(connector);
 
if (val == 0)
radeon_connector->dac_load_detect = false;
else
radeon_connector->dac_load_detect = true;
}
 
if (property == rdev->mode_info.tmds_pll_property) {
struct radeon_encoder_int_tmds *tmds = NULL;
bool ret = false;
/* need to find digital encoder on connector */
encoder = radeon_find_encoder(connector, DRM_MODE_ENCODER_TMDS);
if (!encoder)
return 0;
 
radeon_encoder = to_radeon_encoder(encoder);
 
tmds = radeon_encoder->enc_priv;
if (!tmds)
return 0;
 
if (val == 0) {
if (rdev->is_atom_bios)
ret = radeon_atombios_get_tmds_info(radeon_encoder, tmds);
else
ret = radeon_legacy_get_tmds_info_from_combios(radeon_encoder, tmds);
}
if (val == 1 || ret == false) {
radeon_legacy_get_tmds_info_from_table(radeon_encoder, tmds);
}
radeon_property_change_mode(&radeon_encoder->base);
}
 
return 0;
}
 
static void radeon_fixup_lvds_native_mode(struct drm_encoder *encoder,
struct drm_connector *connector)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
 
/* Try to get native mode details from EDID if necessary */
if (!native_mode->dotclock) {
struct drm_display_mode *t, *mode;
 
list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
if (mode->hdisplay == native_mode->panel_xres &&
mode->vdisplay == native_mode->panel_yres) {
native_mode->hblank = mode->htotal - mode->hdisplay;
native_mode->hoverplus = mode->hsync_start - mode->hdisplay;
native_mode->hsync_width = mode->hsync_end - mode->hsync_start;
native_mode->vblank = mode->vtotal - mode->vdisplay;
native_mode->voverplus = mode->vsync_start - mode->vdisplay;
native_mode->vsync_width = mode->vsync_end - mode->vsync_start;
native_mode->dotclock = mode->clock;
DRM_INFO("Determined LVDS native mode details from EDID\n");
break;
}
}
}
if (!native_mode->dotclock) {
DRM_INFO("No LVDS native mode details, disabling RMX\n");
radeon_encoder->rmx_type = RMX_OFF;
}
}
 
static int radeon_lvds_get_modes(struct drm_connector *connector)
{
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
145,6 → 380,12
if (radeon_connector->ddc_bus) {
ret = radeon_ddc_get_modes(radeon_connector);
if (ret > 0) {
encoder = radeon_best_single_encoder(connector);
if (encoder) {
radeon_fixup_lvds_native_mode(encoder, connector);
/* add scaled modes */
radeon_add_common_modes(encoder, connector);
}
return ret;
}
}
158,7 → 399,10
if (mode) {
ret = 1;
drm_mode_probed_add(connector, mode);
/* add scaled modes */
radeon_add_common_modes(encoder, connector);
}
 
return ret;
}
 
188,6 → 432,42
kfree(connector);
}
 
static int radeon_lvds_set_property(struct drm_connector *connector,
struct drm_property *property,
uint64_t value)
{
struct drm_device *dev = connector->dev;
struct radeon_encoder *radeon_encoder;
enum radeon_rmx_type rmx_type;
 
DRM_DEBUG("\n");
if (property != dev->mode_config.scaling_mode_property)
return 0;
 
if (connector->encoder)
radeon_encoder = to_radeon_encoder(connector->encoder);
else {
struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
radeon_encoder = to_radeon_encoder(connector_funcs->best_encoder(connector));
}
 
switch (value) {
case DRM_MODE_SCALE_NONE: rmx_type = RMX_OFF; break;
case DRM_MODE_SCALE_CENTER: rmx_type = RMX_CENTER; break;
case DRM_MODE_SCALE_ASPECT: rmx_type = RMX_ASPECT; break;
default:
case DRM_MODE_SCALE_FULLSCREEN: rmx_type = RMX_FULL; break;
}
if (radeon_encoder->rmx_type == rmx_type)
return 0;
 
radeon_encoder->rmx_type = rmx_type;
 
radeon_property_change_mode(&radeon_encoder->base);
return 0;
}
 
 
struct drm_connector_helper_funcs radeon_lvds_connector_helper_funcs = {
.get_modes = radeon_lvds_get_modes,
.mode_valid = radeon_lvds_mode_valid,
199,7 → 479,7
.detect = radeon_lvds_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = radeon_connector_destroy,
.set_property = radeon_connector_set_property,
.set_property = radeon_lvds_set_property,
};
 
static int radeon_vga_get_modes(struct drm_connector *connector)
215,7 → 495,6
static int radeon_vga_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
 
return MODE_OK;
}
 
227,6 → 506,10
bool dret;
enum drm_connector_status ret = connector_status_disconnected;
 
encoder = radeon_best_single_encoder(connector);
if (!encoder)
ret = connector_status_disconnected;
 
radeon_i2c_do_lock(radeon_connector, 1);
dret = radeon_ddc_probe(radeon_connector);
radeon_i2c_do_lock(radeon_connector, 0);
233,16 → 516,14
if (dret)
ret = connector_status_connected;
else {
/* if EDID fails to a load detect */
encoder = radeon_best_single_encoder(connector);
if (!encoder)
ret = connector_status_disconnected;
else {
if (radeon_connector->dac_load_detect) {
encoder_funcs = encoder->helper_private;
ret = encoder_funcs->detect(encoder, connector);
}
}
 
if (ret == connector_status_connected)
ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
radeon_connector_update_scratch_regs(connector, ret);
return ret;
}
261,6 → 542,73
.set_property = radeon_connector_set_property,
};
 
static int radeon_tv_get_modes(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct radeon_device *rdev = dev->dev_private;
struct drm_display_mode *tv_mode;
struct drm_encoder *encoder;
 
encoder = radeon_best_single_encoder(connector);
if (!encoder)
return 0;
 
/* avivo chips can scale any mode */
if (rdev->family >= CHIP_RS600)
/* add scaled modes */
radeon_add_common_modes(encoder, connector);
else {
/* only 800x600 is supported right now on pre-avivo chips */
tv_mode = drm_cvt_mode(dev, 800, 600, 60, false, false);
tv_mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(connector, tv_mode);
}
return 1;
}
 
static int radeon_tv_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
return MODE_OK;
}
 
static enum drm_connector_status radeon_tv_detect(struct drm_connector *connector)
{
struct drm_encoder *encoder;
struct drm_encoder_helper_funcs *encoder_funcs;
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
enum drm_connector_status ret = connector_status_disconnected;
 
if (!radeon_connector->dac_load_detect)
return ret;
 
encoder = radeon_best_single_encoder(connector);
if (!encoder)
ret = connector_status_disconnected;
else {
encoder_funcs = encoder->helper_private;
ret = encoder_funcs->detect(encoder, connector);
}
if (ret == connector_status_connected)
ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false);
radeon_connector_update_scratch_regs(connector, ret);
return ret;
}
 
struct drm_connector_helper_funcs radeon_tv_connector_helper_funcs = {
.get_modes = radeon_tv_get_modes,
.mode_valid = radeon_tv_mode_valid,
.best_encoder = radeon_best_single_encoder,
};
 
struct drm_connector_funcs radeon_tv_connector_funcs = {
.dpms = drm_helper_connector_dpms,
.detect = radeon_tv_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = radeon_connector_destroy,
.set_property = radeon_connector_set_property,
};
 
static int radeon_dvi_get_modes(struct drm_connector *connector)
{
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
267,15 → 615,24
int ret;
 
ret = radeon_ddc_get_modes(radeon_connector);
/* reset scratch regs here since radeon_dvi_detect doesn't check digital bit */
radeon_connector_update_scratch_regs(connector, connector_status_connected);
return ret;
}
 
/*
* DVI is complicated
* Do a DDC probe, if DDC probe passes, get the full EDID so
* we can do analog/digital monitor detection at this point.
* If the monitor is an analog monitor or we got no DDC,
* we need to find the DAC encoder object for this connector.
* If we got no DDC, we do load detection on the DAC encoder object.
* If we got analog DDC or load detection passes on the DAC encoder
* we have to check if this analog encoder is shared with anyone else (TV)
* if its shared we have to set the other connector to disconnected.
*/
static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector)
{
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
struct drm_encoder *encoder;
struct drm_encoder *encoder = NULL;
struct drm_encoder_helper_funcs *encoder_funcs;
struct drm_mode_object *obj;
int i;
285,9 → 642,29
radeon_i2c_do_lock(radeon_connector, 1);
dret = radeon_ddc_probe(radeon_connector);
radeon_i2c_do_lock(radeon_connector, 0);
if (dret)
if (dret) {
radeon_i2c_do_lock(radeon_connector, 1);
radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
radeon_i2c_do_lock(radeon_connector, 0);
 
if (!radeon_connector->edid) {
DRM_ERROR("DDC responded but not EDID found for %s\n",
drm_get_connector_name(connector));
} else {
radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
 
/* if this isn't a digital monitor
then we need to make sure we don't have any
TV conflicts */
ret = connector_status_connected;
else {
}
}
 
if ((ret == connector_status_connected) && (radeon_connector->use_digital == true))
goto out;
 
/* find analog encoder */
if (radeon_connector->dac_load_detect) {
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
if (connector->encoder_ids[i] == 0)
break;
302,15 → 679,23
 
encoder_funcs = encoder->helper_private;
if (encoder_funcs->detect) {
if (ret != connector_status_connected) {
ret = encoder_funcs->detect(encoder, connector);
if (ret == connector_status_connected) {
radeon_connector->use_digital = 0;
radeon_connector->use_digital = false;
}
}
break;
}
}
}
 
if ((ret == connector_status_connected) && (radeon_connector->use_digital == false) &&
encoder) {
ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
}
 
out:
/* updated in get modes as well since we need to know if it's analog or digital */
radeon_connector_update_scratch_regs(connector, ret);
return ret;
324,9 → 709,6
struct drm_mode_object *obj;
struct drm_encoder *encoder;
int i;
 
ENTRY();
 
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
if (connector->encoder_ids[i] == 0)
break;
337,7 → 719,7
 
encoder = obj_to_encoder(obj);
 
if (radeon_connector->use_digital) {
if (radeon_connector->use_digital == true) {
if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
return encoder;
} else {
384,6 → 766,7
bool linkb,
uint32_t igp_lane_info)
{
struct radeon_device *rdev = dev->dev_private;
struct drm_connector *connector;
struct radeon_connector *radeon_connector;
struct radeon_connector_atom_dig *radeon_dig_connector;
390,10 → 773,7
uint32_t subpixel_order = SubPixelNone;
 
/* fixme - tv/cv/din */
if ((connector_type == DRM_MODE_CONNECTOR_Unknown) ||
(connector_type == DRM_MODE_CONNECTOR_SVIDEO) ||
(connector_type == DRM_MODE_CONNECTOR_Composite) ||
(connector_type == DRM_MODE_CONNECTOR_9PinDIN))
if (connector_type == DRM_MODE_CONNECTOR_Unknown)
return;
 
/* see if we already added it */
422,6 → 802,9
if (!radeon_connector->ddc_bus)
goto failed;
}
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
break;
case DRM_MODE_CONNECTOR_DVIA:
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
431,6 → 814,9
if (!radeon_connector->ddc_bus)
goto failed;
}
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
break;
case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_DVID:
448,6 → 834,12
goto failed;
}
subpixel_order = SubPixelHorizontalRGB;
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.coherent_mode_property,
1);
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
break;
case DRM_MODE_CONNECTOR_HDMIA:
case DRM_MODE_CONNECTOR_HDMIB:
464,6 → 856,9
if (!radeon_connector->ddc_bus)
goto failed;
}
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.coherent_mode_property,
1);
subpixel_order = SubPixelHorizontalRGB;
break;
case DRM_MODE_CONNECTOR_DisplayPort:
485,6 → 880,13
case DRM_MODE_CONNECTOR_SVIDEO:
case DRM_MODE_CONNECTOR_Composite:
case DRM_MODE_CONNECTOR_9PinDIN:
if (radeon_tv == 1) {
drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
}
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
break;
case DRM_MODE_CONNECTOR_LVDS:
radeon_dig_connector = kzalloc(sizeof(struct radeon_connector_atom_dig), GFP_KERNEL);
500,6 → 902,10
if (!radeon_connector->ddc_bus)
goto failed;
}
drm_mode_create_scaling_mode_property(dev);
drm_connector_attach_property(&radeon_connector->base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_FULLSCREEN);
subpixel_order = SubPixelHorizontalRGB;
break;
}
522,15 → 928,13
int connector_type,
struct radeon_i2c_bus_rec *i2c_bus)
{
struct radeon_device *rdev = dev->dev_private;
struct drm_connector *connector;
struct radeon_connector *radeon_connector;
uint32_t subpixel_order = SubPixelNone;
 
/* fixme - tv/cv/din */
if ((connector_type == DRM_MODE_CONNECTOR_Unknown) ||
(connector_type == DRM_MODE_CONNECTOR_SVIDEO) ||
(connector_type == DRM_MODE_CONNECTOR_Composite) ||
(connector_type == DRM_MODE_CONNECTOR_9PinDIN))
if (connector_type == DRM_MODE_CONNECTOR_Unknown)
return;
 
/* see if we already added it */
559,6 → 963,9
if (!radeon_connector->ddc_bus)
goto failed;
}
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
break;
case DRM_MODE_CONNECTOR_DVIA:
drm_connector_init(dev, &radeon_connector->base, &radeon_vga_connector_funcs, connector_type);
568,6 → 975,9
if (!radeon_connector->ddc_bus)
goto failed;
}
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
break;
case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_DVID:
577,6 → 987,9
radeon_connector->ddc_bus = radeon_i2c_create(dev, i2c_bus, "DVI");
if (!radeon_connector->ddc_bus)
goto failed;
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
}
subpixel_order = SubPixelHorizontalRGB;
break;
583,6 → 996,13
case DRM_MODE_CONNECTOR_SVIDEO:
case DRM_MODE_CONNECTOR_Composite:
case DRM_MODE_CONNECTOR_9PinDIN:
if (radeon_tv == 1) {
drm_connector_init(dev, &radeon_connector->base, &radeon_tv_connector_funcs, connector_type);
drm_connector_helper_add(&radeon_connector->base, &radeon_tv_connector_helper_funcs);
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
}
break;
case DRM_MODE_CONNECTOR_LVDS:
drm_connector_init(dev, &radeon_connector->base, &radeon_lvds_connector_funcs, connector_type);
592,6 → 1012,9
if (!radeon_connector->ddc_bus)
goto failed;
}
drm_connector_attach_property(&radeon_connector->base,
dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_FULLSCREEN);
subpixel_order = SubPixelHorizontalRGB;
break;
}
/drivers/video/drm/radeon/radeon_cursor.c
0,0 → 1,260
/*
* 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.h"
 
#define CURSOR_WIDTH 64
#define CURSOR_HEIGHT 64
 
static void radeon_lock_cursor(struct drm_crtc *crtc, bool lock)
{
struct radeon_device *rdev = crtc->dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
uint32_t cur_lock;
 
if (ASIC_IS_AVIVO(rdev)) {
cur_lock = RREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset);
if (lock)
cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK;
else
cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK;
WREG32(AVIVO_D1CUR_UPDATE + radeon_crtc->crtc_offset, cur_lock);
} else {
cur_lock = RREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset);
if (lock)
cur_lock |= RADEON_CUR_LOCK;
else
cur_lock &= ~RADEON_CUR_LOCK;
WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, cur_lock);
}
}
 
static void radeon_hide_cursor(struct drm_crtc *crtc)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct radeon_device *rdev = crtc->dev->dev_private;
 
if (ASIC_IS_AVIVO(rdev)) {
WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
WREG32(RADEON_MM_DATA, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
} else {
switch (radeon_crtc->crtc_id) {
case 0:
WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
break;
case 1:
WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
break;
default:
return;
}
WREG32_P(RADEON_MM_DATA, 0, ~RADEON_CRTC_CUR_EN);
}
}
 
static void radeon_show_cursor(struct drm_crtc *crtc)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct radeon_device *rdev = crtc->dev->dev_private;
 
if (ASIC_IS_AVIVO(rdev)) {
WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN |
(AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
} else {
switch (radeon_crtc->crtc_id) {
case 0:
WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
break;
case 1:
WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
break;
default:
return;
}
 
WREG32_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN |
(RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)),
~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK));
}
}
 
static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj,
uint32_t gpu_addr)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct radeon_device *rdev = crtc->dev->dev_private;
 
if (ASIC_IS_AVIVO(rdev))
WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr);
else {
radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr;
/* offset is from DISP(2)_BASE_ADDRESS */
WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset);
}
}
 
#if 0
 
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_gem_object *obj;
uint64_t gpu_addr;
int ret;
 
if (!handle) {
/* turn off cursor */
radeon_hide_cursor(crtc);
obj = NULL;
goto unpin;
}
 
if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) {
DRM_ERROR("bad cursor width or height %d x %d\n", width, height);
return -EINVAL;
}
 
radeon_crtc->cursor_width = width;
radeon_crtc->cursor_height = height;
 
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;
}
 
ret = radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
if (ret)
goto fail;
 
radeon_lock_cursor(crtc, true);
/* XXX only 27 bit offset for legacy cursor */
radeon_set_cursor(crtc, obj, gpu_addr);
radeon_show_cursor(crtc);
radeon_lock_cursor(crtc, false);
 
unpin:
if (radeon_crtc->cursor_bo) {
radeon_gem_object_unpin(radeon_crtc->cursor_bo);
mutex_lock(&crtc->dev->struct_mutex);
drm_gem_object_unreference(radeon_crtc->cursor_bo);
mutex_unlock(&crtc->dev->struct_mutex);
}
 
radeon_crtc->cursor_bo = obj;
return 0;
fail:
mutex_lock(&crtc->dev->struct_mutex);
drm_gem_object_unreference(obj);
mutex_unlock(&crtc->dev->struct_mutex);
 
return 0;
}
#endif
 
int radeon_crtc_cursor_move(struct drm_crtc *crtc,
int x, int y)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct radeon_device *rdev = crtc->dev->dev_private;
int xorigin = 0, yorigin = 0;
 
if (x < 0)
xorigin = -x + 1;
if (y < 0)
yorigin = -y + 1;
if (xorigin >= CURSOR_WIDTH)
xorigin = CURSOR_WIDTH - 1;
if (yorigin >= CURSOR_HEIGHT)
yorigin = CURSOR_HEIGHT - 1;
 
radeon_lock_cursor(crtc, true);
if (ASIC_IS_AVIVO(rdev)) {
int w = radeon_crtc->cursor_width;
int i = 0;
struct drm_crtc *crtc_p;
 
/* avivo cursor are offset into the total surface */
x += crtc->x;
y += crtc->y;
DRM_DEBUG("x %d y %d c->x %d c->y %d\n", x, y, crtc->x, crtc->y);
 
/* avivo cursor image can't end on 128 pixel boundry or
* go past the end of the frame if both crtcs are enabled
*/
list_for_each_entry(crtc_p, &crtc->dev->mode_config.crtc_list, head) {
if (crtc_p->enabled)
i++;
}
if (i > 1) {
int cursor_end, frame_end;
 
cursor_end = x - xorigin + w;
frame_end = crtc->x + crtc->mode.crtc_hdisplay;
if (cursor_end >= frame_end) {
w = w - (cursor_end - frame_end);
if (!(frame_end & 0x7f))
w--;
} else {
if (!(cursor_end & 0x7f))
w--;
}
if (w <= 0)
w = 1;
}
 
WREG32(AVIVO_D1CUR_POSITION + radeon_crtc->crtc_offset,
((xorigin ? 0 : x) << 16) |
(yorigin ? 0 : y));
WREG32(AVIVO_D1CUR_HOT_SPOT + radeon_crtc->crtc_offset, (xorigin << 16) | yorigin);
WREG32(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset,
((w - 1) << 16) | (radeon_crtc->cursor_height - 1));
} else {
if (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)
y *= 2;
 
WREG32(RADEON_CUR_HORZ_VERT_OFF + radeon_crtc->crtc_offset,
(RADEON_CUR_LOCK
| (xorigin << 16)
| yorigin));
WREG32(RADEON_CUR_HORZ_VERT_POSN + radeon_crtc->crtc_offset,
(RADEON_CUR_LOCK
| ((xorigin ? 0 : x) << 16)
| (yorigin ? 0 : y)));
/* offset is from DISP(2)_BASE_ADDRESS */
WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset +
(yorigin * 256)));
}
radeon_lock_cursor(crtc, false);
 
return 0;
}
/drivers/video/drm/radeon/radeon_device.c
27,8 → 27,8
*/
//#include <linux/console.h>
 
#include <drmP.h>
#include <drm_crtc_helper.h>
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include "radeon_drm.h"
#include "radeon_reg.h"
#include "radeon.h"
43,14 → 43,15
int radeon_gart_size = 512; /* default gart size */
int radeon_benchmarking = 0;
int radeon_connector_table = 0;
int radeon_tv = 1;
 
 
/*
* Clear GPU surface registers.
*/
static void radeon_surface_init(struct radeon_device *rdev)
void radeon_surface_init(struct radeon_device *rdev)
{
dbgprintf("%s\n",__FUNCTION__);
ENTER();
 
/* FIXME: check this out */
if (rdev->family < CHIP_R600) {
61,6 → 62,8
i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO),
0);
}
/* enable surfaces */
WREG32(RADEON_SURFACE_CNTL, 0);
}
}
 
67,7 → 70,7
/*
* GPU scratch registers helpers function.
*/
static void radeon_scratch_init(struct radeon_device *rdev)
void radeon_scratch_init(struct radeon_device *rdev)
{
int i;
 
132,7 → 135,7
if (rdev->mc.vram_location != 0xFFFFFFFFUL) {
/* vram location was already setup try to put gtt after
* if it fits */
tmp = rdev->mc.vram_location + rdev->mc.vram_size;
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size;
tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1);
if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) {
rdev->mc.gtt_location = tmp;
147,13 → 150,13
} else if (rdev->mc.gtt_location != 0xFFFFFFFFUL) {
/* gtt location was already setup try to put vram before
* if it fits */
if (rdev->mc.vram_size < rdev->mc.gtt_location) {
if (rdev->mc.mc_vram_size < rdev->mc.gtt_location) {
rdev->mc.vram_location = 0;
} else {
tmp = rdev->mc.gtt_location + rdev->mc.gtt_size;
tmp += (rdev->mc.vram_size - 1);
tmp &= ~(rdev->mc.vram_size - 1);
if ((0xFFFFFFFFUL - tmp) >= rdev->mc.vram_size) {
tmp += (rdev->mc.mc_vram_size - 1);
tmp &= ~(rdev->mc.mc_vram_size - 1);
if ((0xFFFFFFFFUL - tmp) >= rdev->mc.mc_vram_size) {
rdev->mc.vram_location = tmp;
} else {
printk(KERN_ERR "[drm] vram too big to fit "
163,16 → 166,22
}
} else {
rdev->mc.vram_location = 0;
rdev->mc.gtt_location = rdev->mc.vram_size;
tmp = rdev->mc.mc_vram_size;
tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1);
rdev->mc.gtt_location = tmp;
}
DRM_INFO("radeon: VRAM %uM\n", rdev->mc.vram_size >> 20);
rdev->mc.vram_start = rdev->mc.vram_location;
rdev->mc.vram_end = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
rdev->mc.gtt_start = rdev->mc.gtt_location;
rdev->mc.gtt_end = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
DRM_INFO("radeon: VRAM %uM\n", (unsigned)(rdev->mc.mc_vram_size >> 20));
DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n",
rdev->mc.vram_location,
rdev->mc.vram_location + rdev->mc.vram_size - 1);
DRM_INFO("radeon: GTT %uM\n", rdev->mc.gtt_size >> 20);
(unsigned)rdev->mc.vram_location,
(unsigned)(rdev->mc.vram_location + rdev->mc.mc_vram_size - 1));
DRM_INFO("radeon: GTT %uM\n", (unsigned)(rdev->mc.gtt_size >> 20));
DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n",
rdev->mc.gtt_location,
rdev->mc.gtt_location + rdev->mc.gtt_size - 1);
(unsigned)rdev->mc.gtt_location,
(unsigned)(rdev->mc.gtt_location + rdev->mc.gtt_size - 1));
return 0;
}
 
180,11 → 189,11
/*
* GPU helpers function.
*/
static bool radeon_card_posted(struct radeon_device *rdev)
bool radeon_card_posted(struct radeon_device *rdev)
{
uint32_t reg;
 
dbgprintf("%s\n",__FUNCTION__);
ENTER();
 
/* first check CRTCs */
if (ASIC_IS_AVIVO(rdev)) {
234,34 → 243,28
 
void radeon_register_accessor_init(struct radeon_device *rdev)
{
 
dbgprintf("%s\n",__FUNCTION__);
 
rdev->mm_rreg = &r100_mm_rreg;
rdev->mm_wreg = &r100_mm_wreg;
rdev->mc_rreg = &radeon_invalid_rreg;
rdev->mc_wreg = &radeon_invalid_wreg;
rdev->pll_rreg = &radeon_invalid_rreg;
rdev->pll_wreg = &radeon_invalid_wreg;
rdev->pcie_rreg = &radeon_invalid_rreg;
rdev->pcie_wreg = &radeon_invalid_wreg;
rdev->pciep_rreg = &radeon_invalid_rreg;
rdev->pciep_wreg = &radeon_invalid_wreg;
 
/* Don't change order as we are overridding accessor. */
if (rdev->family < CHIP_RV515) {
rdev->pcie_rreg = &rv370_pcie_rreg;
rdev->pcie_wreg = &rv370_pcie_wreg;
rdev->pcie_reg_mask = 0xff;
} else {
rdev->pcie_reg_mask = 0x7ff;
}
if (rdev->family >= CHIP_RV515) {
rdev->pcie_rreg = &rv515_pcie_rreg;
rdev->pcie_wreg = &rv515_pcie_wreg;
}
/* FIXME: not sure here */
if (rdev->family <= CHIP_R580) {
rdev->pll_rreg = &r100_pll_rreg;
rdev->pll_wreg = &r100_pll_wreg;
}
if (rdev->family >= CHIP_R420) {
rdev->mc_rreg = &r420_mc_rreg;
rdev->mc_wreg = &r420_mc_wreg;
}
if (rdev->family >= CHIP_RV515) {
rdev->mc_rreg = &rv515_mc_rreg;
rdev->mc_wreg = &rv515_mc_wreg;
270,19 → 273,19
rdev->mc_rreg = &rs400_mc_rreg;
rdev->mc_wreg = &rs400_mc_wreg;
}
if (rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
rdev->mc_rreg = &rs690_mc_rreg;
rdev->mc_wreg = &rs690_mc_wreg;
// if (rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) {
// rdev->mc_rreg = &rs690_mc_rreg;
// rdev->mc_wreg = &rs690_mc_wreg;
// }
// if (rdev->family == CHIP_RS600) {
// rdev->mc_rreg = &rs600_mc_rreg;
// rdev->mc_wreg = &rs600_mc_wreg;
// }
// if (rdev->family >= CHIP_R600) {
// rdev->pciep_rreg = &r600_pciep_rreg;
// rdev->pciep_wreg = &r600_pciep_wreg;
// }
}
if (rdev->family == CHIP_RS600) {
rdev->mc_rreg = &rs600_mc_rreg;
rdev->mc_wreg = &rs600_mc_wreg;
}
if (rdev->family >= CHIP_R600) {
rdev->pciep_rreg = &r600_pciep_rreg;
rdev->pciep_wreg = &r600_pciep_wreg;
}
}
 
 
/*
290,9 → 293,6
*/
int radeon_asic_init(struct radeon_device *rdev)
{
 
dbgprintf("%s\n",__FUNCTION__);
 
radeon_register_accessor_init(rdev);
switch (rdev->family) {
case CHIP_R100:
311,6 → 311,14
case CHIP_RV350:
case CHIP_RV380:
rdev->asic = &r300_asic;
if (rdev->flags & RADEON_IS_PCIE) {
rdev->asic->gart_init = &rv370_pcie_gart_init;
rdev->asic->gart_fini = &rv370_pcie_gart_fini;
rdev->asic->gart_enable = &rv370_pcie_gart_enable;
rdev->asic->gart_disable = &rv370_pcie_gart_disable;
rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
}
break;
case CHIP_R420:
case CHIP_R423:
322,11 → 330,11
rdev->asic = &rs400_asic;
break;
case CHIP_RS600:
rdev->asic = &rs600_asic;
// rdev->asic = &rs600_asic;
break;
case CHIP_RS690:
case CHIP_RS740:
rdev->asic = &rs690_asic;
// rdev->asic = &rs690_asic;
break;
case CHIP_RV515:
rdev->asic = &rv515_asic;
363,9 → 371,8
{
int r;
 
dbgprintf("%s\n",__FUNCTION__);
ENTER();
 
radeon_get_clock_info(rdev->ddev);
r = radeon_static_clocks_init(rdev->ddev);
if (r) {
return r;
439,7 → 446,7
 
int radeon_atombios_init(struct radeon_device *rdev)
{
dbgprintf("%s\n",__FUNCTION__);
ENTER();
 
atom_card_info.dev = rdev->ddev;
rdev->mode_info.atom_context = atom_parse(&atom_card_info, rdev->bios);
465,6 → 472,7
int radeon_modeset_init(struct radeon_device *rdev);
void radeon_modeset_fini(struct radeon_device *rdev);
 
 
/*
* Radeon device.
*/
474,8 → 482,9
uint32_t flags)
{
int r, ret;
int dma_bits;
 
dbgprintf("%s\n",__FUNCTION__);
ENTER();
 
DRM_INFO("radeon: Initializing kernel modesetting.\n");
rdev->shutdown = false;
494,35 → 503,53
// mutex_init(&rdev->cp.mutex);
// rwlock_init(&rdev->fence_drv.lock);
 
/* Set asic functions */
r = radeon_asic_init(rdev);
if (r) {
return r;
}
 
if (radeon_agpmode == -1) {
rdev->flags &= ~RADEON_IS_AGP;
if (rdev->family > CHIP_RV515 ||
if (rdev->family >= CHIP_RV515 ||
rdev->family == CHIP_RV380 ||
rdev->family == CHIP_RV410 ||
rdev->family == CHIP_R423) {
DRM_INFO("Forcing AGP to PCIE mode\n");
rdev->flags |= RADEON_IS_PCIE;
rdev->asic->gart_init = &rv370_pcie_gart_init;
rdev->asic->gart_fini = &rv370_pcie_gart_fini;
rdev->asic->gart_enable = &rv370_pcie_gart_enable;
rdev->asic->gart_disable = &rv370_pcie_gart_disable;
rdev->asic->gart_tlb_flush = &rv370_pcie_gart_tlb_flush;
rdev->asic->gart_set_page = &rv370_pcie_gart_set_page;
} else {
DRM_INFO("Forcing AGP to PCI mode\n");
rdev->flags |= RADEON_IS_PCI;
rdev->asic->gart_init = &r100_pci_gart_init;
rdev->asic->gart_fini = &r100_pci_gart_fini;
rdev->asic->gart_enable = &r100_pci_gart_enable;
rdev->asic->gart_disable = &r100_pci_gart_disable;
rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush;
rdev->asic->gart_set_page = &r100_pci_gart_set_page;
}
}
 
/* Set asic functions */
r = radeon_asic_init(rdev);
if (r) {
return r;
}
/* set DMA mask + need_dma32 flags.
* PCIE - can handle 40-bits.
* IGP - can handle 40-bits (in theory)
* AGP - generally dma32 is safest
* PCI - only dma32
*/
rdev->need_dma32 = false;
if (rdev->flags & RADEON_IS_AGP)
rdev->need_dma32 = true;
if (rdev->flags & RADEON_IS_PCI)
rdev->need_dma32 = true;
 
r = rdev->asic->init(rdev);
 
dma_bits = rdev->need_dma32 ? 32 : 40;
r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits));
if (r) {
return r;
}
 
/* Report DMA addressing limitation */
r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(32));
if (r) {
printk(KERN_WARNING "radeon: No suitable DMA available.\n");
}
 
541,6 → 568,13
DRM_INFO("register mmio base: 0x%08X\n", (uint32_t)rdev->rmmio_base);
DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size);
 
rdev->new_init_path = false;
r = radeon_init(rdev);
if (r) {
return r;
}
 
if (!rdev->new_init_path) {
/* Setup errata flags */
radeon_errata(rdev);
/* Initialize scratch registers */
548,7 → 582,6
/* Initialize surface registers */
radeon_surface_init(rdev);
 
/* TODO: disable VGA need to use VGA request */
/* BIOS*/
if (!radeon_get_bios(rdev)) {
if (ASIC_IS_AVIVO(rdev))
578,23 → 611,9
radeon_combios_asic_init(rdev->ddev);
}
}
/* Get vram informations */
/* Get clock & vram information */
radeon_get_clock_info(rdev->ddev);
radeon_vram_info(rdev);
/* Device is severly broken if aper size > vram size.
* for RN50/M6/M7 - Novell bug 204882 ?
*/
if (rdev->mc.vram_size < rdev->mc.aper_size) {
rdev->mc.aper_size = rdev->mc.vram_size;
}
/* Add an MTRR for the VRAM */
// rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size,
// MTRR_TYPE_WRCOMB, 1);
DRM_INFO("Detected VRAM RAM=%uM, BAR=%uM\n",
rdev->mc.vram_size >> 20,
(unsigned)rdev->mc.aper_size >> 20);
DRM_INFO("RAM width %dbits %cDR\n",
rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S');
 
/* Initialize clocks */
r = radeon_clocks_init(rdev);
if (r) {
606,74 → 625,51
if (r) {
return r;
}
/* Fence driver */
// r = radeon_fence_driver_init(rdev);
// if (r) {
// return r;
// }
// r = radeon_irq_kms_init(rdev);
// if (r) {
// return r;
// }
/* Memory manager */
r = radeon_object_init(rdev);
if (r) {
return r;
}
r = radeon_gpu_gart_init(rdev);
if (r)
return r;
/* Initialize GART (initialize after TTM so we can allocate
* memory through TTM but finalize after TTM) */
r = radeon_gart_enable(rdev);
if (!r) {
if (r)
return 0;
r = radeon_gem_init(rdev);
}
if (r)
return 0;
 
/* 1M ring buffer */
if (!r) {
r = radeon_cp_init(rdev, 1024 * 1024);
}
// if (!r) {
// r = radeon_wb_init(rdev);
// if (r) {
// DRM_ERROR("radeon: failled initializing WB (%d).\n", r);
// return r;
// }
// }
 
// r = radeon_cp_init(rdev, 1024 * 1024);
// if (r)
// return 0;
#if 0
if (!r) {
r = radeon_wb_init(rdev);
if (r)
DRM_ERROR("radeon: failled initializing WB (%d).\n", r);
r = radeon_ib_pool_init(rdev);
if (r) {
DRM_ERROR("radeon: failled initializing IB pool (%d).\n", r);
return r;
}
}
if (!r) {
if (r)
return 0;
r = radeon_ib_test(rdev);
if (r) {
DRM_ERROR("radeon: failled testing IB (%d).\n", r);
return r;
}
}
if (r)
return 0;
#endif
 
ret = r;
rdev->accel_working = true;
r = radeon_modeset_init(rdev);
if (r) {
return r;
}
// if (rdev->fbdev_rfb && rdev->fbdev_rfb->obj) {
// rdev->fbdev_robj = rdev->fbdev_rfb->obj->driver_private;
DRM_INFO("radeon: kernel modesetting successfully initialized.\n");
// if (radeon_testing) {
// radeon_test_moves(rdev);
// }
if (!ret) {
DRM_INFO("radeon: kernel modesetting successfully initialized.\n");
}
if (radeon_benchmarking) {
// if (radeon_benchmarking) {
// radeon_benchmark(rdev);
// }
return 0;
}
return ret;
 
// return -1;
}
 
static struct pci_device_id pciidlist[] = {
radeon_PCI_IDS
680,7 → 676,7
};
 
 
u32_t __stdcall drvEntry(int action)
u32_t drvEntry(int action, char *cmdline)
{
struct pci_device_id *ent;
 
697,6 → 693,9
return 0;
}
 
if(cmdline)
dbgprintf("cmdline: %s\n", cmdline);
 
enum_pci_devices();
 
ent = find_pci_device(&device, pciidlist);
932,3 → 931,6
 
 
 
 
 
 
/drivers/video/drm/radeon/radeon_display.c
158,9 → 158,6
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 
if (radeon_crtc->mode_set.mode) {
drm_mode_destroy(crtc->dev, radeon_crtc->mode_set.mode);
}
drm_crtc_cleanup(crtc);
kfree(radeon_crtc);
}
167,7 → 164,7
 
static const struct drm_crtc_funcs radeon_crtc_funcs = {
// .cursor_set = radeon_crtc_cursor_set,
// .cursor_move = radeon_crtc_cursor_move,
.cursor_move = radeon_crtc_cursor_move,
.gamma_set = radeon_crtc_gamma_set,
.set_config = drm_crtc_helper_set_config,
.destroy = radeon_crtc_destroy,
179,8 → 176,6
struct radeon_crtc *radeon_crtc;
int i;
 
ENTRY();
 
radeon_crtc = kzalloc(sizeof(struct radeon_crtc) + (RADEONFB_CONN_LIMIT * sizeof(struct drm_connector *)), GFP_KERNEL);
if (radeon_crtc == NULL)
return;
189,10 → 184,13
 
drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256);
radeon_crtc->crtc_id = index;
rdev->mode_info.crtcs[index] = radeon_crtc;
 
#if 0
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;
#endif
 
for (i = 0; i < 256; i++) {
radeon_crtc->lut_r[i] = i << 2;
204,8 → 202,6
radeon_atombios_init_crtc(dev, radeon_crtc);
else
radeon_legacy_init_crtc(dev, radeon_crtc);
 
LEAVE();
}
 
static const char *encoder_names[34] = {
316,14 → 312,12
}
}
 
bool radeon_setup_enc_conn(struct drm_device *dev)
static bool radeon_setup_enc_conn(struct drm_device *dev)
{
struct radeon_device *rdev = dev->dev_private;
struct drm_connector *drm_connector;
bool ret = false;
 
ENTRY();
 
if (rdev->bios) {
if (rdev->is_atom_bios) {
if (rdev->family >= CHIP_R600)
341,7 → 335,6
list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
radeon_ddc_dump(drm_connector);
}
LEAVE();
 
return ret;
}
353,9 → 346,13
 
if (!radeon_connector->ddc_bus)
return -1;
if (!radeon_connector->edid) {
radeon_i2c_do_lock(radeon_connector, 1);
edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
radeon_i2c_do_lock(radeon_connector, 0);
} else
edid = radeon_connector->edid;
 
if (edid) {
/* update digital bits here */
if (edid->input & DRM_EDID_INPUT_DIGITAL)
368,7 → 365,7
return ret;
}
drm_mode_connector_update_edid_property(&radeon_connector->base, NULL);
return -1;
return 0;
}
 
static int radeon_ddc_dump(struct drm_connector *connector)
498,6 → 495,10
tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div;
current_freq = radeon_div(tmp, ref_div * post_div);
 
if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) {
error = freq - current_freq;
error = error < 0 ? 0xffffffff : error;
} else
error = abs(current_freq - freq);
vco_diff = abs(vco - best_vco);
 
556,7 → 557,6
*post_div_p = best_post_div;
}
 
 
static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb)
{
struct radeon_framebuffer *radeon_fb = to_radeon_framebuffer(fb);
590,7 → 590,6
.create_handle = radeon_user_framebuffer_create_handle,
};
 
 
struct drm_framebuffer *
radeon_framebuffer_create(struct drm_device *dev,
struct drm_mode_fb_cmd *mode_cmd,
622,17 → 621,90
// return radeon_framebuffer_create(dev, mode_cmd, obj);
}
 
 
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 radeon_device *rdev)
struct drm_prop_enum_list {
int type;
char *name;
};
 
static struct drm_prop_enum_list radeon_tmds_pll_enum_list[] =
{ { 0, "driver" },
{ 1, "bios" },
};
 
static struct drm_prop_enum_list radeon_tv_std_enum_list[] =
{ { TV_STD_NTSC, "ntsc" },
{ TV_STD_PAL, "pal" },
{ TV_STD_PAL_M, "pal-m" },
{ TV_STD_PAL_60, "pal-60" },
{ TV_STD_NTSC_J, "ntsc-j" },
{ TV_STD_SCART_PAL, "scart-pal" },
{ TV_STD_PAL_CN, "pal-cn" },
{ TV_STD_SECAM, "secam" },
};
 
int radeon_modeset_create_props(struct radeon_device *rdev)
{
int i, sz;
 
dbgprintf("%s\n",__FUNCTION__);
if (rdev->is_atom_bios) {
rdev->mode_info.coherent_mode_property =
drm_property_create(rdev->ddev,
DRM_MODE_PROP_RANGE,
"coherent", 2);
if (!rdev->mode_info.coherent_mode_property)
return -ENOMEM;
 
rdev->mode_info.coherent_mode_property->values[0] = 0;
rdev->mode_info.coherent_mode_property->values[0] = 1;
}
 
if (!ASIC_IS_AVIVO(rdev)) {
sz = ARRAY_SIZE(radeon_tmds_pll_enum_list);
rdev->mode_info.tmds_pll_property =
drm_property_create(rdev->ddev,
DRM_MODE_PROP_ENUM,
"tmds_pll", sz);
for (i = 0; i < sz; i++) {
drm_property_add_enum(rdev->mode_info.tmds_pll_property,
i,
radeon_tmds_pll_enum_list[i].type,
radeon_tmds_pll_enum_list[i].name);
}
}
 
rdev->mode_info.load_detect_property =
drm_property_create(rdev->ddev,
DRM_MODE_PROP_RANGE,
"load detection", 2);
if (!rdev->mode_info.load_detect_property)
return -ENOMEM;
rdev->mode_info.load_detect_property->values[0] = 0;
rdev->mode_info.load_detect_property->values[0] = 1;
 
drm_mode_create_scaling_mode_property(rdev->ddev);
 
sz = ARRAY_SIZE(radeon_tv_std_enum_list);
rdev->mode_info.tv_std_property =
drm_property_create(rdev->ddev,
DRM_MODE_PROP_ENUM,
"tv standard", sz);
for (i = 0; i < sz; i++) {
drm_property_add_enum(rdev->mode_info.tv_std_property,
i,
radeon_tv_std_enum_list[i].type,
radeon_tv_std_enum_list[i].name);
}
 
return 0;
}
 
int radeon_modeset_init(struct radeon_device *rdev)
{
int num_crtc = 2, i;
int ret;
 
651,6 → 723,10
 
rdev->ddev->mode_config.fb_base = rdev->mc.aper_base;
 
ret = radeon_modeset_create_props(rdev);
if (ret) {
return ret;
}
/* allocate crtcs - TODO single crtc */
for (i = 0; i < num_crtc; i++) {
radeon_crtc_init(rdev->ddev, i);
662,9 → 738,6
return ret;
}
drm_helper_initial_config(rdev->ddev);
 
dbgprintf("done %s\n",__FUNCTION__);
 
return 0;
}
 
676,36 → 749,50
}
}
 
void radeon_init_disp_bandwidth(struct drm_device *dev)
bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct radeon_device *rdev = dev->dev_private;
struct drm_display_mode *modes[2];
int pixel_bytes[2];
struct drm_crtc *crtc;
 
pixel_bytes[0] = pixel_bytes[1] = 0;
modes[0] = modes[1] = NULL;
 
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct drm_device *dev = crtc->dev;
struct drm_encoder *encoder;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct radeon_encoder *radeon_encoder;
bool first = true;
 
if (crtc->enabled && crtc->fb) {
modes[radeon_crtc->crtc_id] = &crtc->mode;
pixel_bytes[radeon_crtc->crtc_id] = crtc->fb->bits_per_pixel / 8;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
radeon_encoder = to_radeon_encoder(encoder);
if (encoder->crtc != crtc)
continue;
if (first) {
radeon_crtc->rmx_type = radeon_encoder->rmx_type;
memcpy(&radeon_crtc->native_mode,
&radeon_encoder->native_mode,
sizeof(struct radeon_native_mode));
first = false;
} else {
if (radeon_crtc->rmx_type != radeon_encoder->rmx_type) {
/* WARNING: Right now this can't happen but
* in the future we need to check that scaling
* are consistent accross different encoder
* (ie all encoder can work with the same
* scaling).
*/
DRM_ERROR("Scaling not consistent accross encoder.\n");
return false;
}
}
 
if (ASIC_IS_AVIVO(rdev)) {
radeon_init_disp_bw_avivo(dev,
modes[0],
pixel_bytes[0],
modes[1],
pixel_bytes[1]);
}
if (radeon_crtc->rmx_type != RMX_OFF) {
fixed20_12 a, b;
a.full = rfixed_const(crtc->mode.vdisplay);
b.full = rfixed_const(radeon_crtc->native_mode.panel_xres);
radeon_crtc->vsc.full = rfixed_div(a, b);
a.full = rfixed_const(crtc->mode.hdisplay);
b.full = rfixed_const(radeon_crtc->native_mode.panel_yres);
radeon_crtc->hsc.full = rfixed_div(a, b);
} else {
radeon_init_disp_bw_legacy(dev,
modes[0],
pixel_bytes[0],
modes[1],
pixel_bytes[1]);
radeon_crtc->vsc.full = rfixed_const(1);
radeon_crtc->hsc.full = rfixed_const(1);
}
return true;
}
/drivers/video/drm/radeon/radeon_encoders.c
126,6 → 126,23
}
}
 
void radeon_encoder_set_active_device(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct drm_connector *connector;
 
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (connector->encoder == encoder) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
radeon_encoder->active_device = radeon_encoder->devices & radeon_connector->devices;
DRM_DEBUG("setting active device to %08x from %08x %08x for encoder %d\n",
radeon_encoder->active_device, radeon_encoder->devices,
radeon_connector->devices, encoder->encoder_type);
}
}
}
 
static struct drm_connector *
radeon_get_connector_for_encoder(struct drm_encoder *encoder)
{
154,7 → 171,6
 
if (mode->hdisplay < native_mode->panel_xres ||
mode->vdisplay < native_mode->panel_yres) {
radeon_encoder->flags |= RADEON_USE_RMX;
if (ASIC_IS_AVIVO(rdev)) {
adjusted_mode->hdisplay = native_mode->panel_xres;
adjusted_mode->vdisplay = native_mode->panel_yres;
201,11 → 217,8
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;
 
drm_mode_set_crtcinfo(adjusted_mode, 0);
 
if (radeon_encoder->rmx_type != RMX_OFF)
227,9 → 240,12
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
DAC_ENCODER_CONTROL_PS_ALLOCATION args;
int index = 0, num = 0;
/* fixme - fill in enc_priv for atom dac */
struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
enum radeon_tv_std tv_std = TV_STD_NTSC;
 
if (dac_info->tv_std)
tv_std = dac_info->tv_std;
 
memset(&args, 0, sizeof(args));
 
switch (radeon_encoder->encoder_id) {
247,9 → 263,9
 
args.ucAction = action;
 
if (radeon_encoder->devices & (ATOM_DEVICE_CRT_SUPPORT))
if (radeon_encoder->active_device & (ATOM_DEVICE_CRT_SUPPORT))
args.ucDacStandard = ATOM_DAC1_PS2;
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
args.ucDacStandard = ATOM_DAC1_CV;
else {
switch (tv_std) {
282,9 → 298,12
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
TV_ENCODER_CONTROL_PS_ALLOCATION args;
int index = 0;
/* fixme - fill in enc_priv for atom dac */
struct radeon_encoder_atom_dac *dac_info = radeon_encoder->enc_priv;
enum radeon_tv_std tv_std = TV_STD_NTSC;
 
if (dac_info->tv_std)
tv_std = dac_info->tv_std;
 
memset(&args, 0, sizeof(args));
 
index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl);
291,7 → 310,7
 
args.sTVEncoder.ucAction = action;
 
if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
args.sTVEncoder.ucTvStandard = ATOM_TV_CV;
else {
switch (tv_std) {
523,6 → 542,7
 
switch (connector->connector_type) {
case DRM_MODE_CONNECTOR_DVII:
case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */
if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr))
return ATOM_ENCODER_MODE_HDMI;
else if (radeon_connector->use_digital)
532,7 → 552,6
break;
case DRM_MODE_CONNECTOR_DVID:
case DRM_MODE_CONNECTOR_HDMIA:
case DRM_MODE_CONNECTOR_HDMIB:
default:
if (drm_detect_hdmi_monitor((struct edid *)connector->edid_blob_ptr))
return ATOM_ENCODER_MODE_HDMI;
808,234 → 827,6
 
}
 
static void atom_rv515_force_tv_scaler(struct radeon_device *rdev)
{
 
WREG32(0x659C, 0x0);
WREG32(0x6594, 0x705);
WREG32(0x65A4, 0x10001);
WREG32(0x65D8, 0x0);
WREG32(0x65B0, 0x0);
WREG32(0x65C0, 0x0);
WREG32(0x65D4, 0x0);
WREG32(0x6578, 0x0);
WREG32(0x657C, 0x841880A8);
WREG32(0x6578, 0x1);
WREG32(0x657C, 0x84208680);
WREG32(0x6578, 0x2);
WREG32(0x657C, 0xBFF880B0);
WREG32(0x6578, 0x100);
WREG32(0x657C, 0x83D88088);
WREG32(0x6578, 0x101);
WREG32(0x657C, 0x84608680);
WREG32(0x6578, 0x102);
WREG32(0x657C, 0xBFF080D0);
WREG32(0x6578, 0x200);
WREG32(0x657C, 0x83988068);
WREG32(0x6578, 0x201);
WREG32(0x657C, 0x84A08680);
WREG32(0x6578, 0x202);
WREG32(0x657C, 0xBFF080F8);
WREG32(0x6578, 0x300);
WREG32(0x657C, 0x83588058);
WREG32(0x6578, 0x301);
WREG32(0x657C, 0x84E08660);
WREG32(0x6578, 0x302);
WREG32(0x657C, 0xBFF88120);
WREG32(0x6578, 0x400);
WREG32(0x657C, 0x83188040);
WREG32(0x6578, 0x401);
WREG32(0x657C, 0x85008660);
WREG32(0x6578, 0x402);
WREG32(0x657C, 0xBFF88150);
WREG32(0x6578, 0x500);
WREG32(0x657C, 0x82D88030);
WREG32(0x6578, 0x501);
WREG32(0x657C, 0x85408640);
WREG32(0x6578, 0x502);
WREG32(0x657C, 0xBFF88180);
WREG32(0x6578, 0x600);
WREG32(0x657C, 0x82A08018);
WREG32(0x6578, 0x601);
WREG32(0x657C, 0x85808620);
WREG32(0x6578, 0x602);
WREG32(0x657C, 0xBFF081B8);
WREG32(0x6578, 0x700);
WREG32(0x657C, 0x82608010);
WREG32(0x6578, 0x701);
WREG32(0x657C, 0x85A08600);
WREG32(0x6578, 0x702);
WREG32(0x657C, 0x800081F0);
WREG32(0x6578, 0x800);
WREG32(0x657C, 0x8228BFF8);
WREG32(0x6578, 0x801);
WREG32(0x657C, 0x85E085E0);
WREG32(0x6578, 0x802);
WREG32(0x657C, 0xBFF88228);
WREG32(0x6578, 0x10000);
WREG32(0x657C, 0x82A8BF00);
WREG32(0x6578, 0x10001);
WREG32(0x657C, 0x82A08CC0);
WREG32(0x6578, 0x10002);
WREG32(0x657C, 0x8008BEF8);
WREG32(0x6578, 0x10100);
WREG32(0x657C, 0x81F0BF28);
WREG32(0x6578, 0x10101);
WREG32(0x657C, 0x83608CA0);
WREG32(0x6578, 0x10102);
WREG32(0x657C, 0x8018BED0);
WREG32(0x6578, 0x10200);
WREG32(0x657C, 0x8148BF38);
WREG32(0x6578, 0x10201);
WREG32(0x657C, 0x84408C80);
WREG32(0x6578, 0x10202);
WREG32(0x657C, 0x8008BEB8);
WREG32(0x6578, 0x10300);
WREG32(0x657C, 0x80B0BF78);
WREG32(0x6578, 0x10301);
WREG32(0x657C, 0x85008C20);
WREG32(0x6578, 0x10302);
WREG32(0x657C, 0x8020BEA0);
WREG32(0x6578, 0x10400);
WREG32(0x657C, 0x8028BF90);
WREG32(0x6578, 0x10401);
WREG32(0x657C, 0x85E08BC0);
WREG32(0x6578, 0x10402);
WREG32(0x657C, 0x8018BE90);
WREG32(0x6578, 0x10500);
WREG32(0x657C, 0xBFB8BFB0);
WREG32(0x6578, 0x10501);
WREG32(0x657C, 0x86C08B40);
WREG32(0x6578, 0x10502);
WREG32(0x657C, 0x8010BE90);
WREG32(0x6578, 0x10600);
WREG32(0x657C, 0xBF58BFC8);
WREG32(0x6578, 0x10601);
WREG32(0x657C, 0x87A08AA0);
WREG32(0x6578, 0x10602);
WREG32(0x657C, 0x8010BE98);
WREG32(0x6578, 0x10700);
WREG32(0x657C, 0xBF10BFF0);
WREG32(0x6578, 0x10701);
WREG32(0x657C, 0x886089E0);
WREG32(0x6578, 0x10702);
WREG32(0x657C, 0x8018BEB0);
WREG32(0x6578, 0x10800);
WREG32(0x657C, 0xBED8BFE8);
WREG32(0x6578, 0x10801);
WREG32(0x657C, 0x89408940);
WREG32(0x6578, 0x10802);
WREG32(0x657C, 0xBFE8BED8);
WREG32(0x6578, 0x20000);
WREG32(0x657C, 0x80008000);
WREG32(0x6578, 0x20001);
WREG32(0x657C, 0x90008000);
WREG32(0x6578, 0x20002);
WREG32(0x657C, 0x80008000);
WREG32(0x6578, 0x20003);
WREG32(0x657C, 0x80008000);
WREG32(0x6578, 0x20100);
WREG32(0x657C, 0x80108000);
WREG32(0x6578, 0x20101);
WREG32(0x657C, 0x8FE0BF70);
WREG32(0x6578, 0x20102);
WREG32(0x657C, 0xBFE880C0);
WREG32(0x6578, 0x20103);
WREG32(0x657C, 0x80008000);
WREG32(0x6578, 0x20200);
WREG32(0x657C, 0x8018BFF8);
WREG32(0x6578, 0x20201);
WREG32(0x657C, 0x8F80BF08);
WREG32(0x6578, 0x20202);
WREG32(0x657C, 0xBFD081A0);
WREG32(0x6578, 0x20203);
WREG32(0x657C, 0xBFF88000);
WREG32(0x6578, 0x20300);
WREG32(0x657C, 0x80188000);
WREG32(0x6578, 0x20301);
WREG32(0x657C, 0x8EE0BEC0);
WREG32(0x6578, 0x20302);
WREG32(0x657C, 0xBFB082A0);
WREG32(0x6578, 0x20303);
WREG32(0x657C, 0x80008000);
WREG32(0x6578, 0x20400);
WREG32(0x657C, 0x80188000);
WREG32(0x6578, 0x20401);
WREG32(0x657C, 0x8E00BEA0);
WREG32(0x6578, 0x20402);
WREG32(0x657C, 0xBF8883C0);
WREG32(0x6578, 0x20403);
WREG32(0x657C, 0x80008000);
WREG32(0x6578, 0x20500);
WREG32(0x657C, 0x80188000);
WREG32(0x6578, 0x20501);
WREG32(0x657C, 0x8D00BE90);
WREG32(0x6578, 0x20502);
WREG32(0x657C, 0xBF588500);
WREG32(0x6578, 0x20503);
WREG32(0x657C, 0x80008008);
WREG32(0x6578, 0x20600);
WREG32(0x657C, 0x80188000);
WREG32(0x6578, 0x20601);
WREG32(0x657C, 0x8BC0BE98);
WREG32(0x6578, 0x20602);
WREG32(0x657C, 0xBF308660);
WREG32(0x6578, 0x20603);
WREG32(0x657C, 0x80008008);
WREG32(0x6578, 0x20700);
WREG32(0x657C, 0x80108000);
WREG32(0x6578, 0x20701);
WREG32(0x657C, 0x8A80BEB0);
WREG32(0x6578, 0x20702);
WREG32(0x657C, 0xBF0087C0);
WREG32(0x6578, 0x20703);
WREG32(0x657C, 0x80008008);
WREG32(0x6578, 0x20800);
WREG32(0x657C, 0x80108000);
WREG32(0x6578, 0x20801);
WREG32(0x657C, 0x8920BED0);
WREG32(0x6578, 0x20802);
WREG32(0x657C, 0xBED08920);
WREG32(0x6578, 0x20803);
WREG32(0x657C, 0x80008010);
WREG32(0x6578, 0x30000);
WREG32(0x657C, 0x90008000);
WREG32(0x6578, 0x30001);
WREG32(0x657C, 0x80008000);
WREG32(0x6578, 0x30100);
WREG32(0x657C, 0x8FE0BF90);
WREG32(0x6578, 0x30101);
WREG32(0x657C, 0xBFF880A0);
WREG32(0x6578, 0x30200);
WREG32(0x657C, 0x8F60BF40);
WREG32(0x6578, 0x30201);
WREG32(0x657C, 0xBFE88180);
WREG32(0x6578, 0x30300);
WREG32(0x657C, 0x8EC0BF00);
WREG32(0x6578, 0x30301);
WREG32(0x657C, 0xBFC88280);
WREG32(0x6578, 0x30400);
WREG32(0x657C, 0x8DE0BEE0);
WREG32(0x6578, 0x30401);
WREG32(0x657C, 0xBFA083A0);
WREG32(0x6578, 0x30500);
WREG32(0x657C, 0x8CE0BED0);
WREG32(0x6578, 0x30501);
WREG32(0x657C, 0xBF7884E0);
WREG32(0x6578, 0x30600);
WREG32(0x657C, 0x8BA0BED8);
WREG32(0x6578, 0x30601);
WREG32(0x657C, 0xBF508640);
WREG32(0x6578, 0x30700);
WREG32(0x657C, 0x8A60BEE8);
WREG32(0x6578, 0x30701);
WREG32(0x657C, 0xBF2087A0);
WREG32(0x6578, 0x30800);
WREG32(0x657C, 0x8900BF00);
WREG32(0x6578, 0x30801);
WREG32(0x657C, 0xBF008900);
}
 
static void
atombios_yuv_setup(struct drm_encoder *encoder, bool enable)
{
1056,10 → 847,10
 
/* XXX: fix up scratch reg handling */
temp = RREG32(reg);
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
WREG32(reg, (ATOM_S3_TV1_ACTIVE |
(radeon_crtc->crtc_id << 18)));
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
WREG32(reg, (ATOM_S3_CV_ACTIVE | (radeon_crtc->crtc_id << 24)));
else
WREG32(reg, 0);
1074,129 → 865,6
}
 
static void
atombios_overscan_setup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
SET_CRTC_OVERSCAN_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan);
 
memset(&args, 0, sizeof(args));
 
args.usOverscanRight = 0;
args.usOverscanLeft = 0;
args.usOverscanBottom = 0;
args.usOverscanTop = 0;
args.ucCRTC = radeon_crtc->crtc_id;
 
if (radeon_encoder->flags & RADEON_USE_RMX) {
if (radeon_encoder->rmx_type == RMX_FULL) {
args.usOverscanRight = 0;
args.usOverscanLeft = 0;
args.usOverscanBottom = 0;
args.usOverscanTop = 0;
} else if (radeon_encoder->rmx_type == RMX_CENTER) {
args.usOverscanTop = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
args.usOverscanBottom = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
args.usOverscanRight = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
} else if (radeon_encoder->rmx_type == RMX_ASPECT) {
int a1 = mode->crtc_vdisplay * adjusted_mode->crtc_hdisplay;
int a2 = adjusted_mode->crtc_vdisplay * mode->crtc_hdisplay;
 
if (a1 > a2) {
args.usOverscanLeft = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
args.usOverscanRight = (adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2;
} else if (a2 > a1) {
args.usOverscanLeft = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
args.usOverscanRight = (adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2;
}
}
}
 
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 
}
 
static void
atombios_scaler_setup(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
ENABLE_SCALER_PS_ALLOCATION args;
int index = GetIndexIntoMasterTable(COMMAND, EnableScaler);
/* fixme - fill in enc_priv for atom dac */
enum radeon_tv_std tv_std = TV_STD_NTSC;
 
if (!ASIC_IS_AVIVO(rdev) && radeon_crtc->crtc_id)
return;
 
memset(&args, 0, sizeof(args));
 
args.ucScaler = radeon_crtc->crtc_id;
 
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT)) {
switch (tv_std) {
case TV_STD_NTSC:
default:
args.ucTVStandard = ATOM_TV_NTSC;
break;
case TV_STD_PAL:
args.ucTVStandard = ATOM_TV_PAL;
break;
case TV_STD_PAL_M:
args.ucTVStandard = ATOM_TV_PALM;
break;
case TV_STD_PAL_60:
args.ucTVStandard = ATOM_TV_PAL60;
break;
case TV_STD_NTSC_J:
args.ucTVStandard = ATOM_TV_NTSCJ;
break;
case TV_STD_SCART_PAL:
args.ucTVStandard = ATOM_TV_PAL; /* ??? */
break;
case TV_STD_SECAM:
args.ucTVStandard = ATOM_TV_SECAM;
break;
case TV_STD_PAL_CN:
args.ucTVStandard = ATOM_TV_PALCN;
break;
}
args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
} else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT)) {
args.ucTVStandard = ATOM_TV_CV;
args.ucEnable = SCALER_ENABLE_MULTITAP_MODE;
} else 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 if (radeon_encoder->rmx_type == RMX_ASPECT)
args.ucEnable = ATOM_SCALER_EXPANSION;
} else {
if (ASIC_IS_AVIVO(rdev))
args.ucEnable = ATOM_SCALER_DISABLE;
else
args.ucEnable = ATOM_SCALER_CENTER;
}
 
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 
if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)
&& rdev->family >= CHIP_RV515 && rdev->family <= CHIP_RV570) {
atom_rv515_force_tv_scaler(rdev);
}
 
}
 
static void
radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
1205,9 → 873,19
DISPLAY_DEVICE_OUTPUT_CONTROL_PS_ALLOCATION args;
int index = 0;
bool is_dig = false;
int devices;
 
memset(&args, 0, sizeof(args));
 
/* on DPMS off we have no idea if active device is meaningful */
if (mode != DRM_MODE_DPMS_ON && !radeon_encoder->active_device)
devices = radeon_encoder->devices;
else
devices = radeon_encoder->active_device;
 
DRM_DEBUG("encoder dpms %d to mode %d, devices %08x, active_devices %08x\n",
radeon_encoder->encoder_id, mode, radeon_encoder->devices,
radeon_encoder->active_device);
switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
1235,9 → 913,9
break;
case ENCODER_OBJECT_ID_INTERNAL_DAC1:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
if (devices & (ATOM_DEVICE_TV_SUPPORT))
index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
else if (devices & (ATOM_DEVICE_CV_SUPPORT))
index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
else
index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl);
1244,9 → 922,9
break;
case ENCODER_OBJECT_ID_INTERNAL_DAC2:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
if (devices & (ATOM_DEVICE_TV_SUPPORT))
index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl);
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
else if (devices & (ATOM_DEVICE_CV_SUPPORT))
index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl);
else
index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl);
1333,9 → 1011,9
break;
case ENCODER_OBJECT_ID_INTERNAL_DAC1:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
else
args.v1.ucDevice = ATOM_DEVICE_CRT1_INDEX;
1342,9 → 1020,9
break;
case ENCODER_OBJECT_ID_INTERNAL_DAC2:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
args.v1.ucDevice = ATOM_DEVICE_TV1_INDEX;
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
args.v1.ucDevice = ATOM_DEVICE_CV_INDEX;
else
args.v1.ucDevice = ATOM_DEVICE_CRT2_INDEX;
1373,17 → 1051,17
args.v2.ucEncoderID = ASIC_INT_DIG2_ENCODER_ID;
break;
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
else
args.v2.ucEncoderID = ASIC_INT_DAC1_ENCODER_ID;
break;
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT))
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
else if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT))
else if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT))
args.v2.ucEncoderID = ASIC_INT_TV_ENCODER_ID;
else
args.v2.ucEncoderID = ASIC_INT_DAC2_ENCODER_ID;
1448,12 → 1126,10
radeon_encoder->pixel_clock = adjusted_mode->clock;
 
radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
atombios_overscan_setup(encoder, mode, adjusted_mode);
atombios_scaler_setup(encoder);
atombios_set_encoder_crtc_source(encoder);
 
if (ASIC_IS_AVIVO(rdev)) {
if (radeon_encoder->devices & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
atombios_yuv_setup(encoder, true);
else
atombios_yuv_setup(encoder, false);
1491,7 → 1167,7
case ENCODER_OBJECT_ID_INTERNAL_DAC2:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
atombios_dac_setup(encoder, ATOM_ENABLE);
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))
atombios_tv_setup(encoder, ATOM_ENABLE);
break;
}
1499,11 → 1175,12
}
 
static bool
atombios_dac_load_detect(struct drm_encoder *encoder)
atombios_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 
if (radeon_encoder->devices & (ATOM_DEVICE_TV_SUPPORT |
ATOM_DEVICE_CV_SUPPORT |
1524,15 → 1201,15
else
args.sDacload.ucDacType = ATOM_DAC_B;
 
if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT)
if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT)
args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT1_SUPPORT);
else if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT)
else if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT)
args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CRT2_SUPPORT);
else if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
else if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_CV_SUPPORT);
if (crev >= 3)
args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
} else if (radeon_encoder->devices & ATOM_DEVICE_TV1_SUPPORT) {
} else if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
args.sDacload.usDeviceID = cpu_to_le16(ATOM_DEVICE_TV1_SUPPORT);
if (crev >= 3)
args.sDacload.ucMisc = DAC_LOAD_MISC_YPrPb;
1551,9 → 1228,10
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
uint32_t bios_0_scratch;
 
if (!atombios_dac_load_detect(encoder)) {
if (!atombios_dac_load_detect(encoder, connector)) {
DRM_DEBUG("detect returned false \n");
return connector_status_unknown;
}
1563,17 → 1241,20
else
bios_0_scratch = RREG32(RADEON_BIOS_0_SCRATCH);
 
DRM_DEBUG("Bios 0 scratch %x\n", bios_0_scratch);
if (radeon_encoder->devices & ATOM_DEVICE_CRT1_SUPPORT) {
DRM_DEBUG("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
if (bios_0_scratch & ATOM_S0_CRT1_MASK)
return connector_status_connected;
} else if (radeon_encoder->devices & ATOM_DEVICE_CRT2_SUPPORT) {
}
if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
if (bios_0_scratch & ATOM_S0_CRT2_MASK)
return connector_status_connected;
} else if (radeon_encoder->devices & ATOM_DEVICE_CV_SUPPORT) {
}
if (radeon_connector->devices & 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->devices & ATOM_DEVICE_TV1_SUPPORT) {
}
if (radeon_connector->devices & 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))
1586,6 → 1267,8
{
radeon_atom_output_lock(encoder, true);
radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
 
radeon_encoder_set_active_device(encoder);
}
 
static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
1594,6 → 1277,13
radeon_atom_output_lock(encoder, false);
}
 
static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
radeon_encoder->active_device = 0;
}
 
static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
.dpms = radeon_atom_encoder_dpms,
.mode_fixup = radeon_atom_mode_fixup,
1600,6 → 1290,7
.prepare = radeon_atom_encoder_prepare,
.mode_set = radeon_atom_encoder_mode_set,
.commit = radeon_atom_encoder_commit,
.disable = radeon_atom_encoder_disable,
/* no detect for TMDS/LVDS yet */
};
 
1624,6 → 1315,18
.destroy = radeon_enc_destroy,
};
 
struct radeon_encoder_atom_dac *
radeon_atombios_set_dac_info(struct radeon_encoder *radeon_encoder)
{
struct radeon_encoder_atom_dac *dac = kzalloc(sizeof(struct radeon_encoder_atom_dac), GFP_KERNEL);
 
if (!dac)
return NULL;
 
dac->tv_std = TV_STD_NTSC;
return dac;
}
 
struct radeon_encoder_atom_dig *
radeon_atombios_set_dig_info(struct radeon_encoder *radeon_encoder)
{
1667,6 → 1370,7
 
radeon_encoder->encoder_id = encoder_id;
radeon_encoder->devices = supported_device;
radeon_encoder->rmx_type = RMX_OFF;
 
switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_LVDS:
1691,6 → 1395,7
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TVDAC);
radeon_encoder->enc_priv = radeon_atombios_set_dac_info(radeon_encoder);
drm_encoder_helper_add(encoder, &radeon_atom_dac_helper_funcs);
break;
case ENCODER_OBJECT_ID_INTERNAL_DVO1:
1700,8 → 1405,14
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
radeon_encoder->rmx_type = RMX_FULL;
drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_LVDS);
radeon_encoder->enc_priv = radeon_atombios_get_lvds_info(radeon_encoder);
} else {
drm_encoder_init(dev, encoder, &radeon_atom_enc_funcs, DRM_MODE_ENCODER_TMDS);
radeon_encoder->enc_priv = radeon_atombios_set_dig_info(radeon_encoder);
}
drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
break;
}
/drivers/video/drm/radeon/radeon_family.h
0,0 → 1,97
/*
* Copyright 2008 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
* Copyright 2009 Jerome Glisse.
*
* 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
* Jerome Glisse
*/
 
/* this file defines the CHIP_ and family flags used in the pciids,
* its is common between kms and non-kms because duplicating it and
* changing one place is fail.
*/
#ifndef RADEON_FAMILY_H
#define RADEON_FAMILY_H
/*
* Radeon chip families
*/
enum radeon_family {
CHIP_R100,
CHIP_RV100,
CHIP_RS100,
CHIP_RV200,
CHIP_RS200,
CHIP_R200,
CHIP_RV250,
CHIP_RS300,
CHIP_RV280,
CHIP_R300,
CHIP_R350,
CHIP_RV350,
CHIP_RV380,
CHIP_R420,
CHIP_R423,
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_RV610,
CHIP_RV630,
CHIP_RV670,
CHIP_RV620,
CHIP_RV635,
CHIP_RS780,
CHIP_RS880,
CHIP_RV770,
CHIP_RV730,
CHIP_RV710,
CHIP_RV740,
CHIP_LAST,
};
 
/*
* Chip flags
*/
enum radeon_chip_flags {
RADEON_FAMILY_MASK = 0x0000ffffUL,
RADEON_FLAGS_MASK = 0xffff0000UL,
RADEON_IS_MOBILITY = 0x00010000UL,
RADEON_IS_IGP = 0x00020000UL,
RADEON_SINGLE_CRTC = 0x00040000UL,
RADEON_IS_AGP = 0x00080000UL,
RADEON_HAS_HIERZ = 0x00100000UL,
RADEON_IS_PCIE = 0x00200000UL,
RADEON_NEW_MEMMAP = 0x00400000UL,
RADEON_IS_PCI = 0x00800000UL,
RADEON_IS_IGPGART = 0x01000000UL,
};
#endif
/drivers/video/drm/radeon/radeon_fb.c
27,16 → 27,8
* Modularization
*/
 
//#include <linux/module.h>
//#include <linux/kernel.h>
//#include <linux/errno.h>
//#include <linux/string.h>
//#include <linux/mm.h>
//#include <linux/tty.h>
//#include <linux/slab.h>
//#include <linux/delay.h>
//#include <linux/fb.h>
//#include <linux/init.h>
#include <linux/module.h>
#include <linux/fb.h>
 
#include "drmP.h"
#include "drm.h"
45,559 → 37,29
#include "radeon_drm.h"
#include "radeon.h"
 
#include "drm_fb_helper.h"
 
#include <drm_mm.h>
#include "radeon_object.h"
 
struct fb_info *framebuffer_alloc(size_t size);
 
#define FB_TYPE_PACKED_PIXELS 0 /* Packed Pixels */
#define FB_VISUAL_TRUECOLOR 2 /* True color */
 
struct fb_fix_screeninfo {
char id[16]; /* identification string eg "TT Builtin" */
unsigned long smem_start; /* Start of frame buffer mem */
/* (physical address) */
__u32 smem_len; /* Length of frame buffer mem */
__u32 type; /* see FB_TYPE_* */
__u32 type_aux; /* Interleave for interleaved Planes */
__u32 visual; /* see FB_VISUAL_* */
__u16 xpanstep; /* zero if no hardware panning */
__u16 ypanstep; /* zero if no hardware panning */
__u16 ywrapstep; /* zero if no hardware ywrap */
__u32 line_length; /* length of a line in bytes */
unsigned long mmio_start; /* Start of Memory Mapped I/O */
/* (physical address) */
__u32 mmio_len; /* Length of Memory Mapped I/O */
__u32 accel; /* Indicate to driver which */
/* specific chip/card we have */
__u16 reserved[3]; /* Reserved for future compatibility */
};
 
 
 
 
struct fb_bitfield {
__u32 offset; /* beginning of bitfield */
__u32 length; /* length of bitfield */
__u32 msb_right; /* != 0 : Most significant bit is */
/* right */
};
 
 
struct fb_var_screeninfo {
__u32 xres; /* visible resolution */
__u32 yres;
__u32 xres_virtual; /* virtual resolution */
__u32 yres_virtual;
__u32 xoffset; /* offset from virtual to visible */
__u32 yoffset; /* resolution */
 
__u32 bits_per_pixel; /* guess what */
__u32 grayscale; /* != 0 Graylevels instead of colors */
 
struct fb_bitfield red; /* bitfield in fb mem if true color, */
struct fb_bitfield green; /* else only length is significant */
struct fb_bitfield blue;
struct fb_bitfield transp; /* transparency */
 
__u32 nonstd; /* != 0 Non standard pixel format */
 
__u32 activate; /* see FB_ACTIVATE_* */
 
__u32 height; /* height of picture in mm */
__u32 width; /* width of picture in mm */
 
__u32 accel_flags; /* (OBSOLETE) see fb_info.flags */
 
/* Timing: All values in pixclocks, except pixclock (of course) */
__u32 pixclock; /* pixel clock in ps (pico seconds) */
__u32 left_margin; /* time from sync to picture */
__u32 right_margin; /* time from picture to sync */
__u32 upper_margin; /* time from sync to picture */
__u32 lower_margin;
__u32 hsync_len; /* length of horizontal sync */
__u32 vsync_len; /* length of vertical sync */
__u32 sync; /* see FB_SYNC_* */
__u32 vmode; /* see FB_VMODE_* */
__u32 rotate; /* angle we rotate counter clockwise */
__u32 reserved[5]; /* Reserved for future compatibility */
};
 
 
 
struct fb_chroma {
__u32 redx; /* in fraction of 1024 */
__u32 greenx;
__u32 bluex;
__u32 whitex;
__u32 redy;
__u32 greeny;
__u32 bluey;
__u32 whitey;
};
 
struct fb_videomode {
const char *name; /* optional */
u32 refresh; /* optional */
u32 xres;
u32 yres;
u32 pixclock;
u32 left_margin;
u32 right_margin;
u32 upper_margin;
u32 lower_margin;
u32 hsync_len;
u32 vsync_len;
u32 sync;
u32 vmode;
u32 flag;
};
 
 
struct fb_monspecs {
struct fb_chroma chroma;
struct fb_videomode *modedb; /* mode database */
__u8 manufacturer[4]; /* Manufacturer */
__u8 monitor[14]; /* Monitor String */
__u8 serial_no[14]; /* Serial Number */
__u8 ascii[14]; /* ? */
__u32 modedb_len; /* mode database length */
__u32 model; /* Monitor Model */
__u32 serial; /* Serial Number - Integer */
__u32 year; /* Year manufactured */
__u32 week; /* Week Manufactured */
__u32 hfmin; /* hfreq lower limit (Hz) */
__u32 hfmax; /* hfreq upper limit (Hz) */
__u32 dclkmin; /* pixelclock lower limit (Hz) */
__u32 dclkmax; /* pixelclock upper limit (Hz) */
__u16 input; /* display type - see FB_DISP_* */
__u16 dpms; /* DPMS support - see FB_DPMS_ */
__u16 signal; /* Signal Type - see FB_SIGNAL_* */
__u16 vfmin; /* vfreq lower limit (Hz) */
__u16 vfmax; /* vfreq upper limit (Hz) */
__u16 gamma; /* Gamma - in fractions of 100 */
__u16 gtf : 1; /* supports GTF */
__u16 misc; /* Misc flags - see FB_MISC_* */
__u8 version; /* EDID version... */
__u8 revision; /* ...and revision */
__u8 max_x; /* Maximum horizontal size (cm) */
__u8 max_y; /* Maximum vertical size (cm) */
};
 
 
struct fb_info {
int node;
int flags;
// struct mutex lock; /* Lock for open/release/ioctl funcs */
// struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */
struct fb_var_screeninfo var; /* Current var */
struct fb_fix_screeninfo fix; /* Current fix */
struct fb_monspecs monspecs; /* Current Monitor specs */
// struct work_struct queue; /* Framebuffer event queue */
// struct fb_pixmap pixmap; /* Image hardware mapper */
// struct fb_pixmap sprite; /* Cursor hardware mapper */
// struct fb_cmap cmap; /* Current cmap */
struct list_head modelist; /* mode list */
struct fb_videomode *mode; /* current mode */
 
#ifdef CONFIG_FB_BACKLIGHT
/* assigned backlight device */
/* set before framebuffer registration,
remove after unregister */
struct backlight_device *bl_dev;
 
/* Backlight level curve */
struct mutex bl_curve_mutex;
u8 bl_curve[FB_BACKLIGHT_LEVELS];
#endif
#ifdef CONFIG_FB_DEFERRED_IO
struct delayed_work deferred_work;
struct fb_deferred_io *fbdefio;
#endif
 
struct fb_ops *fbops;
// struct device *device; /* This is the parent */
// struct device *dev; /* This is this fb device */
int class_flag; /* private sysfs flags */
#ifdef CONFIG_FB_TILEBLITTING
struct fb_tile_ops *tileops; /* Tile Blitting */
#endif
char __iomem *screen_base; /* Virtual address */
unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */
void *pseudo_palette; /* Fake palette of 16 colors */
#define FBINFO_STATE_RUNNING 0
#define FBINFO_STATE_SUSPENDED 1
u32 state; /* Hardware state i.e suspend */
void *fbcon_par; /* fbcon use-only private area */
/* From here on everything is device dependent */
void *par;
/* we need the PCI or similiar aperture base/size not
smem_start/size as smem_start may just be an object
allocated inside the aperture so may not actually overlap */
resource_size_t aperture_base;
resource_size_t aperture_size;
};
 
 
 
struct radeon_fb_device {
struct drm_fb_helper helper;
struct radeon_framebuffer *rfb;
struct radeon_device *rdev;
struct drm_display_mode *mode;
struct radeon_framebuffer *rfb;
int crtc_count;
/* crtc currently bound to this */
uint32_t crtc_ids[2];
};
 
int radeon_gem_fb_object_create(struct radeon_device *rdev, int size,
int alignment, int initial_domain,
bool discardable, bool kernel,
bool interruptible,
struct drm_gem_object **obj);
 
struct fb_info *framebuffer_alloc(size_t size);
 
#if 0
static int radeonfb_setcolreg(unsigned regno,
unsigned red,
unsigned green,
unsigned blue,
unsigned transp,
struct fb_info *info)
{
struct radeon_fb_device *rfbdev = info->par;
struct drm_device *dev = rfbdev->rdev->ddev;
struct drm_crtc *crtc;
int i;
 
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_mode_set *modeset = &radeon_crtc->mode_set;
struct drm_framebuffer *fb = modeset->fb;
 
for (i = 0; i < rfbdev->crtc_count; i++) {
if (crtc->base.id == rfbdev->crtc_ids[i]) {
break;
}
}
if (i == rfbdev->crtc_count) {
continue;
}
if (regno > 255) {
return 1;
}
if (fb->depth == 8) {
radeon_crtc_fb_gamma_set(crtc, red, green, blue, regno);
return 0;
}
 
if (regno < 16) {
switch (fb->depth) {
case 15:
fb->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
((green & 0xf800) >> 6) |
((blue & 0xf800) >> 11);
break;
case 16:
fb->pseudo_palette[regno] = (red & 0xf800) |
((green & 0xfc00) >> 5) |
((blue & 0xf800) >> 11);
break;
case 24:
case 32:
fb->pseudo_palette[regno] = ((red & 0xff00) << 8) |
(green & 0xff00) |
((blue & 0xff00) >> 8);
break;
}
}
}
return 0;
}
 
static int radeonfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct radeon_fb_device *rfbdev = info->par;
struct radeon_framebuffer *rfb = rfbdev->rfb;
struct drm_framebuffer *fb = &rfb->base;
int depth;
 
if (var->pixclock == -1 || !var->pixclock) {
return -EINVAL;
}
/* Need to resize the fb object !!! */
if (var->xres > fb->width || var->yres > fb->height) {
DRM_ERROR("Requested width/height is greater than current fb "
"object %dx%d > %dx%d\n", var->xres, var->yres,
fb->width, fb->height);
DRM_ERROR("Need resizing code.\n");
return -EINVAL;
}
 
switch (var->bits_per_pixel) {
case 16:
depth = (var->green.length == 6) ? 16 : 15;
break;
case 32:
depth = (var->transp.length > 0) ? 32 : 24;
break;
default:
depth = var->bits_per_pixel;
break;
}
 
switch (depth) {
case 8:
var->red.offset = 0;
var->green.offset = 0;
var->blue.offset = 0;
var->red.length = 8;
var->green.length = 8;
var->blue.length = 8;
var->transp.length = 0;
var->transp.offset = 0;
break;
case 15:
var->red.offset = 10;
var->green.offset = 5;
var->blue.offset = 0;
var->red.length = 5;
var->green.length = 5;
var->blue.length = 5;
var->transp.length = 1;
var->transp.offset = 15;
break;
case 16:
var->red.offset = 11;
var->green.offset = 5;
var->blue.offset = 0;
var->red.length = 5;
var->green.length = 6;
var->blue.length = 5;
var->transp.length = 0;
var->transp.offset = 0;
break;
case 24:
var->red.offset = 16;
var->green.offset = 8;
var->blue.offset = 0;
var->red.length = 8;
var->green.length = 8;
var->blue.length = 8;
var->transp.length = 0;
var->transp.offset = 0;
break;
case 32:
var->red.offset = 16;
var->green.offset = 8;
var->blue.offset = 0;
var->red.length = 8;
var->green.length = 8;
var->blue.length = 8;
var->transp.length = 8;
var->transp.offset = 24;
break;
default:
return -EINVAL;
}
return 0;
}
 
#endif
 
 
/* this will let fbcon do the mode init */
static int radeonfb_set_par(struct fb_info *info)
{
struct radeon_fb_device *rfbdev = info->par;
struct drm_device *dev = rfbdev->rdev->ddev;
struct fb_var_screeninfo *var = &info->var;
struct drm_crtc *crtc;
int ret;
int i;
 
if (var->pixclock != -1) {
DRM_ERROR("PIXEL CLCOK SET\n");
return -EINVAL;
}
 
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
 
for (i = 0; i < rfbdev->crtc_count; i++) {
if (crtc->base.id == rfbdev->crtc_ids[i]) {
break;
}
}
if (i == rfbdev->crtc_count) {
continue;
}
if (crtc->fb == radeon_crtc->mode_set.fb) {
// mutex_lock(&dev->mode_config.mutex);
ret = crtc->funcs->set_config(&radeon_crtc->mode_set);
// mutex_unlock(&dev->mode_config.mutex);
if (ret) {
return ret;
}
}
}
return 0;
}
 
#if 0
 
static int radeonfb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct radeon_fb_device *rfbdev = info->par;
struct drm_device *dev = rfbdev->rdev->ddev;
struct drm_mode_set *modeset;
struct drm_crtc *crtc;
struct radeon_crtc *radeon_crtc;
int ret = 0;
int i;
 
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
for (i = 0; i < rfbdev->crtc_count; i++) {
if (crtc->base.id == rfbdev->crtc_ids[i]) {
break;
}
}
 
if (i == rfbdev->crtc_count) {
continue;
}
 
radeon_crtc = to_radeon_crtc(crtc);
modeset = &radeon_crtc->mode_set;
 
modeset->x = var->xoffset;
modeset->y = var->yoffset;
 
if (modeset->num_connectors) {
mutex_lock(&dev->mode_config.mutex);
ret = crtc->funcs->set_config(modeset);
mutex_unlock(&dev->mode_config.mutex);
if (!ret) {
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
}
}
}
return ret;
}
 
static void radeonfb_on(struct fb_info *info)
{
struct radeon_fb_device *rfbdev = info->par;
struct drm_device *dev = rfbdev->rdev->ddev;
struct drm_crtc *crtc;
struct drm_encoder *encoder;
int i;
 
/*
* For each CRTC in this fb, find all associated encoders
* and turn them off, then turn off the CRTC.
*/
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 
for (i = 0; i < rfbdev->crtc_count; i++) {
if (crtc->base.id == rfbdev->crtc_ids[i]) {
break;
}
}
 
mutex_lock(&dev->mode_config.mutex);
crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
mutex_unlock(&dev->mode_config.mutex);
 
/* 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;
mutex_lock(&dev->mode_config.mutex);
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
mutex_unlock(&dev->mode_config.mutex);
}
}
}
}
 
static void radeonfb_off(struct fb_info *info, int dpms_mode)
{
struct radeon_fb_device *rfbdev = info->par;
struct drm_device *dev = rfbdev->rdev->ddev;
struct drm_crtc *crtc;
struct drm_encoder *encoder;
int i;
 
/*
* For each CRTC in this fb, find all associated encoders
* and turn them off, then turn off the CRTC.
*/
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 
for (i = 0; i < rfbdev->crtc_count; i++) {
if (crtc->base.id == rfbdev->crtc_ids[i]) {
break;
}
}
 
/* 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;
mutex_lock(&dev->mode_config.mutex);
encoder_funcs->dpms(encoder, dpms_mode);
mutex_unlock(&dev->mode_config.mutex);
}
}
if (dpms_mode == DRM_MODE_DPMS_OFF) {
mutex_lock(&dev->mode_config.mutex);
crtc_funcs->dpms(crtc, dpms_mode);
mutex_unlock(&dev->mode_config.mutex);
}
}
}
 
int radeonfb_blank(int blank, struct fb_info *info)
{
switch (blank) {
case FB_BLANK_UNBLANK:
radeonfb_on(info);
break;
case FB_BLANK_NORMAL:
radeonfb_off(info, DRM_MODE_DPMS_STANDBY);
break;
case FB_BLANK_HSYNC_SUSPEND:
radeonfb_off(info, DRM_MODE_DPMS_STANDBY);
break;
case FB_BLANK_VSYNC_SUSPEND:
radeonfb_off(info, DRM_MODE_DPMS_SUSPEND);
break;
case FB_BLANK_POWERDOWN:
radeonfb_off(info, DRM_MODE_DPMS_OFF);
break;
}
return 0;
}
 
static struct fb_ops radeonfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = radeonfb_check_var,
.fb_set_par = radeonfb_set_par,
.fb_setcolreg = radeonfb_setcolreg,
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
.fb_pan_display = radeonfb_pan_display,
.fb_blank = radeonfb_blank,
// .owner = THIS_MODULE,
.fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par,
.fb_setcolreg = drm_fb_helper_setcolreg,
// .fb_fillrect = cfb_fillrect,
// .fb_copyarea = cfb_copyarea,
// .fb_imageblit = cfb_imageblit,
// .fb_pan_display = drm_fb_helper_pan_display,
.fb_blank = drm_fb_helper_blank,
};
 
/**
640,26 → 102,10
}
EXPORT_SYMBOL(radeonfb_resize);
 
static struct drm_mode_set panic_mode;
 
int radeonfb_panic(struct notifier_block *n, unsigned long ununsed,
void *panic_str)
static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled)
{
DRM_ERROR("panic occurred, switching back to text console\n");
drm_crtc_helper_set_config(&panic_mode);
return 0;
}
EXPORT_SYMBOL(radeonfb_panic);
 
static struct notifier_block paniced = {
.notifier_call = radeonfb_panic,
};
#endif
 
static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp)
{
int aligned = width;
int align_large = (ASIC_IS_AVIVO(rdev));
int align_large = (ASIC_IS_AVIVO(rdev)) || tiled;
int pitch_mask = 0;
 
switch (bpp / 8) {
680,11 → 126,16
return aligned;
}
 
int radeonfb_create(struct radeon_device *rdev,
static struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
.gamma_set = radeon_crtc_fb_gamma_set,
};
 
int radeonfb_create(struct drm_device *dev,
uint32_t fb_width, uint32_t fb_height,
uint32_t surface_width, uint32_t surface_height,
struct radeon_framebuffer **rfb_p)
struct drm_framebuffer **fb_p)
{
struct radeon_device *rdev = dev->dev_private;
struct fb_info *info;
struct radeon_fb_device *rfbdev;
struct drm_framebuffer *fb = NULL;
697,15 → 148,15
u64 fb_gpuaddr;
void *fbptr = NULL;
unsigned long tmp;
bool fb_tiled = false; /* useful for testing */
u32 tiling_flags = 0;
 
ENTRY();
 
mode_cmd.width = surface_width;
mode_cmd.height = surface_height;
mode_cmd.bpp = 32;
/* need to align pitch with crtc limits */
mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp) * ((mode_cmd.bpp + 1) / 8);
mode_cmd.depth = 32;
mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8);
mode_cmd.depth = 24;
 
size = mode_cmd.pitch * mode_cmd.height;
aligned_size = ALIGN(size, PAGE_SIZE);
715,7 → 166,6
false, 0,
false, &gobj);
 
 
if (ret) {
printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n",
surface_width, surface_height);
724,7 → 174,7
}
robj = gobj->driver_private;
 
// mutex_lock(&rdev->ddev->struct_mutex);
mutex_lock(&rdev->ddev->struct_mutex);
fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj);
if (fb == NULL) {
DRM_ERROR("failed to allocate fb.\n");
740,8 → 190,8
 
list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list);
 
*fb_p = fb;
rfb = to_radeon_framebuffer(fb);
*rfb_p = rfb;
rdev->fbdev_rfb = rfb;
rdev->fbdev_robj = robj;
 
750,7 → 200,15
ret = -ENOMEM;
goto out_unref;
}
 
rdev->fbdev_info = info;
rfbdev = info->par;
rfbdev->helper.funcs = &radeon_fb_helper_funcs;
rfbdev->helper.dev = dev;
ret = drm_fb_helper_init_crtc_count(&rfbdev->helper, 2,
RADEONFB_CONN_LIMIT);
if (ret)
goto out_unref;
 
// ret = radeon_object_kmap(robj, &fbptr);
// if (ret) {
757,37 → 215,28
// goto out_unref;
// }
 
 
fbptr = (void*)0xFE000000; // LFB_BASE
 
strcpy(info->fix.id, "radeondrmfb");
 
strcpy(info->fix.id, "radeondrmfb");
info->fix.type = FB_TYPE_PACKED_PIXELS;
info->fix.visual = FB_VISUAL_TRUECOLOR;
info->fix.type_aux = 0;
info->fix.xpanstep = 1; /* doing it in hw */
info->fix.ypanstep = 1; /* doing it in hw */
info->fix.ywrapstep = 0;
// info->fix.accel = FB_ACCEL_NONE;
info->fix.type_aux = 0;
// info->flags = FBINFO_DEFAULT;
// info->fbops = &radeonfb_ops;
info->fix.line_length = fb->pitch;
drm_fb_helper_fill_fix(info, fb->pitch);
 
info->flags = FBINFO_DEFAULT;
info->fbops = &radeonfb_ops;
 
tmp = fb_gpuaddr - rdev->mc.vram_location;
info->fix.smem_start = rdev->mc.aper_base + tmp;
info->fix.smem_len = size;
info->screen_base = fbptr;
info->screen_size = size;
info->pseudo_palette = fb->pseudo_palette;
info->var.xres_virtual = fb->width;
info->var.yres_virtual = fb->height;
info->var.bits_per_pixel = fb->bits_per_pixel;
info->var.xoffset = 0;
info->var.yoffset = 0;
// info->var.activate = FB_ACTIVATE_NOW;
info->var.height = -1;
info->var.width = -1;
info->var.xres = fb_width;
info->var.yres = fb_height;
 
drm_fb_helper_fill_var(info, fb, fb_width, fb_height);
 
/* setup aperture base/size for vesafb takeover */
info->aperture_base = rdev->ddev->mode_config.fb_base;
info->aperture_size = rdev->mc.real_vram_size;
 
info->fix.mmio_start = 0;
info->fix.mmio_len = 0;
// info->pixmap.size = 64*1024;
805,60 → 254,6
DRM_INFO("fb depth is %d\n", fb->depth);
DRM_INFO(" pitch is %d\n", fb->pitch);
 
switch (fb->depth) {
case 8:
info->var.red.offset = 0;
info->var.green.offset = 0;
info->var.blue.offset = 0;
info->var.red.length = 8; /* 8bit DAC */
info->var.green.length = 8;
info->var.blue.length = 8;
info->var.transp.offset = 0;
info->var.transp.length = 0;
break;
case 15:
info->var.red.offset = 10;
info->var.green.offset = 5;
info->var.blue.offset = 0;
info->var.red.length = 5;
info->var.green.length = 5;
info->var.blue.length = 5;
info->var.transp.offset = 15;
info->var.transp.length = 1;
break;
case 16:
info->var.red.offset = 11;
info->var.green.offset = 5;
info->var.blue.offset = 0;
info->var.red.length = 5;
info->var.green.length = 6;
info->var.blue.length = 5;
info->var.transp.offset = 0;
break;
case 24:
info->var.red.offset = 16;
info->var.green.offset = 8;
info->var.blue.offset = 0;
info->var.red.length = 8;
info->var.green.length = 8;
info->var.blue.length = 8;
info->var.transp.offset = 0;
info->var.transp.length = 0;
break;
case 32:
info->var.red.offset = 16;
info->var.green.offset = 8;
info->var.blue.offset = 0;
info->var.red.length = 8;
info->var.green.length = 8;
info->var.blue.length = 8;
info->var.transp.offset = 24;
info->var.transp.length = 8;
break;
default:
break;
}
 
dbgprintf("fb = %x\n", fb);
 
fb->fbdev = info;
865,7 → 260,7
rfbdev->rfb = rfb;
rfbdev->rdev = rdev;
 
// mutex_unlock(&rdev->ddev->struct_mutex);
mutex_unlock(&rdev->ddev->struct_mutex);
return 0;
 
out_unref:
879,156 → 274,15
kfree(fb);
}
// drm_gem_object_unreference(gobj);
// mutex_unlock(&rdev->ddev->struct_mutex);
mutex_unlock(&rdev->ddev->struct_mutex);
out:
return ret;
}
 
static int radeonfb_single_fb_probe(struct radeon_device *rdev)
{
struct drm_crtc *crtc;
struct drm_connector *connector;
unsigned int fb_width = (unsigned)-1, fb_height = (unsigned)-1;
unsigned int surface_width = 0, surface_height = 0;
int new_fb = 0;
int crtc_count = 0;
int ret, i, conn_count = 0;
struct radeon_framebuffer *rfb;
struct fb_info *info;
struct radeon_fb_device *rfbdev;
struct drm_mode_set *modeset = NULL;
 
ENTRY();
 
/* first up get a count of crtcs now in use and new min/maxes width/heights */
list_for_each_entry(crtc, &rdev->ddev->mode_config.crtc_list, head) {
if (drm_helper_crtc_in_use(crtc)) {
if (crtc->desired_mode) {
if (crtc->desired_mode->hdisplay < fb_width)
fb_width = crtc->desired_mode->hdisplay;
 
if (crtc->desired_mode->vdisplay < fb_height)
fb_height = crtc->desired_mode->vdisplay;
 
if (crtc->desired_mode->hdisplay > surface_width)
surface_width = crtc->desired_mode->hdisplay;
 
if (crtc->desired_mode->vdisplay > surface_height)
surface_height = crtc->desired_mode->vdisplay;
}
crtc_count++;
}
}
 
if (crtc_count == 0 || fb_width == -1 || fb_height == -1) {
/* hmm everyone went away - assume VGA cable just fell out
and will come back later. */
 
dbgprintf("crtc count %x width %x height %x\n",
crtc_count, fb_width, fb_height);
return 0;
}
 
/* do we have an fb already? */
if (list_empty(&rdev->ddev->mode_config.fb_kernel_list)) {
/* create an fb if we don't have one */
ret = radeonfb_create(rdev, fb_width, fb_height, surface_width, surface_height, &rfb);
if (ret) {
return -EINVAL;
}
new_fb = 1;
} else {
struct drm_framebuffer *fb;
fb = list_first_entry(&rdev->ddev->mode_config.fb_kernel_list, struct drm_framebuffer, filp_head);
rfb = to_radeon_framebuffer(fb);
 
/* if someone hotplugs something bigger than we have already allocated, we are pwned.
As really we can't resize an fbdev that is in the wild currently due to fbdev
not really being designed for the lower layers moving stuff around under it.
- so in the grand style of things - punt. */
if ((fb->width < surface_width) || (fb->height < surface_height)) {
DRM_ERROR("Framebuffer not large enough to scale console onto.\n");
return -EINVAL;
}
}
 
info = rfb->base.fbdev;
rdev->fbdev_info = info;
rfbdev = info->par;
 
crtc_count = 0;
/* okay we need to setup new connector sets in the crtcs */
list_for_each_entry(crtc, &rdev->ddev->mode_config.crtc_list, head) {
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
modeset = &radeon_crtc->mode_set;
modeset->fb = &rfb->base;
conn_count = 0;
list_for_each_entry(connector, &rdev->ddev->mode_config.connector_list, head) {
if (connector->encoder)
if (connector->encoder->crtc == modeset->crtc) {
modeset->connectors[conn_count] = connector;
conn_count++;
if (conn_count > RADEONFB_CONN_LIMIT)
BUG();
}
}
 
for (i = conn_count; i < RADEONFB_CONN_LIMIT; i++)
modeset->connectors[i] = NULL;
 
 
rfbdev->crtc_ids[crtc_count++] = crtc->base.id;
 
modeset->num_connectors = conn_count;
if (modeset->crtc->desired_mode) {
if (modeset->mode) {
drm_mode_destroy(rdev->ddev, modeset->mode);
}
modeset->mode = drm_mode_duplicate(rdev->ddev,
modeset->crtc->desired_mode);
}
}
rfbdev->crtc_count = crtc_count;
 
if (new_fb) {
info->var.pixclock = -1;
// if (register_framebuffer(info) < 0)
// return -EINVAL;
} else {
radeonfb_set_par(info);
}
printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node,
info->fix.id);
 
/* Switch back to kernel console on panic */
// panic_mode = *modeset;
// atomic_notifier_chain_register(&panic_notifier_list, &paniced);
// printk(KERN_INFO "registered panic notifier\n");
LEAVE();
 
return 0;
}
 
int radeonfb_probe(struct drm_device *dev)
{
int ret;
 
/* something has changed in the lower levels of hell - deal with it
here */
 
/* two modes : a) 1 fb to rule all crtcs.
b) one fb per crtc.
two actions 1) new connected device
2) device removed.
case a/1 : if the fb surface isn't big enough - resize the surface fb.
if the fb size isn't big enough - resize fb into surface.
if everything big enough configure the new crtc/etc.
case a/2 : undo the configuration
possibly resize down the fb to fit the new configuration.
case b/1 : see if it is on a new crtc - setup a new fb and add it.
case b/2 : teardown the new fb.
*/
ret = radeonfb_single_fb_probe(dev->dev_private);
ret = drm_fb_helper_single_fb_probe(dev, &radeonfb_create);
return ret;
}
EXPORT_SYMBOL(radeonfb_probe);
1044,6 → 298,7
}
info = fb->fbdev;
if (info) {
struct radeon_fb_device *rfbdev = info->par;
robj = rfb->obj->driver_private;
// unregister_framebuffer(info);
// radeon_object_kunmap(robj);
1052,8 → 307,7
}
 
printk(KERN_INFO "unregistered panic notifier\n");
// atomic_notifier_chain_unregister(&panic_notifier_list, &paniced);
// memset(&panic_mode, 0, sizeof(struct drm_mode_set));
 
return 0;
}
EXPORT_SYMBOL(radeonfb_remove);
1192,8 → 446,6
 
bool ret;
 
ENTRY();
 
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
{
struct drm_display_mode *mode;
1244,17 → 496,17
 
fb->width = width;
fb->height = height;
fb->pitch = radeon_align_pitch(dev->dev_private, width, 32)
* ((32 + 1) / 8);
fb->pitch = radeon_align_pitch(dev->dev_private, width, 32, false) * ((32 + 1) / 8);
 
crtc->fb = fb;
 
ret = drm_crtc_helper_set_mode(crtc, mode, 0, 0, fb);
 
sysSetScreen(width,height);
sysSetScreen(width, height, fb->pitch);
 
if (ret == true)
{
dbgprintf("new mode %d %d pitch %d\n", width, height, fb->pitch);
}
else
{
/drivers/video/drm/radeon/radeon_fence.c
53,9 → 53,9
* away
*/
WREG32(rdev->fence_drv.scratch_reg, fence->seq);
} else {
} else
radeon_fence_ring_emit(rdev, fence);
}
 
fence->emited = true;
fence->timeout = jiffies + ((2000 * HZ) / 1000);
list_del(&fence->list);
168,9 → 168,40
return signaled;
}
 
int radeon_fence_wait(struct radeon_fence *fence, bool interruptible)
int r600_fence_wait(struct radeon_fence *fence, bool intr, bool lazy)
{
struct radeon_device *rdev;
int ret = 0;
 
rdev = fence->rdev;
 
__set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
 
while (1) {
if (radeon_fence_signaled(fence))
break;
 
if (time_after_eq(jiffies, fence->timeout)) {
ret = -EBUSY;
break;
}
 
if (lazy)
schedule_timeout(1);
 
if (intr && signal_pending(current)) {
ret = -ERESTARTSYS;
break;
}
}
__set_current_state(TASK_RUNNING);
return ret;
}
 
 
int radeon_fence_wait(struct radeon_fence *fence, bool intr)
{
struct radeon_device *rdev;
unsigned long cur_jiffies;
unsigned long timeout;
bool expired = false;
185,6 → 216,14
if (radeon_fence_signaled(fence)) {
return 0;
}
 
if (rdev->family >= CHIP_R600) {
r = r600_fence_wait(fence, intr, 0);
if (r == -ERESTARTSYS)
return -EBUSY;
return r;
}
 
retry:
cur_jiffies = jiffies;
timeout = HZ / 100;
191,11 → 230,11
if (time_after(fence->timeout, cur_jiffies)) {
timeout = fence->timeout - cur_jiffies;
}
if (interruptible) {
if (intr) {
r = wait_event_interruptible_timeout(rdev->fence_drv.queue,
radeon_fence_signaled(fence), timeout);
if (unlikely(r == -ERESTARTSYS)) {
return -ERESTART;
return -EBUSY;
}
} else {
r = wait_event_timeout(rdev->fence_drv.queue,
/drivers/video/drm/radeon/radeon_gart.c
75,10 → 75,9
 
int radeon_gart_table_vram_alloc(struct radeon_device *rdev)
{
uint32_t gpu_addr;
int r;
 
dbgprintf("%s\n",__FUNCTION__);
ENTER();
 
if (rdev->gart.table.vram.robj == NULL) {
r = radeon_object_create(rdev, NULL,
90,6 → 89,14
return r;
}
}
return 0;
}
 
int radeon_gart_table_vram_pin(struct radeon_device *rdev)
{
uint64_t gpu_addr;
int r;
 
r = radeon_object_pin(rdev->gart.table.vram.robj,
RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
if (r) {
175,7 → 182,8
uint64_t page_base;
int i, j;
 
dbgprintf("%s ",__FUNCTION__);
ENTER();
 
dbgprintf("offset %x pages %x list %x\n",
offset, pages, pagelist);
 
207,7 → 215,7
mb();
radeon_gart_tlb_flush(rdev);
 
dbgprintf("done %s\n",__FUNCTION__);
LEAVE();
 
return 0;
}
215,7 → 223,7
int radeon_gart_init(struct radeon_device *rdev)
{
 
dbgprintf("%s\n",__FUNCTION__);
ENTER();
 
if (rdev->gart.pages) {
return 0;
/drivers/video/drm/radeon/radeon_gem.c
182,9 → 182,9
struct radeon_device *rdev = dev->dev_private;
struct drm_radeon_gem_info *args = data;
 
args->vram_size = rdev->mc.vram_size;
args->vram_size = rdev->mc.real_vram_size;
/* FIXME: report somethings that makes sense */
args->vram_visible = rdev->mc.vram_size - (4 * 1024 * 1024);
args->vram_visible = rdev->mc.real_vram_size - (4 * 1024 * 1024);
args->gart_size = rdev->mc.gtt_size;
return 0;
}
/drivers/video/drm/radeon/radeon_legacy_crtc.c
23,12 → 23,178
* Authors: Dave Airlie
* Alex Deucher
*/
#include <drmP.h>
#include <drm_crtc_helper.h>
#include "radeon_drm.h"
#include <drm/drmP.h>
#include <drm/drm_crtc_helper.h>
#include <drm/radeon_drm.h>
#include "radeon_fixed.h"
#include "radeon.h"
#include "atom.h"
 
static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
int xres = mode->hdisplay;
int yres = mode->vdisplay;
bool hscale = true, vscale = true;
int hsync_wid;
int vsync_wid;
int hsync_start;
int blank_width;
u32 scale, inc, crtc_more_cntl;
u32 fp_horz_stretch, fp_vert_stretch, fp_horz_vert_active;
u32 fp_h_sync_strt_wid, fp_crtc_h_total_disp;
u32 fp_v_sync_strt_wid, fp_crtc_v_total_disp;
struct radeon_native_mode *native_mode = &radeon_crtc->native_mode;
 
fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) &
(RADEON_VERT_STRETCH_RESERVED |
RADEON_VERT_AUTO_RATIO_INC);
fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH) &
(RADEON_HORZ_FP_LOOP_STRETCH |
RADEON_HORZ_AUTO_RATIO_INC);
 
crtc_more_cntl = 0;
if ((rdev->family == CHIP_RS100) ||
(rdev->family == CHIP_RS200)) {
/* This is to workaround the asic bug for RMX, some versions
of BIOS dosen't have this register initialized correctly. */
crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN;
}
 
 
fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff)
| ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
 
hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
if (!hsync_wid)
hsync_wid = 1;
hsync_start = mode->crtc_hsync_start - 8;
 
fp_h_sync_strt_wid = ((hsync_start & 0x1fff)
| ((hsync_wid & 0x3f) << 16)
| ((mode->flags & DRM_MODE_FLAG_NHSYNC)
? RADEON_CRTC_H_SYNC_POL
: 0));
 
fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff)
| ((mode->crtc_vdisplay - 1) << 16));
 
vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
if (!vsync_wid)
vsync_wid = 1;
 
fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff)
| ((vsync_wid & 0x1f) << 16)
| ((mode->flags & DRM_MODE_FLAG_NVSYNC)
? RADEON_CRTC_V_SYNC_POL
: 0));
 
fp_horz_vert_active = 0;
 
if (native_mode->panel_xres == 0 ||
native_mode->panel_yres == 0) {
hscale = false;
vscale = false;
} else {
if (xres > native_mode->panel_xres)
xres = native_mode->panel_xres;
if (yres > native_mode->panel_yres)
yres = native_mode->panel_yres;
 
if (xres == native_mode->panel_xres)
hscale = false;
if (yres == native_mode->panel_yres)
vscale = false;
}
 
switch (radeon_crtc->rmx_type) {
case RMX_FULL:
case RMX_ASPECT:
if (!hscale)
fp_horz_stretch |= ((xres/8-1) << 16);
else {
inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0;
scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX)
/ native_mode->panel_xres + 1;
fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) |
RADEON_HORZ_STRETCH_BLEND |
RADEON_HORZ_STRETCH_ENABLE |
((native_mode->panel_xres/8-1) << 16));
}
 
if (!vscale)
fp_vert_stretch |= ((yres-1) << 12);
else {
inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0;
scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX)
/ native_mode->panel_yres + 1;
fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) |
RADEON_VERT_STRETCH_ENABLE |
RADEON_VERT_STRETCH_BLEND |
((native_mode->panel_yres-1) << 12));
}
break;
case RMX_CENTER:
fp_horz_stretch |= ((xres/8-1) << 16);
fp_vert_stretch |= ((yres-1) << 12);
 
crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN |
RADEON_CRTC_AUTO_VERT_CENTER_EN);
 
blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8;
if (blank_width > 110)
blank_width = 110;
 
fp_crtc_h_total_disp = (((blank_width) & 0x3ff)
| ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
 
hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
if (!hsync_wid)
hsync_wid = 1;
 
fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff)
| ((hsync_wid & 0x3f) << 16)
| ((mode->flags & DRM_MODE_FLAG_NHSYNC)
? RADEON_CRTC_H_SYNC_POL
: 0));
 
fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff)
| ((mode->crtc_vdisplay - 1) << 16));
 
vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
if (!vsync_wid)
vsync_wid = 1;
 
fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff)
| ((vsync_wid & 0x1f) << 16)
| ((mode->flags & DRM_MODE_FLAG_NVSYNC)
? RADEON_CRTC_V_SYNC_POL
: 0)));
 
fp_horz_vert_active = (((native_mode->panel_yres) & 0xfff) |
(((native_mode->panel_xres / 8) & 0x1ff) << 16));
break;
case RMX_OFF:
default:
fp_horz_stretch |= ((xres/8-1) << 16);
fp_vert_stretch |= ((yres-1) << 12);
break;
}
 
WREG32(RADEON_FP_HORZ_STRETCH, fp_horz_stretch);
WREG32(RADEON_FP_VERT_STRETCH, fp_vert_stretch);
WREG32(RADEON_CRTC_MORE_CNTL, crtc_more_cntl);
WREG32(RADEON_FP_HORZ_VERT_ACTIVE, fp_horz_vert_active);
WREG32(RADEON_FP_H_SYNC_STRT_WID, fp_h_sync_strt_wid);
WREG32(RADEON_FP_V_SYNC_STRT_WID, fp_v_sync_strt_wid);
WREG32(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp);
WREG32(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp);
}
 
void radeon_restore_common_regs(struct drm_device *dev)
{
/* don't need this yet */
145,10 → 311,13
RADEON_CRTC_DISP_REQ_EN_B));
WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask);
}
// drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
radeon_crtc_load_lut(crtc);
break;
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
// drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
if (radeon_crtc->crtc_id)
WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~mask);
else {
158,11 → 327,7
}
break;
}
 
if (mode != DRM_MODE_DPMS_OFF) {
radeon_crtc_load_lut(crtc);
}
}
 
/* properly set crtc bpp when using atombios */
void radeon_legacy_atom_set_surface(struct drm_crtc *crtc)
176,6 → 341,9
uint32_t crtc_pitch;
 
switch (crtc->fb->bits_per_pixel) {
case 8:
format = 2;
break;
case 15: /* 555 */
format = 3;
break;
235,16 → 403,44
uint64_t base;
uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0;
uint32_t crtc_pitch, pitch_pixels;
uint32_t tiling_flags;
int format;
uint32_t gen_cntl_reg, gen_cntl_val;
 
DRM_DEBUG("\n");
 
radeon_fb = to_radeon_framebuffer(crtc->fb);
 
switch (crtc->fb->bits_per_pixel) {
case 8:
format = 2;
break;
case 15: /* 555 */
format = 3;
break;
case 16: /* 565 */
format = 4;
break;
case 24: /* RGB */
format = 5;
break;
case 32: /* xRGB */
format = 6;
break;
default:
return false;
}
 
obj = radeon_fb->obj;
// if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &base)) {
// return -EINVAL;
// }
crtc_offset = (u32)base;
/* if scanout was in GTT this really wouldn't work */
/* crtc offset is from display base addr not FB location */
radeon_crtc->legacy_display_base_addr = rdev->mc.vram_location;
 
base -= radeon_crtc->legacy_display_base_addr;
 
crtc_offset_cntl = 0;
 
pitch_pixels = crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8);
253,8 → 449,12
(crtc->fb->bits_per_pixel * 8));
crtc_pitch |= crtc_pitch << 16;
 
/* TODO tiling */
if (0) {
// radeon_object_get_tiling_flags(obj->driver_private,
// &tiling_flags, NULL);
if (tiling_flags & RADEON_TILING_MICRO)
DRM_ERROR("trying to scanout microtiled buffer\n");
 
if (tiling_flags & RADEON_TILING_MACRO) {
if (ASIC_IS_R300(rdev))
crtc_offset_cntl |= (R300_CRTC_X_Y_MODE_EN |
R300_CRTC_MICRO_TILE_BUFFER_DIS |
270,15 → 470,13
crtc_offset_cntl &= ~RADEON_CRTC_TILE_EN;
}
 
 
/* TODO more tiling */
if (0) {
if (tiling_flags & RADEON_TILING_MACRO) {
if (ASIC_IS_R300(rdev)) {
crtc_tile_x0_y0 = x | (y << 16);
base &= ~0x7ff;
} else {
int byteshift = crtc->fb->bits_per_pixel >> 4;
int tile_addr = (((y >> 3) * crtc->fb->width + x) >> (8 - byteshift)) << 11;
int tile_addr = (((y >> 3) * pitch_pixels + x) >> (8 - byteshift)) << 11;
base += tile_addr + ((x << byteshift) % 256) + ((y % 8) << 8);
crtc_offset_cntl |= (y % 16);
}
285,6 → 483,9
} else {
int offset = y * pitch_pixels + x;
switch (crtc->fb->bits_per_pixel) {
case 8:
offset *= 1;
break;
case 15:
case 16:
offset *= 2;
303,11 → 504,19
 
base &= ~7;
 
/* update sarea TODO */
if (radeon_crtc->crtc_id == 1)
gen_cntl_reg = RADEON_CRTC2_GEN_CNTL;
else
gen_cntl_reg = RADEON_CRTC_GEN_CNTL;
 
gen_cntl_val = RREG32(gen_cntl_reg);
gen_cntl_val &= ~(0xf << 8);
gen_cntl_val |= (format << 8);
WREG32(gen_cntl_reg, gen_cntl_val);
 
crtc_offset = (u32)base;
 
WREG32(RADEON_DISPLAY_BASE_ADDR + radeon_crtc->crtc_offset, rdev->mc.vram_location);
WREG32(RADEON_DISPLAY_BASE_ADDR + radeon_crtc->crtc_offset, radeon_crtc->legacy_display_base_addr);
 
if (ASIC_IS_R300(rdev)) {
if (radeon_crtc->crtc_id)
331,6 → 540,7
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_encoder *encoder;
int format;
int hsync_start;
int hsync_wid;
339,10 → 549,24
uint32_t crtc_h_sync_strt_wid;
uint32_t crtc_v_total_disp;
uint32_t crtc_v_sync_strt_wid;
bool is_tv = false;
 
DRM_DEBUG("\n");
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (encoder->crtc == crtc) {
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
is_tv = true;
DRM_INFO("crtc %d is connected to a TV\n", radeon_crtc->crtc_id);
break;
}
}
}
 
switch (crtc->fb->bits_per_pixel) {
case 8:
format = 2;
break;
case 15: /* 555 */
format = 3;
break;
472,6 → 696,11
WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
}
 
if (is_tv)
radeon_legacy_tv_adjust_crtc_reg(encoder, &crtc_h_total_disp,
&crtc_h_sync_strt_wid, &crtc_v_total_disp,
&crtc_v_sync_strt_wid);
 
WREG32(RADEON_CRTC_H_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_h_total_disp);
WREG32(RADEON_CRTC_H_SYNC_STRT_WID + radeon_crtc->crtc_offset, crtc_h_sync_strt_wid);
WREG32(RADEON_CRTC_V_TOTAL_DISP + radeon_crtc->crtc_offset, crtc_v_total_disp);
498,7 → 727,7
uint32_t pll_ref_div = 0;
uint32_t pll_fb_post_div = 0;
uint32_t htotal_cntl = 0;
 
bool is_tv = false;
struct radeon_pll *pll;
 
struct {
533,6 → 762,13
 
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (encoder->crtc == crtc) {
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 
if (radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT) {
is_tv = true;
break;
}
 
if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
596,6 → 832,12
~(RADEON_PIX2CLK_SRC_SEL_MASK)) |
RADEON_PIX2CLK_SRC_SEL_P2PLLCLK);
 
if (is_tv) {
radeon_legacy_tv_adjust_pll2(encoder, &htotal_cntl,
&pll_ref_div, &pll_fb_post_div,
&pixclks_cntl);
}
 
WREG32_PLL_P(RADEON_PIXCLKS_CNTL,
RADEON_PIX2CLK_SRC_SEL_CPUCLK,
~(RADEON_PIX2CLK_SRC_SEL_MASK));
650,6 → 892,15
 
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
} else {
uint32_t pixclks_cntl;
 
 
if (is_tv) {
pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
radeon_legacy_tv_adjust_pll1(encoder, &htotal_cntl, &pll_ref_div,
&pll_fb_post_div, &pixclks_cntl);
}
 
if (rdev->flags & RADEON_IS_MOBILITY) {
/* A temporal workaround for the occational blanking on certain laptop panels.
This appears to related to the PLL divider registers (fail to lock?).
744,6 → 995,8
RADEON_VCLK_SRC_SEL_PPLLCLK,
~(RADEON_VCLK_SRC_SEL_MASK));
 
if (is_tv)
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
}
}
 
751,6 → 1004,8
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
return false;
return true;
}
 
759,16 → 1014,25
struct drm_display_mode *adjusted_mode,
int x, int y, struct drm_framebuffer *old_fb)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
 
DRM_DEBUG("\n");
 
/* TODO TV */
 
radeon_crtc_set_base(crtc, x, y, old_fb);
radeon_set_crtc_timing(crtc, adjusted_mode);
radeon_set_pll(crtc, adjusted_mode);
radeon_init_disp_bandwidth(crtc->dev);
 
radeon_bandwidth_update(rdev);
if (radeon_crtc->crtc_id == 0) {
radeon_legacy_rmx_mode_set(crtc, mode, adjusted_mode);
} else {
if (radeon_crtc->rmx_type != RMX_OFF) {
/* FIXME: only first crtc has rmx what should we
* do ?
*/
DRM_ERROR("Mode need scaling but only first crtc can do that.\n");
}
}
return 0;
}
 
799,478 → 1063,3
radeon_crtc->crtc_offset = RADEON_CRTC2_H_TOTAL_DISP - RADEON_CRTC_H_TOTAL_DISP;
drm_crtc_helper_add(&radeon_crtc->base, &legacy_helper_funcs);
}
 
void radeon_init_disp_bw_legacy(struct drm_device *dev,
struct drm_display_mode *mode1,
uint32_t pixel_bytes1,
struct drm_display_mode *mode2,
uint32_t pixel_bytes2)
{
struct radeon_device *rdev = dev->dev_private;
fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff;
fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff;
fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff;
uint32_t temp, data, mem_trcd, mem_trp, mem_tras;
fixed20_12 memtcas_ff[8] = {
fixed_init(1),
fixed_init(2),
fixed_init(3),
fixed_init(0),
fixed_init_half(1),
fixed_init_half(2),
fixed_init(0),
};
fixed20_12 memtcas_rs480_ff[8] = {
fixed_init(0),
fixed_init(1),
fixed_init(2),
fixed_init(3),
fixed_init(0),
fixed_init_half(1),
fixed_init_half(2),
fixed_init_half(3),
};
fixed20_12 memtcas2_ff[8] = {
fixed_init(0),
fixed_init(1),
fixed_init(2),
fixed_init(3),
fixed_init(4),
fixed_init(5),
fixed_init(6),
fixed_init(7),
};
fixed20_12 memtrbs[8] = {
fixed_init(1),
fixed_init_half(1),
fixed_init(2),
fixed_init_half(2),
fixed_init(3),
fixed_init_half(3),
fixed_init(4),
fixed_init_half(4)
};
fixed20_12 memtrbs_r4xx[8] = {
fixed_init(4),
fixed_init(5),
fixed_init(6),
fixed_init(7),
fixed_init(8),
fixed_init(9),
fixed_init(10),
fixed_init(11)
};
fixed20_12 min_mem_eff;
fixed20_12 mc_latency_sclk, mc_latency_mclk, k1;
fixed20_12 cur_latency_mclk, cur_latency_sclk;
fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate,
disp_drain_rate2, read_return_rate;
fixed20_12 time_disp1_drop_priority;
int c;
int cur_size = 16; /* in octawords */
int critical_point = 0, critical_point2;
/* uint32_t read_return_rate, time_disp1_drop_priority; */
int stop_req, max_stop_req;
 
min_mem_eff.full = rfixed_const_8(0);
/* get modes */
if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) {
uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER);
mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT);
mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT);
/* check crtc enables */
if (mode2)
mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT);
if (mode1)
mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT);
WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer);
}
 
/*
* determine is there is enough bw for current mode
*/
mclk_ff.full = rfixed_const(rdev->clock.default_mclk);
temp_ff.full = rfixed_const(100);
mclk_ff.full = rfixed_div(mclk_ff, temp_ff);
sclk_ff.full = rfixed_const(rdev->clock.default_sclk);
sclk_ff.full = rfixed_div(sclk_ff, temp_ff);
 
temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1);
temp_ff.full = rfixed_const(temp);
mem_bw.full = rfixed_mul(mclk_ff, temp_ff);
 
pix_clk.full = 0;
pix_clk2.full = 0;
peak_disp_bw.full = 0;
if (mode1) {
temp_ff.full = rfixed_const(1000);
pix_clk.full = rfixed_const(mode1->clock); /* convert to fixed point */
pix_clk.full = rfixed_div(pix_clk, temp_ff);
temp_ff.full = rfixed_const(pixel_bytes1);
peak_disp_bw.full += rfixed_mul(pix_clk, temp_ff);
}
if (mode2) {
temp_ff.full = rfixed_const(1000);
pix_clk2.full = rfixed_const(mode2->clock); /* convert to fixed point */
pix_clk2.full = rfixed_div(pix_clk2, temp_ff);
temp_ff.full = rfixed_const(pixel_bytes2);
peak_disp_bw.full += rfixed_mul(pix_clk2, temp_ff);
}
 
mem_bw.full = rfixed_mul(mem_bw, min_mem_eff);
if (peak_disp_bw.full >= mem_bw.full) {
DRM_ERROR("You may not have enough display bandwidth for current mode\n"
"If you have flickering problem, try to lower resolution, refresh rate, or color depth\n");
}
 
/* Get values from the EXT_MEM_CNTL register...converting its contents. */
temp = RREG32(RADEON_MEM_TIMING_CNTL);
if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */
mem_trcd = ((temp >> 2) & 0x3) + 1;
mem_trp = ((temp & 0x3)) + 1;
mem_tras = ((temp & 0x70) >> 4) + 1;
} else if (rdev->family == CHIP_R300 ||
rdev->family == CHIP_R350) { /* r300, r350 */
mem_trcd = (temp & 0x7) + 1;
mem_trp = ((temp >> 8) & 0x7) + 1;
mem_tras = ((temp >> 11) & 0xf) + 4;
} else if (rdev->family == CHIP_RV350 ||
rdev->family <= CHIP_RV380) {
/* rv3x0 */
mem_trcd = (temp & 0x7) + 3;
mem_trp = ((temp >> 8) & 0x7) + 3;
mem_tras = ((temp >> 11) & 0xf) + 6;
} else if (rdev->family == CHIP_R420 ||
rdev->family == CHIP_R423 ||
rdev->family == CHIP_RV410) {
/* r4xx */
mem_trcd = (temp & 0xf) + 3;
if (mem_trcd > 15)
mem_trcd = 15;
mem_trp = ((temp >> 8) & 0xf) + 3;
if (mem_trp > 15)
mem_trp = 15;
mem_tras = ((temp >> 12) & 0x1f) + 6;
if (mem_tras > 31)
mem_tras = 31;
} else { /* RV200, R200 */
mem_trcd = (temp & 0x7) + 1;
mem_trp = ((temp >> 8) & 0x7) + 1;
mem_tras = ((temp >> 12) & 0xf) + 4;
}
/* convert to FF */
trcd_ff.full = rfixed_const(mem_trcd);
trp_ff.full = rfixed_const(mem_trp);
tras_ff.full = rfixed_const(mem_tras);
 
/* Get values from the MEM_SDRAM_MODE_REG register...converting its */
temp = RREG32(RADEON_MEM_SDRAM_MODE_REG);
data = (temp & (7 << 20)) >> 20;
if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) {
if (rdev->family == CHIP_RS480) /* don't think rs400 */
tcas_ff = memtcas_rs480_ff[data];
else
tcas_ff = memtcas_ff[data];
} else
tcas_ff = memtcas2_ff[data];
 
if (rdev->family == CHIP_RS400 ||
rdev->family == CHIP_RS480) {
/* extra cas latency stored in bits 23-25 0-4 clocks */
data = (temp >> 23) & 0x7;
if (data < 5)
tcas_ff.full += rfixed_const(data);
}
 
if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) {
/* on the R300, Tcas is included in Trbs.
*/
temp = RREG32(RADEON_MEM_CNTL);
data = (R300_MEM_NUM_CHANNELS_MASK & temp);
if (data == 1) {
if (R300_MEM_USE_CD_CH_ONLY & temp) {
temp = RREG32(R300_MC_IND_INDEX);
temp &= ~R300_MC_IND_ADDR_MASK;
temp |= R300_MC_READ_CNTL_CD_mcind;
WREG32(R300_MC_IND_INDEX, temp);
temp = RREG32(R300_MC_IND_DATA);
data = (R300_MEM_RBS_POSITION_C_MASK & temp);
} else {
temp = RREG32(R300_MC_READ_CNTL_AB);
data = (R300_MEM_RBS_POSITION_A_MASK & temp);
}
} else {
temp = RREG32(R300_MC_READ_CNTL_AB);
data = (R300_MEM_RBS_POSITION_A_MASK & temp);
}
if (rdev->family == CHIP_RV410 ||
rdev->family == CHIP_R420 ||
rdev->family == CHIP_R423)
trbs_ff = memtrbs_r4xx[data];
else
trbs_ff = memtrbs[data];
tcas_ff.full += trbs_ff.full;
}
 
sclk_eff_ff.full = sclk_ff.full;
 
// if (rdev->flags & RADEON_IS_AGP) {
// fixed20_12 agpmode_ff;
// agpmode_ff.full = rfixed_const(radeon_agpmode);
// temp_ff.full = rfixed_const_666(16);
// sclk_eff_ff.full -= rfixed_mul(agpmode_ff, temp_ff);
// }
/* TODO PCIE lanes may affect this - agpmode == 16?? */
 
if (ASIC_IS_R300(rdev)) {
sclk_delay_ff.full = rfixed_const(250);
} else {
if ((rdev->family == CHIP_RV100) ||
rdev->flags & RADEON_IS_IGP) {
if (rdev->mc.vram_is_ddr)
sclk_delay_ff.full = rfixed_const(41);
else
sclk_delay_ff.full = rfixed_const(33);
} else {
if (rdev->mc.vram_width == 128)
sclk_delay_ff.full = rfixed_const(57);
else
sclk_delay_ff.full = rfixed_const(41);
}
}
 
mc_latency_sclk.full = rfixed_div(sclk_delay_ff, sclk_eff_ff);
 
if (rdev->mc.vram_is_ddr) {
if (rdev->mc.vram_width == 32) {
k1.full = rfixed_const(40);
c = 3;
} else {
k1.full = rfixed_const(20);
c = 1;
}
} else {
k1.full = rfixed_const(40);
c = 3;
}
 
temp_ff.full = rfixed_const(2);
mc_latency_mclk.full = rfixed_mul(trcd_ff, temp_ff);
temp_ff.full = rfixed_const(c);
mc_latency_mclk.full += rfixed_mul(tcas_ff, temp_ff);
temp_ff.full = rfixed_const(4);
mc_latency_mclk.full += rfixed_mul(tras_ff, temp_ff);
mc_latency_mclk.full += rfixed_mul(trp_ff, temp_ff);
mc_latency_mclk.full += k1.full;
 
mc_latency_mclk.full = rfixed_div(mc_latency_mclk, mclk_ff);
mc_latency_mclk.full += rfixed_div(temp_ff, sclk_eff_ff);
 
/*
HW cursor time assuming worst case of full size colour cursor.
*/
temp_ff.full = rfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1))));
temp_ff.full += trcd_ff.full;
if (temp_ff.full < tras_ff.full)
temp_ff.full = tras_ff.full;
cur_latency_mclk.full = rfixed_div(temp_ff, mclk_ff);
 
temp_ff.full = rfixed_const(cur_size);
cur_latency_sclk.full = rfixed_div(temp_ff, sclk_eff_ff);
/*
Find the total latency for the display data.
*/
disp_latency_overhead.full = rfixed_const(80);
disp_latency_overhead.full = rfixed_div(disp_latency_overhead, sclk_ff);
mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full;
mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full;
 
if (mc_latency_mclk.full > mc_latency_sclk.full)
disp_latency.full = mc_latency_mclk.full;
else
disp_latency.full = mc_latency_sclk.full;
 
/* setup Max GRPH_STOP_REQ default value */
if (ASIC_IS_RV100(rdev))
max_stop_req = 0x5c;
else
max_stop_req = 0x7c;
 
if (mode1) {
/* CRTC1
Set GRPH_BUFFER_CNTL register using h/w defined optimal values.
GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ]
*/
stop_req = mode1->hdisplay * pixel_bytes1 / 16;
 
if (stop_req > max_stop_req)
stop_req = max_stop_req;
 
/*
Find the drain rate of the display buffer.
*/
temp_ff.full = rfixed_const((16/pixel_bytes1));
disp_drain_rate.full = rfixed_div(pix_clk, temp_ff);
 
/*
Find the critical point of the display buffer.
*/
crit_point_ff.full = rfixed_mul(disp_drain_rate, disp_latency);
crit_point_ff.full += rfixed_const_half(0);
 
critical_point = rfixed_trunc(crit_point_ff);
 
if (rdev->disp_priority == 2) {
critical_point = 0;
}
 
/*
The critical point should never be above max_stop_req-4. Setting
GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time.
*/
if (max_stop_req - critical_point < 4)
critical_point = 0;
 
if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) {
/* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/
critical_point = 0x10;
}
 
temp = RREG32(RADEON_GRPH_BUFFER_CNTL);
temp &= ~(RADEON_GRPH_STOP_REQ_MASK);
temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
temp &= ~(RADEON_GRPH_START_REQ_MASK);
if ((rdev->family == CHIP_R350) &&
(stop_req > 0x15)) {
stop_req -= 0x10;
}
temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
temp |= RADEON_GRPH_BUFFER_SIZE;
temp &= ~(RADEON_GRPH_CRITICAL_CNTL |
RADEON_GRPH_CRITICAL_AT_SOF |
RADEON_GRPH_STOP_CNTL);
/*
Write the result into the register.
*/
WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
(critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
 
#if 0
if ((rdev->family == CHIP_RS400) ||
(rdev->family == CHIP_RS480)) {
/* attempt to program RS400 disp regs correctly ??? */
temp = RREG32(RS400_DISP1_REG_CNTL);
temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK |
RS400_DISP1_STOP_REQ_LEVEL_MASK);
WREG32(RS400_DISP1_REQ_CNTL1, (temp |
(critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) |
(critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT)));
temp = RREG32(RS400_DMIF_MEM_CNTL1);
temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK |
RS400_DISP1_CRITICAL_POINT_STOP_MASK);
WREG32(RS400_DMIF_MEM_CNTL1, (temp |
(critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) |
(critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT)));
}
#endif
 
DRM_DEBUG("GRPH_BUFFER_CNTL from to %x\n",
/* (unsigned int)info->SavedReg->grph_buffer_cntl, */
(unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL));
}
 
if (mode2) {
u32 grph2_cntl;
stop_req = mode2->hdisplay * pixel_bytes2 / 16;
 
if (stop_req > max_stop_req)
stop_req = max_stop_req;
 
/*
Find the drain rate of the display buffer.
*/
temp_ff.full = rfixed_const((16/pixel_bytes2));
disp_drain_rate2.full = rfixed_div(pix_clk2, temp_ff);
 
grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL);
grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK);
grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT);
grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK);
if ((rdev->family == CHIP_R350) &&
(stop_req > 0x15)) {
stop_req -= 0x10;
}
grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT);
grph2_cntl |= RADEON_GRPH_BUFFER_SIZE;
grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL |
RADEON_GRPH_CRITICAL_AT_SOF |
RADEON_GRPH_STOP_CNTL);
 
if ((rdev->family == CHIP_RS100) ||
(rdev->family == CHIP_RS200))
critical_point2 = 0;
else {
temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128;
temp_ff.full = rfixed_const(temp);
temp_ff.full = rfixed_mul(mclk_ff, temp_ff);
if (sclk_ff.full < temp_ff.full)
temp_ff.full = sclk_ff.full;
 
read_return_rate.full = temp_ff.full;
 
if (mode1) {
temp_ff.full = read_return_rate.full - disp_drain_rate.full;
time_disp1_drop_priority.full = rfixed_div(crit_point_ff, temp_ff);
} else {
time_disp1_drop_priority.full = 0;
}
crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full;
crit_point_ff.full = rfixed_mul(crit_point_ff, disp_drain_rate2);
crit_point_ff.full += rfixed_const_half(0);
 
critical_point2 = rfixed_trunc(crit_point_ff);
 
if (rdev->disp_priority == 2) {
critical_point2 = 0;
}
 
if (max_stop_req - critical_point2 < 4)
critical_point2 = 0;
 
}
 
if (critical_point2 == 0 && rdev->family == CHIP_R300) {
/* some R300 cards have problem with this set to 0 */
critical_point2 = 0x10;
}
 
WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) |
(critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT)));
 
if ((rdev->family == CHIP_RS400) ||
(rdev->family == CHIP_RS480)) {
#if 0
/* attempt to program RS400 disp2 regs correctly ??? */
temp = RREG32(RS400_DISP2_REQ_CNTL1);
temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK |
RS400_DISP2_STOP_REQ_LEVEL_MASK);
WREG32(RS400_DISP2_REQ_CNTL1, (temp |
(critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) |
(critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT)));
temp = RREG32(RS400_DISP2_REQ_CNTL2);
temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK |
RS400_DISP2_CRITICAL_POINT_STOP_MASK);
WREG32(RS400_DISP2_REQ_CNTL2, (temp |
(critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) |
(critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT)));
#endif
WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC);
WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000);
WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC);
WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC);
}
 
DRM_DEBUG("GRPH2_BUFFER_CNTL from to %x\n",
(unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL));
}
}
/drivers/video/drm/radeon/radeon_legacy_encoders.c
29,171 → 29,16
#include "radeon.h"
#include "atom.h"
 
 
static void radeon_legacy_rmx_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
int xres = mode->hdisplay;
int yres = mode->vdisplay;
bool hscale = true, vscale = true;
int hsync_wid;
int vsync_wid;
int hsync_start;
uint32_t scale, inc;
uint32_t fp_horz_stretch, fp_vert_stretch, crtc_more_cntl, fp_horz_vert_active;
uint32_t fp_h_sync_strt_wid, fp_v_sync_strt_wid, fp_crtc_h_total_disp, fp_crtc_v_total_disp;
struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
struct drm_encoder_helper_funcs *encoder_funcs;
 
DRM_DEBUG("\n");
 
fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) &
(RADEON_VERT_STRETCH_RESERVED |
RADEON_VERT_AUTO_RATIO_INC);
fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH) &
(RADEON_HORZ_FP_LOOP_STRETCH |
RADEON_HORZ_AUTO_RATIO_INC);
 
crtc_more_cntl = 0;
if ((rdev->family == CHIP_RS100) ||
(rdev->family == CHIP_RS200)) {
/* This is to workaround the asic bug for RMX, some versions
of BIOS dosen't have this register initialized correctly. */
crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN;
encoder_funcs = encoder->helper_private;
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
radeon_encoder->active_device = 0;
}
 
 
fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff)
| ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
 
hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
if (!hsync_wid)
hsync_wid = 1;
hsync_start = mode->crtc_hsync_start - 8;
 
fp_h_sync_strt_wid = ((hsync_start & 0x1fff)
| ((hsync_wid & 0x3f) << 16)
| ((mode->flags & DRM_MODE_FLAG_NHSYNC)
? RADEON_CRTC_H_SYNC_POL
: 0));
 
fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff)
| ((mode->crtc_vdisplay - 1) << 16));
 
vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
if (!vsync_wid)
vsync_wid = 1;
 
fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff)
| ((vsync_wid & 0x1f) << 16)
| ((mode->flags & DRM_MODE_FLAG_NVSYNC)
? RADEON_CRTC_V_SYNC_POL
: 0));
 
fp_horz_vert_active = 0;
 
if (native_mode->panel_xres == 0 ||
native_mode->panel_yres == 0) {
hscale = false;
vscale = false;
} else {
if (xres > native_mode->panel_xres)
xres = native_mode->panel_xres;
if (yres > native_mode->panel_yres)
yres = native_mode->panel_yres;
 
if (xres == native_mode->panel_xres)
hscale = false;
if (yres == native_mode->panel_yres)
vscale = false;
}
 
if (radeon_encoder->flags & RADEON_USE_RMX) {
if (radeon_encoder->rmx_type != RMX_CENTER) {
if (!hscale)
fp_horz_stretch |= ((xres/8-1) << 16);
else {
inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0;
scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX)
/ native_mode->panel_xres + 1;
fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) |
RADEON_HORZ_STRETCH_BLEND |
RADEON_HORZ_STRETCH_ENABLE |
((native_mode->panel_xres/8-1) << 16));
}
 
if (!vscale)
fp_vert_stretch |= ((yres-1) << 12);
else {
inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0;
scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX)
/ native_mode->panel_yres + 1;
fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) |
RADEON_VERT_STRETCH_ENABLE |
RADEON_VERT_STRETCH_BLEND |
((native_mode->panel_yres-1) << 12));
}
} else if (radeon_encoder->rmx_type == RMX_CENTER) {
int blank_width;
 
fp_horz_stretch |= ((xres/8-1) << 16);
fp_vert_stretch |= ((yres-1) << 12);
 
crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN |
RADEON_CRTC_AUTO_VERT_CENTER_EN);
 
blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8;
if (blank_width > 110)
blank_width = 110;
 
fp_crtc_h_total_disp = (((blank_width) & 0x3ff)
| ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
 
hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
if (!hsync_wid)
hsync_wid = 1;
 
fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff)
| ((hsync_wid & 0x3f) << 16)
| ((mode->flags & DRM_MODE_FLAG_NHSYNC)
? RADEON_CRTC_H_SYNC_POL
: 0));
 
fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff)
| ((mode->crtc_vdisplay - 1) << 16));
 
vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
if (!vsync_wid)
vsync_wid = 1;
 
fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff)
| ((vsync_wid & 0x1f) << 16)
| ((mode->flags & DRM_MODE_FLAG_NVSYNC)
? RADEON_CRTC_V_SYNC_POL
: 0)));
 
fp_horz_vert_active = (((native_mode->panel_yres) & 0xfff) |
(((native_mode->panel_xres / 8) & 0x1ff) << 16));
}
} else {
fp_horz_stretch |= ((xres/8-1) << 16);
fp_vert_stretch |= ((yres-1) << 12);
}
 
WREG32(RADEON_FP_HORZ_STRETCH, fp_horz_stretch);
WREG32(RADEON_FP_VERT_STRETCH, fp_vert_stretch);
WREG32(RADEON_CRTC_MORE_CNTL, crtc_more_cntl);
WREG32(RADEON_FP_HORZ_VERT_ACTIVE, fp_horz_vert_active);
WREG32(RADEON_FP_H_SYNC_STRT_WID, fp_h_sync_strt_wid);
WREG32(RADEON_FP_V_SYNC_STRT_WID, fp_v_sync_strt_wid);
WREG32(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp);
WREG32(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp);
 
}
 
static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
262,6 → 107,8
else
radeon_combios_output_lock(encoder, true);
radeon_legacy_lvds_dpms(encoder, DRM_MODE_DPMS_OFF);
 
radeon_encoder_set_active_device(encoder);
}
 
static void radeon_legacy_lvds_commit(struct drm_encoder *encoder)
287,9 → 134,6
 
DRM_DEBUG("\n");
 
if (radeon_crtc->crtc_id == 0)
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
 
lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN;
 
318,7 → 162,7
 
if (radeon_crtc->crtc_id == 0) {
if (ASIC_IS_R300(rdev)) {
if (radeon_encoder->flags & RADEON_USE_RMX)
if (radeon_encoder->rmx_type != RMX_OFF)
lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX;
} else
lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2;
350,8 → 194,6
 
drm_mode_set_crtcinfo(adjusted_mode, 0);
 
radeon_encoder->flags &= ~RADEON_USE_RMX;
 
if (radeon_encoder->rmx_type != RMX_OFF)
radeon_rmx_mode_fixup(encoder, mode, adjusted_mode);
 
364,6 → 206,7
.prepare = radeon_legacy_lvds_prepare,
.mode_set = radeon_legacy_lvds_mode_set,
.commit = radeon_legacy_lvds_commit,
.disable = radeon_legacy_encoder_disable,
};
 
 
429,6 → 272,7
else
radeon_combios_output_lock(encoder, true);
radeon_legacy_primary_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
radeon_encoder_set_active_device(encoder);
}
 
static void radeon_legacy_primary_dac_commit(struct drm_encoder *encoder)
455,9 → 299,6
 
DRM_DEBUG("\n");
 
if (radeon_crtc->crtc_id == 0)
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
 
if (radeon_crtc->crtc_id == 0) {
if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) {
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) &
574,6 → 415,7
.mode_set = radeon_legacy_primary_dac_mode_set,
.commit = radeon_legacy_primary_dac_commit,
.detect = radeon_legacy_primary_dac_detect,
.disable = radeon_legacy_encoder_disable,
};
 
 
626,6 → 468,7
else
radeon_combios_output_lock(encoder, true);
radeon_legacy_tmds_int_dpms(encoder, DRM_MODE_DPMS_OFF);
radeon_encoder_set_active_device(encoder);
}
 
static void radeon_legacy_tmds_int_commit(struct drm_encoder *encoder)
653,9 → 496,6
 
DRM_DEBUG("\n");
 
if (radeon_crtc->crtc_id == 0)
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
 
tmp = tmds_pll_cntl = RREG32(RADEON_TMDS_PLL_CNTL);
tmp &= 0xfffff;
if (rdev->family == CHIP_RV280) {
711,7 → 551,7
if (radeon_crtc->crtc_id == 0) {
if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) {
fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
if (radeon_encoder->flags & RADEON_USE_RMX)
if (radeon_encoder->rmx_type != RMX_OFF)
fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
else
fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
741,6 → 581,7
.prepare = radeon_legacy_tmds_int_prepare,
.mode_set = radeon_legacy_tmds_int_mode_set,
.commit = radeon_legacy_tmds_int_commit,
.disable = radeon_legacy_encoder_disable,
};
 
 
795,6 → 636,7
else
radeon_combios_output_lock(encoder, true);
radeon_legacy_tmds_ext_dpms(encoder, DRM_MODE_DPMS_OFF);
radeon_encoder_set_active_device(encoder);
}
 
static void radeon_legacy_tmds_ext_commit(struct drm_encoder *encoder)
820,9 → 662,6
 
DRM_DEBUG("\n");
 
if (radeon_crtc->crtc_id == 0)
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
 
if (rdev->is_atom_bios) {
radeon_encoder->pixel_clock = adjusted_mode->clock;
atombios_external_tmds_setup(encoder, ATOM_ENABLE);
856,7 → 695,7
if (radeon_crtc->crtc_id == 0) {
if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) {
fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
if (radeon_encoder->flags & RADEON_USE_RMX)
if (radeon_encoder->rmx_type != RMX_OFF)
fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX;
else
fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1;
884,6 → 723,7
.prepare = radeon_legacy_tmds_ext_prepare,
.mode_set = radeon_legacy_tmds_ext_mode_set,
.commit = radeon_legacy_tmds_ext_commit,
.disable = radeon_legacy_encoder_disable,
};
 
 
905,17 → 745,21
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
uint32_t fp2_gen_cntl = 0, crtc2_gen_cntl = 0, tv_dac_cntl = 0;
/* uint32_t tv_master_cntl = 0; */
 
uint32_t tv_master_cntl = 0;
bool is_tv;
DRM_DEBUG("\n");
 
is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false;
 
if (rdev->family == CHIP_R200)
fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
else {
if (is_tv)
tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL);
else
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
/* FIXME TV */
/* tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL); */
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
}
 
924,8 → 768,11
if (rdev->family == CHIP_R200) {
fp2_gen_cntl |= (RADEON_FP2_ON | RADEON_FP2_DVO_EN);
} else {
if (is_tv)
tv_master_cntl |= RADEON_TV_ON;
else
crtc2_gen_cntl |= RADEON_CRTC2_CRT2_ON;
/* tv_master_cntl |= RADEON_TV_ON; */
 
if (rdev->family == CHIP_R420 ||
rdev->family == CHIP_R423 ||
rdev->family == CHIP_RV410)
946,8 → 793,11
if (rdev->family == CHIP_R200)
fp2_gen_cntl &= ~(RADEON_FP2_ON | RADEON_FP2_DVO_EN);
else {
if (is_tv)
tv_master_cntl &= ~RADEON_TV_ON;
else
crtc2_gen_cntl &= ~RADEON_CRTC2_CRT2_ON;
/* tv_master_cntl &= ~RADEON_TV_ON; */
 
if (rdev->family == CHIP_R420 ||
rdev->family == CHIP_R423 ||
rdev->family == CHIP_RV410)
967,8 → 817,10
if (rdev->family == CHIP_R200) {
WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
} else {
if (is_tv)
WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
else
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
/* WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); */
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
}
 
987,6 → 839,7
else
radeon_combios_output_lock(encoder, true);
radeon_legacy_tv_dac_dpms(encoder, DRM_MODE_DPMS_OFF);
radeon_encoder_set_active_device(encoder);
}
 
static void radeon_legacy_tv_dac_commit(struct drm_encoder *encoder)
1009,13 → 862,14
struct radeon_device *rdev = dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
uint32_t tv_dac_cntl, gpiopad_a = 0, dac2_cntl, disp_output_cntl = 0;
uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0;
uint32_t disp_hw_debug = 0, fp2_gen_cntl = 0, disp_tv_out_cntl = 0;
bool is_tv = false;
 
DRM_DEBUG("\n");
 
if (radeon_crtc->crtc_id == 0)
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
is_tv = radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT ? true : false;
 
if (rdev->family != CHIP_R200) {
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
1039,7 → 893,7
}
 
/* FIXME TV */
if (radeon_encoder->enc_priv) {
if (tv_dac) {
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
tv_dac_cntl |= (RADEON_TV_DAC_NBLANK |
RADEON_TV_DAC_NHOLD |
1056,11 → 910,52
if (ASIC_IS_R300(rdev)) {
gpiopad_a = RREG32(RADEON_GPIOPAD_A) | 1;
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
} else if (rdev->family == CHIP_R200)
fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
}
 
if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev))
disp_tv_out_cntl = RREG32(RADEON_DISP_TV_OUT_CNTL);
else
disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
 
if (rdev->family == CHIP_R200)
fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
 
if (is_tv) {
uint32_t dac_cntl;
 
dac_cntl = RREG32(RADEON_DAC_CNTL);
dac_cntl &= ~RADEON_DAC_TVO_EN;
WREG32(RADEON_DAC_CNTL, dac_cntl);
 
if (ASIC_IS_R300(rdev))
gpiopad_a = RREG32(RADEON_GPIOPAD_A) & ~1;
 
dac2_cntl = RREG32(RADEON_DAC_CNTL2) & ~RADEON_DAC2_DAC2_CLK_SEL;
if (radeon_crtc->crtc_id == 0) {
if (ASIC_IS_R300(rdev)) {
disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
disp_output_cntl |= (RADEON_DISP_TVDAC_SOURCE_CRTC |
RADEON_DISP_TV_SOURCE_CRTC);
}
if (rdev->family >= CHIP_R200) {
disp_tv_out_cntl &= ~RADEON_DISP_TV_PATH_SRC_CRTC2;
} else {
disp_hw_debug |= RADEON_CRT2_DISP1_SEL;
}
} else {
if (ASIC_IS_R300(rdev)) {
disp_output_cntl &= ~RADEON_DISP_TVDAC_SOURCE_MASK;
disp_output_cntl |= RADEON_DISP_TV_SOURCE_CRTC;
}
if (rdev->family >= CHIP_R200) {
disp_tv_out_cntl |= RADEON_DISP_TV_PATH_SRC_CRTC2;
} else {
disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
}
}
WREG32(RADEON_DAC_CNTL2, dac2_cntl);
} else {
 
dac2_cntl = RREG32(RADEON_DAC_CNTL2) | RADEON_DAC2_DAC2_CLK_SEL;
 
if (radeon_crtc->crtc_id == 0) {
1083,17 → 978,25
} else
disp_hw_debug &= ~RADEON_CRT2_DISP1_SEL;
}
 
WREG32(RADEON_DAC_CNTL2, dac2_cntl);
}
 
if (ASIC_IS_R300(rdev)) {
WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
WREG32(RADEON_DISP_TV_OUT_CNTL, disp_output_cntl);
} else if (rdev->family == CHIP_R200)
WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
}
 
if (rdev->family >= CHIP_R200)
WREG32(RADEON_DISP_TV_OUT_CNTL, disp_tv_out_cntl);
else
WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
 
if (rdev->family == CHIP_R200)
WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
 
if (is_tv)
radeon_legacy_tv_mode_set(encoder, mode, adjusted_mode);
 
if (rdev->is_atom_bios)
radeon_atombios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
else
1101,6 → 1004,141
 
}
 
static bool r300_legacy_tv_detect(struct drm_encoder *encoder,
struct drm_connector *connector)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
uint32_t disp_output_cntl, gpiopad_a, tmp;
bool found = false;
 
/* save regs needed */
gpiopad_a = RREG32(RADEON_GPIOPAD_A);
dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
 
WREG32_P(RADEON_GPIOPAD_A, 0, ~1);
 
WREG32(RADEON_DAC_CNTL2, RADEON_DAC2_DAC2_CLK_SEL);
 
WREG32(RADEON_CRTC2_GEN_CNTL,
RADEON_CRTC2_CRT2_ON | RADEON_CRTC2_VSYNC_TRISTAT);
 
tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
 
WREG32(RADEON_DAC_EXT_CNTL,
RADEON_DAC2_FORCE_BLANK_OFF_EN |
RADEON_DAC2_FORCE_DATA_EN |
RADEON_DAC_FORCE_DATA_SEL_RGB |
(0xec << RADEON_DAC_FORCE_DATA_SHIFT));
 
WREG32(RADEON_TV_DAC_CNTL,
RADEON_TV_DAC_STD_NTSC |
(8 << RADEON_TV_DAC_BGADJ_SHIFT) |
(6 << RADEON_TV_DAC_DACADJ_SHIFT));
 
RREG32(RADEON_TV_DAC_CNTL);
mdelay(4);
 
WREG32(RADEON_TV_DAC_CNTL,
RADEON_TV_DAC_NBLANK |
RADEON_TV_DAC_NHOLD |
RADEON_TV_MONITOR_DETECT_EN |
RADEON_TV_DAC_STD_NTSC |
(8 << RADEON_TV_DAC_BGADJ_SHIFT) |
(6 << RADEON_TV_DAC_DACADJ_SHIFT));
 
RREG32(RADEON_TV_DAC_CNTL);
mdelay(6);
 
tmp = RREG32(RADEON_TV_DAC_CNTL);
if ((tmp & RADEON_TV_DAC_GDACDET) != 0) {
found = true;
DRM_DEBUG("S-video TV connection detected\n");
} else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) {
found = true;
DRM_DEBUG("Composite TV connection detected\n");
}
 
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
WREG32(RADEON_DAC_CNTL2, dac_cntl2);
WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
return found;
}
 
static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,
struct drm_connector *connector)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
uint32_t tv_dac_cntl, dac_cntl2;
uint32_t config_cntl, tv_pre_dac_mux_cntl, tv_master_cntl, tmp;
bool found = false;
 
if (ASIC_IS_R300(rdev))
return r300_legacy_tv_detect(encoder, connector);
 
dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
tv_master_cntl = RREG32(RADEON_TV_MASTER_CNTL);
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
config_cntl = RREG32(RADEON_CONFIG_CNTL);
tv_pre_dac_mux_cntl = RREG32(RADEON_TV_PRE_DAC_MUX_CNTL);
 
tmp = dac_cntl2 & ~RADEON_DAC2_DAC2_CLK_SEL;
WREG32(RADEON_DAC_CNTL2, tmp);
 
tmp = tv_master_cntl | RADEON_TV_ON;
tmp &= ~(RADEON_TV_ASYNC_RST |
RADEON_RESTART_PHASE_FIX |
RADEON_CRT_FIFO_CE_EN |
RADEON_TV_FIFO_CE_EN |
RADEON_RE_SYNC_NOW_SEL_MASK);
tmp |= RADEON_TV_FIFO_ASYNC_RST | RADEON_CRT_ASYNC_RST;
WREG32(RADEON_TV_MASTER_CNTL, tmp);
 
tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD |
RADEON_TV_MONITOR_DETECT_EN | RADEON_TV_DAC_STD_NTSC |
(8 << RADEON_TV_DAC_BGADJ_SHIFT);
 
if (config_cntl & RADEON_CFG_ATI_REV_ID_MASK)
tmp |= (4 << RADEON_TV_DAC_DACADJ_SHIFT);
else
tmp |= (8 << RADEON_TV_DAC_DACADJ_SHIFT);
WREG32(RADEON_TV_DAC_CNTL, tmp);
 
tmp = RADEON_C_GRN_EN | RADEON_CMP_BLU_EN |
RADEON_RED_MX_FORCE_DAC_DATA |
RADEON_GRN_MX_FORCE_DAC_DATA |
RADEON_BLU_MX_FORCE_DAC_DATA |
(0x109 << RADEON_TV_FORCE_DAC_DATA_SHIFT);
WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tmp);
 
mdelay(3);
tmp = RREG32(RADEON_TV_DAC_CNTL);
if (tmp & RADEON_TV_DAC_GDACDET) {
found = true;
DRM_DEBUG("S-video TV connection detected\n");
} else if ((tmp & RADEON_TV_DAC_BDACDET) != 0) {
found = true;
DRM_DEBUG("Composite TV connection detected\n");
}
 
WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, tv_pre_dac_mux_cntl);
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
WREG32(RADEON_DAC_CNTL2, dac_cntl2);
return found;
}
 
static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
struct drm_connector *connector)
{
1109,10 → 1147,30
uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
enum drm_connector_status found = connector_status_disconnected;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
bool color = true;
 
/* FIXME tv */
if (connector->connector_type == DRM_MODE_CONNECTOR_SVIDEO ||
connector->connector_type == DRM_MODE_CONNECTOR_Composite ||
connector->connector_type == DRM_MODE_CONNECTOR_9PinDIN) {
bool tv_detect;
 
if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_TV_SUPPORT))
return connector_status_disconnected;
 
tv_detect = radeon_legacy_tv_detect(encoder, connector);
if (tv_detect && tv_dac)
found = connector_status_connected;
return found;
}
 
/* don't probe if the encoder is being used for something else not CRT related */
if (radeon_encoder->active_device && !(radeon_encoder->active_device & ATOM_DEVICE_CRT_SUPPORT)) {
DRM_INFO("not detecting due to %08x\n", radeon_encoder->active_device);
return connector_status_disconnected;
}
 
/* save the regs we need */
pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0;
1194,8 → 1252,7
}
WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
 
/* return found; */
return connector_status_disconnected;
return found;
 
}
 
1206,6 → 1263,7
.mode_set = radeon_legacy_tv_dac_mode_set,
.commit = radeon_legacy_tv_dac_commit,
.detect = radeon_legacy_tv_dac_detect,
.disable = radeon_legacy_encoder_disable,
};
 
 
1213,6 → 1271,30
.destroy = radeon_enc_destroy,
};
 
 
static struct radeon_encoder_int_tmds *radeon_legacy_get_tmds_info(struct radeon_encoder *encoder)
{
struct drm_device *dev = encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder_int_tmds *tmds = NULL;
bool ret;
 
tmds = kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
 
if (!tmds)
return NULL;
 
if (rdev->is_atom_bios)
ret = radeon_atombios_get_tmds_info(encoder, tmds);
else
ret = radeon_legacy_get_tmds_info_from_combios(encoder, tmds);
 
if (ret == false)
radeon_legacy_get_tmds_info_from_table(encoder, tmds);
 
return tmds;
}
 
void
radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device)
{
1243,9 → 1325,11
 
radeon_encoder->encoder_id = encoder_id;
radeon_encoder->devices = supported_device;
radeon_encoder->rmx_type = RMX_OFF;
 
switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_LVDS:
encoder->possible_crtcs = 0x1;
drm_encoder_init(dev, encoder, &radeon_legacy_lvds_enc_funcs, DRM_MODE_ENCODER_LVDS);
drm_encoder_helper_add(encoder, &radeon_legacy_lvds_helper_funcs);
if (rdev->is_atom_bios)
1257,10 → 1341,7
case ENCODER_OBJECT_ID_INTERNAL_TMDS1:
drm_encoder_init(dev, encoder, &radeon_legacy_tmds_int_enc_funcs, DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(encoder, &radeon_legacy_tmds_int_helper_funcs);
if (rdev->is_atom_bios)
radeon_encoder->enc_priv = radeon_atombios_get_tmds_info(radeon_encoder);
else
radeon_encoder->enc_priv = radeon_combios_get_tmds_info(radeon_encoder);
radeon_encoder->enc_priv = radeon_legacy_get_tmds_info(radeon_encoder);
break;
case ENCODER_OBJECT_ID_INTERNAL_DAC1:
drm_encoder_init(dev, encoder, &radeon_legacy_primary_dac_enc_funcs, DRM_MODE_ENCODER_DAC);
/drivers/video/drm/radeon/radeon_legacy_tv.c
0,0 → 1,904
#include "drmP.h"
#include "drm_crtc_helper.h"
#include "radeon.h"
 
/*
* Integrated TV out support based on the GATOS code by
* Federico Ulivi <fulivi@lycos.com>
*/
 
 
/*
* Limits of h/v positions (hPos & vPos)
*/
#define MAX_H_POSITION 5 /* Range: [-5..5], negative is on the left, 0 is default, positive is on the right */
#define MAX_V_POSITION 5 /* Range: [-5..5], negative is up, 0 is default, positive is down */
 
/*
* Unit for hPos (in TV clock periods)
*/
#define H_POS_UNIT 10
 
/*
* Indexes in h. code timing table for horizontal line position adjustment
*/
#define H_TABLE_POS1 6
#define H_TABLE_POS2 8
 
/*
* Limits of hor. size (hSize)
*/
#define MAX_H_SIZE 5 /* Range: [-5..5], negative is smaller, positive is larger */
 
/* tv standard constants */
#define NTSC_TV_CLOCK_T 233
#define NTSC_TV_VFTOTAL 1
#define NTSC_TV_LINES_PER_FRAME 525
#define NTSC_TV_ZERO_H_SIZE 479166
#define NTSC_TV_H_SIZE_UNIT 9478
 
#define PAL_TV_CLOCK_T 188
#define PAL_TV_VFTOTAL 3
#define PAL_TV_LINES_PER_FRAME 625
#define PAL_TV_ZERO_H_SIZE 473200
#define PAL_TV_H_SIZE_UNIT 9360
 
/* tv pll setting for 27 mhz ref clk */
#define NTSC_TV_PLL_M_27 22
#define NTSC_TV_PLL_N_27 175
#define NTSC_TV_PLL_P_27 5
 
#define PAL_TV_PLL_M_27 113
#define PAL_TV_PLL_N_27 668
#define PAL_TV_PLL_P_27 3
 
/* tv pll setting for 14 mhz ref clk */
#define NTSC_TV_PLL_M_14 33
#define NTSC_TV_PLL_N_14 693
#define NTSC_TV_PLL_P_14 7
 
#define VERT_LEAD_IN_LINES 2
#define FRAC_BITS 0xe
#define FRAC_MASK 0x3fff
 
struct radeon_tv_mode_constants {
uint16_t hor_resolution;
uint16_t ver_resolution;
enum radeon_tv_std standard;
uint16_t hor_total;
uint16_t ver_total;
uint16_t hor_start;
uint16_t hor_syncstart;
uint16_t ver_syncstart;
unsigned def_restart;
uint16_t crtcPLL_N;
uint8_t crtcPLL_M;
uint8_t crtcPLL_post_div;
unsigned pix_to_tv;
};
 
static const uint16_t hor_timing_NTSC[] = {
0x0007,
0x003f,
0x0263,
0x0a24,
0x2a6b,
0x0a36,
0x126d, /* H_TABLE_POS1 */
0x1bfe,
0x1a8f, /* H_TABLE_POS2 */
0x1ec7,
0x3863,
0x1bfe,
0x1bfe,
0x1a2a,
0x1e95,
0x0e31,
0x201b,
0
};
 
static const uint16_t vert_timing_NTSC[] = {
0x2001,
0x200d,
0x1006,
0x0c06,
0x1006,
0x1818,
0x21e3,
0x1006,
0x0c06,
0x1006,
0x1817,
0x21d4,
0x0002,
0
};
 
static const uint16_t hor_timing_PAL[] = {
0x0007,
0x0058,
0x027c,
0x0a31,
0x2a77,
0x0a95,
0x124f, /* H_TABLE_POS1 */
0x1bfe,
0x1b22, /* H_TABLE_POS2 */
0x1ef9,
0x387c,
0x1bfe,
0x1bfe,
0x1b31,
0x1eb5,
0x0e43,
0x201b,
0
};
 
static const uint16_t vert_timing_PAL[] = {
0x2001,
0x200c,
0x1005,
0x0c05,
0x1005,
0x1401,
0x1821,
0x2240,
0x1005,
0x0c05,
0x1005,
0x1401,
0x1822,
0x2230,
0x0002,
0
};
 
/**********************************************************************
*
* availableModes
*
* Table of all allowed modes for tv output
*
**********************************************************************/
static const struct radeon_tv_mode_constants available_tv_modes[] = {
{ /* NTSC timing for 27 Mhz ref clk */
800, /* horResolution */
600, /* verResolution */
TV_STD_NTSC, /* standard */
990, /* horTotal */
740, /* verTotal */
813, /* horStart */
824, /* horSyncStart */
632, /* verSyncStart */
625592, /* defRestart */
592, /* crtcPLL_N */
91, /* crtcPLL_M */
4, /* crtcPLL_postDiv */
1022, /* pixToTV */
},
{ /* PAL timing for 27 Mhz ref clk */
800, /* horResolution */
600, /* verResolution */
TV_STD_PAL, /* standard */
1144, /* horTotal */
706, /* verTotal */
812, /* horStart */
824, /* horSyncStart */
669, /* verSyncStart */
696700, /* defRestart */
1382, /* crtcPLL_N */
231, /* crtcPLL_M */
4, /* crtcPLL_postDiv */
759, /* pixToTV */
},
{ /* NTSC timing for 14 Mhz ref clk */
800, /* horResolution */
600, /* verResolution */
TV_STD_NTSC, /* standard */
1018, /* horTotal */
727, /* verTotal */
813, /* horStart */
840, /* horSyncStart */
633, /* verSyncStart */
630627, /* defRestart */
347, /* crtcPLL_N */
14, /* crtcPLL_M */
8, /* crtcPLL_postDiv */
1022, /* pixToTV */
},
};
 
#define N_AVAILABLE_MODES ARRAY_SIZE(available_tv_modes)
 
static const struct radeon_tv_mode_constants *radeon_legacy_tv_get_std_mode(struct radeon_encoder *radeon_encoder,
uint16_t *pll_ref_freq)
{
struct drm_device *dev = radeon_encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_crtc *radeon_crtc;
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
const struct radeon_tv_mode_constants *const_ptr;
struct radeon_pll *pll;
 
radeon_crtc = to_radeon_crtc(radeon_encoder->base.crtc);
if (radeon_crtc->crtc_id == 1)
pll = &rdev->clock.p2pll;
else
pll = &rdev->clock.p1pll;
 
if (pll_ref_freq)
*pll_ref_freq = pll->reference_freq;
 
if (tv_dac->tv_std == TV_STD_NTSC ||
tv_dac->tv_std == TV_STD_NTSC_J ||
tv_dac->tv_std == TV_STD_PAL_M) {
if (pll->reference_freq == 2700)
const_ptr = &available_tv_modes[0];
else
const_ptr = &available_tv_modes[2];
} else {
if (pll->reference_freq == 2700)
const_ptr = &available_tv_modes[1];
else
const_ptr = &available_tv_modes[1]; /* FIX ME */
}
return const_ptr;
}
 
static long YCOEF_value[5] = { 2, 2, 0, 4, 0 };
static long YCOEF_EN_value[5] = { 1, 1, 0, 1, 0 };
static long SLOPE_value[5] = { 1, 2, 2, 4, 8 };
static long SLOPE_limit[5] = { 6, 5, 4, 3, 2 };
 
static void radeon_wait_pll_lock(struct drm_encoder *encoder, unsigned n_tests,
unsigned n_wait_loops, unsigned cnt_threshold)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
uint32_t save_pll_test;
unsigned int i, j;
 
WREG32(RADEON_TEST_DEBUG_MUX, (RREG32(RADEON_TEST_DEBUG_MUX) & 0xffff60ff) | 0x100);
save_pll_test = RREG32_PLL(RADEON_PLL_TEST_CNTL);
WREG32_PLL(RADEON_PLL_TEST_CNTL, save_pll_test & ~RADEON_PLL_MASK_READ_B);
 
WREG8(RADEON_CLOCK_CNTL_INDEX, RADEON_PLL_TEST_CNTL);
for (i = 0; i < n_tests; i++) {
WREG8(RADEON_CLOCK_CNTL_DATA + 3, 0);
for (j = 0; j < n_wait_loops; j++)
if (RREG8(RADEON_CLOCK_CNTL_DATA + 3) >= cnt_threshold)
break;
}
WREG32_PLL(RADEON_PLL_TEST_CNTL, save_pll_test);
WREG32(RADEON_TEST_DEBUG_MUX, RREG32(RADEON_TEST_DEBUG_MUX) & 0xffffe0ff);
}
 
 
static void radeon_legacy_tv_write_fifo(struct radeon_encoder *radeon_encoder,
uint16_t addr, uint32_t value)
{
struct drm_device *dev = radeon_encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
uint32_t tmp;
int i = 0;
 
WREG32(RADEON_TV_HOST_WRITE_DATA, value);
 
WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr);
WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_WT);
 
do {
tmp = RREG32(RADEON_TV_HOST_RD_WT_CNTL);
if ((tmp & RADEON_HOST_FIFO_WT_ACK) == 0)
break;
i++;
} while (i < 10000);
WREG32(RADEON_TV_HOST_RD_WT_CNTL, 0);
}
 
#if 0 /* included for completeness */
static uint32_t radeon_legacy_tv_read_fifo(struct radeon_encoder *radeon_encoder, uint16_t addr)
{
struct drm_device *dev = radeon_encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
uint32_t tmp;
int i = 0;
 
WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr);
WREG32(RADEON_TV_HOST_RD_WT_CNTL, addr | RADEON_HOST_FIFO_RD);
 
do {
tmp = RREG32(RADEON_TV_HOST_RD_WT_CNTL);
if ((tmp & RADEON_HOST_FIFO_RD_ACK) == 0)
break;
i++;
} while (i < 10000);
WREG32(RADEON_TV_HOST_RD_WT_CNTL, 0);
return RREG32(RADEON_TV_HOST_READ_DATA);
}
#endif
 
static uint16_t radeon_get_htiming_tables_addr(uint32_t tv_uv_adr)
{
uint16_t h_table;
 
switch ((tv_uv_adr & RADEON_HCODE_TABLE_SEL_MASK) >> RADEON_HCODE_TABLE_SEL_SHIFT) {
case 0:
h_table = RADEON_TV_MAX_FIFO_ADDR_INTERNAL;
break;
case 1:
h_table = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2;
break;
case 2:
h_table = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2;
break;
default:
h_table = 0;
break;
}
return h_table;
}
 
static uint16_t radeon_get_vtiming_tables_addr(uint32_t tv_uv_adr)
{
uint16_t v_table;
 
switch ((tv_uv_adr & RADEON_VCODE_TABLE_SEL_MASK) >> RADEON_VCODE_TABLE_SEL_SHIFT) {
case 0:
v_table = ((tv_uv_adr & RADEON_MAX_UV_ADR_MASK) >> RADEON_MAX_UV_ADR_SHIFT) * 2 + 1;
break;
case 1:
v_table = ((tv_uv_adr & RADEON_TABLE1_BOT_ADR_MASK) >> RADEON_TABLE1_BOT_ADR_SHIFT) * 2 + 1;
break;
case 2:
v_table = ((tv_uv_adr & RADEON_TABLE3_TOP_ADR_MASK) >> RADEON_TABLE3_TOP_ADR_SHIFT) * 2 + 1;
break;
default:
v_table = 0;
break;
}
return v_table;
}
 
static void radeon_restore_tv_timing_tables(struct radeon_encoder *radeon_encoder)
{
struct drm_device *dev = radeon_encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
uint16_t h_table, v_table;
uint32_t tmp;
int i;
 
WREG32(RADEON_TV_UV_ADR, tv_dac->tv.tv_uv_adr);
h_table = radeon_get_htiming_tables_addr(tv_dac->tv.tv_uv_adr);
v_table = radeon_get_vtiming_tables_addr(tv_dac->tv.tv_uv_adr);
 
for (i = 0; i < MAX_H_CODE_TIMING_LEN; i += 2, h_table--) {
tmp = ((uint32_t)tv_dac->tv.h_code_timing[i] << 14) | ((uint32_t)tv_dac->tv.h_code_timing[i+1]);
radeon_legacy_tv_write_fifo(radeon_encoder, h_table, tmp);
if (tv_dac->tv.h_code_timing[i] == 0 || tv_dac->tv.h_code_timing[i + 1] == 0)
break;
}
for (i = 0; i < MAX_V_CODE_TIMING_LEN; i += 2, v_table++) {
tmp = ((uint32_t)tv_dac->tv.v_code_timing[i+1] << 14) | ((uint32_t)tv_dac->tv.v_code_timing[i]);
radeon_legacy_tv_write_fifo(radeon_encoder, v_table, tmp);
if (tv_dac->tv.v_code_timing[i] == 0 || tv_dac->tv.v_code_timing[i + 1] == 0)
break;
}
}
 
static void radeon_legacy_write_tv_restarts(struct radeon_encoder *radeon_encoder)
{
struct drm_device *dev = radeon_encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
WREG32(RADEON_TV_FRESTART, tv_dac->tv.frestart);
WREG32(RADEON_TV_HRESTART, tv_dac->tv.hrestart);
WREG32(RADEON_TV_VRESTART, tv_dac->tv.vrestart);
}
 
static bool radeon_legacy_tv_init_restarts(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
struct radeon_crtc *radeon_crtc;
int restart;
unsigned int h_total, v_total, f_total;
int v_offset, h_offset;
u16 p1, p2, h_inc;
bool h_changed;
const struct radeon_tv_mode_constants *const_ptr;
struct radeon_pll *pll;
 
radeon_crtc = to_radeon_crtc(radeon_encoder->base.crtc);
if (radeon_crtc->crtc_id == 1)
pll = &rdev->clock.p2pll;
else
pll = &rdev->clock.p1pll;
 
const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
if (!const_ptr)
return false;
 
h_total = const_ptr->hor_total;
v_total = const_ptr->ver_total;
 
if (tv_dac->tv_std == TV_STD_NTSC ||
tv_dac->tv_std == TV_STD_NTSC_J ||
tv_dac->tv_std == TV_STD_PAL_M ||
tv_dac->tv_std == TV_STD_PAL_60)
f_total = NTSC_TV_VFTOTAL + 1;
else
f_total = PAL_TV_VFTOTAL + 1;
 
/* adjust positions 1&2 in hor. cod timing table */
h_offset = tv_dac->h_pos * H_POS_UNIT;
 
if (tv_dac->tv_std == TV_STD_NTSC ||
tv_dac->tv_std == TV_STD_NTSC_J ||
tv_dac->tv_std == TV_STD_PAL_M) {
h_offset -= 50;
p1 = hor_timing_NTSC[H_TABLE_POS1];
p2 = hor_timing_NTSC[H_TABLE_POS2];
} else {
p1 = hor_timing_PAL[H_TABLE_POS1];
p2 = hor_timing_PAL[H_TABLE_POS2];
}
 
p1 = (u16)((int)p1 + h_offset);
p2 = (u16)((int)p2 - h_offset);
 
h_changed = (p1 != tv_dac->tv.h_code_timing[H_TABLE_POS1] ||
p2 != tv_dac->tv.h_code_timing[H_TABLE_POS2]);
 
tv_dac->tv.h_code_timing[H_TABLE_POS1] = p1;
tv_dac->tv.h_code_timing[H_TABLE_POS2] = p2;
 
/* Convert hOffset from n. of TV clock periods to n. of CRTC clock periods (CRTC pixels) */
h_offset = (h_offset * (int)(const_ptr->pix_to_tv)) / 1000;
 
/* adjust restart */
restart = const_ptr->def_restart;
 
/*
* convert v_pos TV lines to n. of CRTC pixels
*/
if (tv_dac->tv_std == TV_STD_NTSC ||
tv_dac->tv_std == TV_STD_NTSC_J ||
tv_dac->tv_std == TV_STD_PAL_M ||
tv_dac->tv_std == TV_STD_PAL_60)
v_offset = ((int)(v_total * h_total) * 2 * tv_dac->v_pos) / (int)(NTSC_TV_LINES_PER_FRAME);
else
v_offset = ((int)(v_total * h_total) * 2 * tv_dac->v_pos) / (int)(PAL_TV_LINES_PER_FRAME);
 
restart -= v_offset + h_offset;
 
DRM_DEBUG("compute_restarts: def = %u h = %d v = %d, p1 = %04x, p2 = %04x, restart = %d\n",
const_ptr->def_restart, tv_dac->h_pos, tv_dac->v_pos, p1, p2, restart);
 
tv_dac->tv.hrestart = restart % h_total;
restart /= h_total;
tv_dac->tv.vrestart = restart % v_total;
restart /= v_total;
tv_dac->tv.frestart = restart % f_total;
 
DRM_DEBUG("compute_restart: F/H/V=%u,%u,%u\n",
(unsigned)tv_dac->tv.frestart,
(unsigned)tv_dac->tv.vrestart,
(unsigned)tv_dac->tv.hrestart);
 
/* compute h_inc from hsize */
if (tv_dac->tv_std == TV_STD_NTSC ||
tv_dac->tv_std == TV_STD_NTSC_J ||
tv_dac->tv_std == TV_STD_PAL_M)
h_inc = (u16)((int)(const_ptr->hor_resolution * 4096 * NTSC_TV_CLOCK_T) /
(tv_dac->h_size * (int)(NTSC_TV_H_SIZE_UNIT) + (int)(NTSC_TV_ZERO_H_SIZE)));
else
h_inc = (u16)((int)(const_ptr->hor_resolution * 4096 * PAL_TV_CLOCK_T) /
(tv_dac->h_size * (int)(PAL_TV_H_SIZE_UNIT) + (int)(PAL_TV_ZERO_H_SIZE)));
 
tv_dac->tv.timing_cntl = (tv_dac->tv.timing_cntl & ~RADEON_H_INC_MASK) |
((u32)h_inc << RADEON_H_INC_SHIFT);
 
DRM_DEBUG("compute_restart: h_size = %d h_inc = %d\n", tv_dac->h_size, h_inc);
 
return h_changed;
}
 
void radeon_legacy_tv_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
const struct radeon_tv_mode_constants *const_ptr;
struct radeon_crtc *radeon_crtc;
int i;
uint16_t pll_ref_freq;
uint32_t vert_space, flicker_removal, tmp;
uint32_t tv_master_cntl, tv_rgb_cntl, tv_dac_cntl;
uint32_t tv_modulator_cntl1, tv_modulator_cntl2;
uint32_t tv_vscaler_cntl1, tv_vscaler_cntl2;
uint32_t tv_pll_cntl, tv_pll_cntl1, tv_ftotal;
uint32_t tv_y_fall_cntl, tv_y_rise_cntl, tv_y_saw_tooth_cntl;
uint32_t m, n, p;
const uint16_t *hor_timing;
const uint16_t *vert_timing;
 
const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, &pll_ref_freq);
if (!const_ptr)
return;
 
radeon_crtc = to_radeon_crtc(encoder->crtc);
 
tv_master_cntl = (RADEON_VIN_ASYNC_RST |
RADEON_CRT_FIFO_CE_EN |
RADEON_TV_FIFO_CE_EN |
RADEON_TV_ON);
 
if (!ASIC_IS_R300(rdev))
tv_master_cntl |= RADEON_TVCLK_ALWAYS_ONb;
 
if (tv_dac->tv_std == TV_STD_NTSC ||
tv_dac->tv_std == TV_STD_NTSC_J)
tv_master_cntl |= RADEON_RESTART_PHASE_FIX;
 
tv_modulator_cntl1 = (RADEON_SLEW_RATE_LIMIT |
RADEON_SYNC_TIP_LEVEL |
RADEON_YFLT_EN |
RADEON_UVFLT_EN |
(6 << RADEON_CY_FILT_BLEND_SHIFT));
 
if (tv_dac->tv_std == TV_STD_NTSC ||
tv_dac->tv_std == TV_STD_NTSC_J) {
tv_modulator_cntl1 |= (0x46 << RADEON_SET_UP_LEVEL_SHIFT) |
(0x3b << RADEON_BLANK_LEVEL_SHIFT);
tv_modulator_cntl2 = (-111 & RADEON_TV_U_BURST_LEVEL_MASK) |
((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
} else if (tv_dac->tv_std == TV_STD_SCART_PAL) {
tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN;
tv_modulator_cntl2 = (0 & RADEON_TV_U_BURST_LEVEL_MASK) |
((0 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
} else {
tv_modulator_cntl1 |= RADEON_ALT_PHASE_EN |
(0x3b << RADEON_SET_UP_LEVEL_SHIFT) |
(0x3b << RADEON_BLANK_LEVEL_SHIFT);
tv_modulator_cntl2 = (-78 & RADEON_TV_U_BURST_LEVEL_MASK) |
((62 & RADEON_TV_V_BURST_LEVEL_MASK) << RADEON_TV_V_BURST_LEVEL_SHIFT);
}
 
 
tv_rgb_cntl = (RADEON_RGB_DITHER_EN
| RADEON_TVOUT_SCALE_EN
| (0x0b << RADEON_UVRAM_READ_MARGIN_SHIFT)
| (0x07 << RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT)
| RADEON_RGB_ATTEN_SEL(0x3)
| RADEON_RGB_ATTEN_VAL(0xc));
 
if (radeon_crtc->crtc_id == 1)
tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC2;
else {
if (radeon_crtc->rmx_type != RMX_OFF)
tv_rgb_cntl |= RADEON_RGB_SRC_SEL_RMX;
else
tv_rgb_cntl |= RADEON_RGB_SRC_SEL_CRTC1;
}
 
if (tv_dac->tv_std == TV_STD_NTSC ||
tv_dac->tv_std == TV_STD_NTSC_J ||
tv_dac->tv_std == TV_STD_PAL_M ||
tv_dac->tv_std == TV_STD_PAL_60)
vert_space = const_ptr->ver_total * 2 * 10000 / NTSC_TV_LINES_PER_FRAME;
else
vert_space = const_ptr->ver_total * 2 * 10000 / PAL_TV_LINES_PER_FRAME;
 
tmp = RREG32(RADEON_TV_VSCALER_CNTL1);
tmp &= 0xe3ff0000;
tmp |= (vert_space * (1 << FRAC_BITS) / 10000);
tv_vscaler_cntl1 = tmp;
 
if (pll_ref_freq == 2700)
tv_vscaler_cntl1 |= RADEON_RESTART_FIELD;
 
if (const_ptr->hor_resolution == 1024)
tv_vscaler_cntl1 |= (4 << RADEON_Y_DEL_W_SIG_SHIFT);
else
tv_vscaler_cntl1 |= (2 << RADEON_Y_DEL_W_SIG_SHIFT);
 
/* scale up for int divide */
tmp = const_ptr->ver_total * 2 * 1000;
if (tv_dac->tv_std == TV_STD_NTSC ||
tv_dac->tv_std == TV_STD_NTSC_J ||
tv_dac->tv_std == TV_STD_PAL_M ||
tv_dac->tv_std == TV_STD_PAL_60) {
tmp /= NTSC_TV_LINES_PER_FRAME;
} else {
tmp /= PAL_TV_LINES_PER_FRAME;
}
flicker_removal = (tmp + 500) / 1000;
 
if (flicker_removal < 3)
flicker_removal = 3;
for (i = 0; i < 6; ++i) {
if (flicker_removal == SLOPE_limit[i])
break;
}
 
tv_y_saw_tooth_cntl = (vert_space * SLOPE_value[i] * (1 << (FRAC_BITS - 1)) +
5001) / 10000 / 8 | ((SLOPE_value[i] *
(1 << (FRAC_BITS - 1)) / 8) << 16);
tv_y_fall_cntl =
(YCOEF_EN_value[i] << 17) | ((YCOEF_value[i] * (1 << 8) / 8) << 24) |
RADEON_Y_FALL_PING_PONG | (272 * SLOPE_value[i] / 8) * (1 << (FRAC_BITS - 1)) /
1024;
tv_y_rise_cntl = RADEON_Y_RISE_PING_PONG|
(flicker_removal * 1024 - 272) * SLOPE_value[i] / 8 * (1 << (FRAC_BITS - 1)) / 1024;
 
tv_vscaler_cntl2 = RREG32(RADEON_TV_VSCALER_CNTL2) & 0x00fffff0;
tv_vscaler_cntl2 |= (0x10 << 24) |
RADEON_DITHER_MODE |
RADEON_Y_OUTPUT_DITHER_EN |
RADEON_UV_OUTPUT_DITHER_EN |
RADEON_UV_TO_BUF_DITHER_EN;
 
tmp = (tv_vscaler_cntl1 >> RADEON_UV_INC_SHIFT) & RADEON_UV_INC_MASK;
tmp = ((16384 * 256 * 10) / tmp + 5) / 10;
tmp = (tmp << RADEON_UV_OUTPUT_POST_SCALE_SHIFT) | 0x000b0000;
tv_dac->tv.timing_cntl = tmp;
 
if (tv_dac->tv_std == TV_STD_NTSC ||
tv_dac->tv_std == TV_STD_NTSC_J ||
tv_dac->tv_std == TV_STD_PAL_M ||
tv_dac->tv_std == TV_STD_PAL_60)
tv_dac_cntl = tv_dac->ntsc_tvdac_adj;
else
tv_dac_cntl = tv_dac->pal_tvdac_adj;
 
tv_dac_cntl |= RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD;
 
if (tv_dac->tv_std == TV_STD_NTSC ||
tv_dac->tv_std == TV_STD_NTSC_J)
tv_dac_cntl |= RADEON_TV_DAC_STD_NTSC;
else
tv_dac_cntl |= RADEON_TV_DAC_STD_PAL;
 
if (tv_dac->tv_std == TV_STD_NTSC ||
tv_dac->tv_std == TV_STD_NTSC_J) {
if (pll_ref_freq == 2700) {
m = NTSC_TV_PLL_M_27;
n = NTSC_TV_PLL_N_27;
p = NTSC_TV_PLL_P_27;
} else {
m = NTSC_TV_PLL_M_14;
n = NTSC_TV_PLL_N_14;
p = NTSC_TV_PLL_P_14;
}
} else {
if (pll_ref_freq == 2700) {
m = PAL_TV_PLL_M_27;
n = PAL_TV_PLL_N_27;
p = PAL_TV_PLL_P_27;
} else {
m = PAL_TV_PLL_M_27;
n = PAL_TV_PLL_N_27;
p = PAL_TV_PLL_P_27;
}
}
 
tv_pll_cntl = (m & RADEON_TV_M0LO_MASK) |
(((m >> 8) & RADEON_TV_M0HI_MASK) << RADEON_TV_M0HI_SHIFT) |
((n & RADEON_TV_N0LO_MASK) << RADEON_TV_N0LO_SHIFT) |
(((n >> 9) & RADEON_TV_N0HI_MASK) << RADEON_TV_N0HI_SHIFT) |
((p & RADEON_TV_P_MASK) << RADEON_TV_P_SHIFT);
 
tv_pll_cntl1 = (((4 & RADEON_TVPCP_MASK) << RADEON_TVPCP_SHIFT) |
((4 & RADEON_TVPVG_MASK) << RADEON_TVPVG_SHIFT) |
((1 & RADEON_TVPDC_MASK) << RADEON_TVPDC_SHIFT) |
RADEON_TVCLK_SRC_SEL_TVPLL |
RADEON_TVPLL_TEST_DIS);
 
tv_dac->tv.tv_uv_adr = 0xc8;
 
if (tv_dac->tv_std == TV_STD_NTSC ||
tv_dac->tv_std == TV_STD_NTSC_J ||
tv_dac->tv_std == TV_STD_PAL_M ||
tv_dac->tv_std == TV_STD_PAL_60) {
tv_ftotal = NTSC_TV_VFTOTAL;
hor_timing = hor_timing_NTSC;
vert_timing = vert_timing_NTSC;
} else {
hor_timing = hor_timing_PAL;
vert_timing = vert_timing_PAL;
tv_ftotal = PAL_TV_VFTOTAL;
}
 
for (i = 0; i < MAX_H_CODE_TIMING_LEN; i++) {
if ((tv_dac->tv.h_code_timing[i] = hor_timing[i]) == 0)
break;
}
 
for (i = 0; i < MAX_V_CODE_TIMING_LEN; i++) {
if ((tv_dac->tv.v_code_timing[i] = vert_timing[i]) == 0)
break;
}
 
radeon_legacy_tv_init_restarts(encoder);
 
/* play with DAC_CNTL */
/* play with GPIOPAD_A */
/* DISP_OUTPUT_CNTL */
/* use reference freq */
 
/* program the TV registers */
WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST |
RADEON_CRT_ASYNC_RST | RADEON_TV_FIFO_ASYNC_RST));
 
tmp = RREG32(RADEON_TV_DAC_CNTL);
tmp &= ~RADEON_TV_DAC_NBLANK;
tmp |= RADEON_TV_DAC_BGSLEEP |
RADEON_TV_DAC_RDACPD |
RADEON_TV_DAC_GDACPD |
RADEON_TV_DAC_BDACPD;
WREG32(RADEON_TV_DAC_CNTL, tmp);
 
/* TV PLL */
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVCLK_SRC_SEL_TVPLL);
WREG32_PLL(RADEON_TV_PLL_CNTL, tv_pll_cntl);
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, RADEON_TVPLL_RESET, ~RADEON_TVPLL_RESET);
 
radeon_wait_pll_lock(encoder, 200, 800, 135);
 
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_RESET);
 
radeon_wait_pll_lock(encoder, 300, 160, 27);
radeon_wait_pll_lock(encoder, 200, 800, 135);
 
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~0xf);
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, RADEON_TVCLK_SRC_SEL_TVPLL, ~RADEON_TVCLK_SRC_SEL_TVPLL);
 
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, (1 << RADEON_TVPDC_SHIFT), ~RADEON_TVPDC_MASK);
WREG32_PLL_P(RADEON_TV_PLL_CNTL1, 0, ~RADEON_TVPLL_SLEEP);
 
/* TV HV */
WREG32(RADEON_TV_RGB_CNTL, tv_rgb_cntl);
WREG32(RADEON_TV_HTOTAL, const_ptr->hor_total - 1);
WREG32(RADEON_TV_HDISP, const_ptr->hor_resolution - 1);
WREG32(RADEON_TV_HSTART, const_ptr->hor_start);
 
WREG32(RADEON_TV_VTOTAL, const_ptr->ver_total - 1);
WREG32(RADEON_TV_VDISP, const_ptr->ver_resolution - 1);
WREG32(RADEON_TV_FTOTAL, tv_ftotal);
WREG32(RADEON_TV_VSCALER_CNTL1, tv_vscaler_cntl1);
WREG32(RADEON_TV_VSCALER_CNTL2, tv_vscaler_cntl2);
 
WREG32(RADEON_TV_Y_FALL_CNTL, tv_y_fall_cntl);
WREG32(RADEON_TV_Y_RISE_CNTL, tv_y_rise_cntl);
WREG32(RADEON_TV_Y_SAW_TOOTH_CNTL, tv_y_saw_tooth_cntl);
 
WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST |
RADEON_CRT_ASYNC_RST));
 
/* TV restarts */
radeon_legacy_write_tv_restarts(radeon_encoder);
 
/* tv timings */
radeon_restore_tv_timing_tables(radeon_encoder);
 
WREG32(RADEON_TV_MASTER_CNTL, (tv_master_cntl | RADEON_TV_ASYNC_RST));
 
/* tv std */
WREG32(RADEON_TV_SYNC_CNTL, (RADEON_SYNC_PUB | RADEON_TV_SYNC_IO_DRIVE));
WREG32(RADEON_TV_TIMING_CNTL, tv_dac->tv.timing_cntl);
WREG32(RADEON_TV_MODULATOR_CNTL1, tv_modulator_cntl1);
WREG32(RADEON_TV_MODULATOR_CNTL2, tv_modulator_cntl2);
WREG32(RADEON_TV_PRE_DAC_MUX_CNTL, (RADEON_Y_RED_EN |
RADEON_C_GRN_EN |
RADEON_CMP_BLU_EN |
RADEON_DAC_DITHER_EN));
 
WREG32(RADEON_TV_CRC_CNTL, 0);
 
WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
 
WREG32(RADEON_TV_GAIN_LIMIT_SETTINGS, ((0x17f << RADEON_UV_GAIN_LIMIT_SHIFT) |
(0x5ff << RADEON_Y_GAIN_LIMIT_SHIFT)));
WREG32(RADEON_TV_LINEAR_GAIN_SETTINGS, ((0x100 << RADEON_UV_GAIN_SHIFT) |
(0x100 << RADEON_Y_GAIN_SHIFT)));
 
WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
 
}
 
void radeon_legacy_tv_adjust_crtc_reg(struct drm_encoder *encoder,
uint32_t *h_total_disp, uint32_t *h_sync_strt_wid,
uint32_t *v_total_disp, uint32_t *v_sync_strt_wid)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
const struct radeon_tv_mode_constants *const_ptr;
uint32_t tmp;
 
const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
if (!const_ptr)
return;
 
*h_total_disp = (((const_ptr->hor_resolution / 8) - 1) << RADEON_CRTC_H_DISP_SHIFT) |
(((const_ptr->hor_total / 8) - 1) << RADEON_CRTC_H_TOTAL_SHIFT);
 
tmp = *h_sync_strt_wid;
tmp &= ~(RADEON_CRTC_H_SYNC_STRT_PIX | RADEON_CRTC_H_SYNC_STRT_CHAR);
tmp |= (((const_ptr->hor_syncstart / 8) - 1) << RADEON_CRTC_H_SYNC_STRT_CHAR_SHIFT) |
(const_ptr->hor_syncstart & 7);
*h_sync_strt_wid = tmp;
 
*v_total_disp = ((const_ptr->ver_resolution - 1) << RADEON_CRTC_V_DISP_SHIFT) |
((const_ptr->ver_total - 1) << RADEON_CRTC_V_TOTAL_SHIFT);
 
tmp = *v_sync_strt_wid;
tmp &= ~RADEON_CRTC_V_SYNC_STRT;
tmp |= ((const_ptr->ver_syncstart - 1) << RADEON_CRTC_V_SYNC_STRT_SHIFT);
*v_sync_strt_wid = tmp;
}
 
static inline int get_post_div(int value)
{
int post_div;
switch (value) {
case 1: post_div = 0; break;
case 2: post_div = 1; break;
case 3: post_div = 4; break;
case 4: post_div = 2; break;
case 6: post_div = 6; break;
case 8: post_div = 3; break;
case 12: post_div = 7; break;
case 16:
default: post_div = 5; break;
}
return post_div;
}
 
void radeon_legacy_tv_adjust_pll1(struct drm_encoder *encoder,
uint32_t *htotal_cntl, uint32_t *ppll_ref_div,
uint32_t *ppll_div_3, uint32_t *pixclks_cntl)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
const struct radeon_tv_mode_constants *const_ptr;
 
const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
if (!const_ptr)
return;
 
*htotal_cntl = (const_ptr->hor_total & 0x7) | RADEON_HTOT_CNTL_VGA_EN;
 
*ppll_ref_div = const_ptr->crtcPLL_M;
 
*ppll_div_3 = (const_ptr->crtcPLL_N & 0x7ff) | (get_post_div(const_ptr->crtcPLL_post_div) << 16);
*pixclks_cntl &= ~(RADEON_PIX2CLK_SRC_SEL_MASK | RADEON_PIXCLK_TV_SRC_SEL);
*pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK;
}
 
void radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder,
uint32_t *htotal2_cntl, uint32_t *p2pll_ref_div,
uint32_t *p2pll_div_0, uint32_t *pixclks_cntl)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
const struct radeon_tv_mode_constants *const_ptr;
 
const_ptr = radeon_legacy_tv_get_std_mode(radeon_encoder, NULL);
if (!const_ptr)
return;
 
*htotal2_cntl = (const_ptr->hor_total & 0x7);
 
*p2pll_ref_div = const_ptr->crtcPLL_M;
 
*p2pll_div_0 = (const_ptr->crtcPLL_N & 0x7ff) | (get_post_div(const_ptr->crtcPLL_post_div) << 16);
*pixclks_cntl &= ~RADEON_PIX2CLK_SRC_SEL_MASK;
*pixclks_cntl |= RADEON_PIX2CLK_SRC_SEL_P2PLLCLK | RADEON_PIXCLK_TV_SRC_SEL;
}
 
/drivers/video/drm/radeon/radeon_mode.h
34,8 → 34,12
#include <drm_mode.h>
#include <drm_edid.h>
#include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/i2c-algo-bit.h>
#include "radeon_fixed.h"
 
struct radeon_device;
 
#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)
123,6 → 127,7
#define RADEON_PLL_PREFER_LOW_POST_DIV (1 << 8)
#define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9)
#define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10)
#define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11)
 
struct radeon_pll {
uint16_t reference_freq;
169,36 → 174,63
struct atom_context *atom_context;
enum radeon_connector_table connector_table;
bool mode_config_initialized;
struct radeon_crtc *crtcs[2];
/* DVI-I properties */
struct drm_property *coherent_mode_property;
/* DAC enable load detect */
struct drm_property *load_detect_property;
/* TV standard load detect */
struct drm_property *tv_std_property;
/* legacy TMDS PLL detect */
struct drm_property *tmds_pll_property;
 
};
 
struct radeon_native_mode {
/* preferred mode */
uint32_t panel_xres, panel_yres;
uint32_t hoverplus, hsync_width;
uint32_t hblank;
uint32_t voverplus, vsync_width;
uint32_t vblank;
uint32_t dotclock;
uint32_t flags;
};
 
#define MAX_H_CODE_TIMING_LEN 32
#define MAX_V_CODE_TIMING_LEN 32
 
/* need to store these as reading
back code tables is excessive */
struct radeon_tv_regs {
uint32_t tv_uv_adr;
uint32_t timing_cntl;
uint32_t hrestart;
uint32_t vrestart;
uint32_t frestart;
uint16_t h_code_timing[MAX_H_CODE_TIMING_LEN];
uint16_t v_code_timing[MAX_V_CODE_TIMING_LEN];
};
 
struct radeon_crtc {
struct drm_crtc base;
int crtc_id;
u16_t lut_r[256], lut_g[256], lut_b[256];
u16 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 drm_gem_object *cursor_bo;
uint64_t cursor_addr;
int cursor_width;
int cursor_height;
uint32_t legacy_display_base_addr;
uint32_t legacy_cursor_offset;
enum radeon_rmx_type rmx_type;
fixed20_12 vsc;
fixed20_12 hsc;
struct radeon_native_mode native_mode;
};
 
#define RADEON_USE_RMX 1
 
struct radeon_native_mode {
/* preferred mode */
uint32_t panel_xres, panel_yres;
uint32_t hoverplus, hsync_width;
uint32_t hblank;
uint32_t voverplus, vsync_width;
uint32_t vblank;
uint32_t dotclock;
uint32_t flags;
};
 
struct radeon_encoder_primary_dac {
/* legacy primary dac */
uint32_t ps2_pdac_adj;
225,7 → 257,13
uint32_t ntsc_tvdac_adj;
uint32_t pal_tvdac_adj;
 
int h_pos;
int v_pos;
int h_size;
int supported_tv_stds;
bool tv_on;
enum radeon_tv_std tv_std;
struct radeon_tv_regs tv;
};
 
struct radeon_encoder_int_tmds {
244,10 → 282,15
struct radeon_native_mode native_mode;
};
 
struct radeon_encoder_atom_dac {
enum radeon_tv_std tv_std;
};
 
struct radeon_encoder {
struct drm_encoder base;
uint32_t encoder_id;
uint32_t devices;
uint32_t active_device;
uint32_t flags;
uint32_t pixel_clock;
enum radeon_rmx_type rmx_type;
265,8 → 308,12
uint32_t connector_id;
uint32_t devices;
struct radeon_i2c_chan *ddc_bus;
int use_digital;
bool use_digital;
/* we need to mind the EDID between detect
and get modes due to analog/digital/tvencoder */
struct edid *edid;
void *con_priv;
bool dac_load_detect;
};
 
struct radeon_framebuffer {
299,6 → 346,7
struct drm_encoder *radeon_encoder_legacy_tmds_ext_add(struct drm_device *dev, int bios_index);
extern void atombios_external_tmds_setup(struct drm_encoder *encoder, int action);
extern int atombios_get_encoder_mode(struct drm_encoder *encoder);
extern void radeon_encoder_set_active_device(struct drm_encoder *encoder);
 
extern void radeon_crtc_load_lut(struct drm_crtc *crtc);
extern int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
326,8 → 374,12
extern bool radeon_combios_get_clock_info(struct drm_device *dev);
extern struct radeon_encoder_atom_dig *
radeon_atombios_get_lvds_info(struct radeon_encoder *encoder);
extern struct radeon_encoder_int_tmds *
radeon_atombios_get_tmds_info(struct radeon_encoder *encoder);
bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds);
bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds);
bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds);
extern struct radeon_encoder_primary_dac *
radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder);
extern struct radeon_encoder_tv_dac *
334,8 → 386,6
radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder);
extern struct radeon_encoder_lvds *
radeon_combios_get_lvds_info(struct radeon_encoder *encoder);
extern struct radeon_encoder_int_tmds *
radeon_combios_get_tmds_info(struct radeon_encoder *encoder);
extern void radeon_combios_get_ext_tmds_info(struct radeon_encoder *encoder);
extern struct radeon_encoder_tv_dac *
radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder);
345,6 → 395,8
extern void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev);
extern void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock);
extern void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev);
extern void radeon_save_bios_scratch_regs(struct radeon_device *rdev);
extern void radeon_restore_bios_scratch_regs(struct radeon_device *rdev);
extern void
radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc);
extern void
382,16 → 434,22
void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj);
void radeon_combios_asic_init(struct drm_device *dev);
extern int radeon_static_clocks_init(struct drm_device *dev);
void radeon_init_disp_bw_legacy(struct drm_device *dev,
struct drm_display_mode *mode1,
uint32_t pixel_bytes1,
struct drm_display_mode *mode2,
uint32_t pixel_bytes2);
void radeon_init_disp_bw_avivo(struct drm_device *dev,
struct drm_display_mode *mode1,
uint32_t pixel_bytes1,
struct drm_display_mode *mode2,
uint32_t pixel_bytes2);
void radeon_init_disp_bandwidth(struct drm_device *dev);
bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
void atom_rv515_force_tv_scaler(struct radeon_device *rdev, struct radeon_crtc *radeon_crtc);
 
/* legacy tv */
void radeon_legacy_tv_adjust_crtc_reg(struct drm_encoder *encoder,
uint32_t *h_total_disp, uint32_t *h_sync_strt_wid,
uint32_t *v_total_disp, uint32_t *v_sync_strt_wid);
void radeon_legacy_tv_adjust_pll1(struct drm_encoder *encoder,
uint32_t *htotal_cntl, uint32_t *ppll_ref_div,
uint32_t *ppll_div_3, uint32_t *pixclks_cntl);
void radeon_legacy_tv_adjust_pll2(struct drm_encoder *encoder,
uint32_t *htotal2_cntl, uint32_t *p2pll_ref_div,
uint32_t *p2pll_div_0, uint32_t *pixclks_cntl);
void radeon_legacy_tv_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
#endif
/drivers/video/drm/radeon/radeon_object.c
29,9 → 29,8
* Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
* Dave Airlie
*/
#include <list.h>
#include <drmP.h>
 
#include <linux/list.h>
#include <drm/drmP.h>
#include "radeon_drm.h"
#include "radeon.h"
#include <drm_mm.h>
/drivers/video/drm/radeon/radeon_reg.h
982,12 → 982,15
# define RS400_TMDS2_PLLRST (1 << 1)
 
#define RADEON_GEN_INT_CNTL 0x0040
# define RADEON_CRTC_VBLANK_MASK (1 << 0)
# define RADEON_CRTC2_VBLANK_MASK (1 << 9)
# define RADEON_SW_INT_ENABLE (1 << 25)
#define RADEON_GEN_INT_STATUS 0x0044
# define RADEON_VSYNC_INT_AK (1 << 2)
# define RADEON_VSYNC_INT (1 << 2)
# define RADEON_VSYNC2_INT_AK (1 << 6)
# define RADEON_VSYNC2_INT (1 << 6)
# define AVIVO_DISPLAY_INT_STATUS (1 << 0)
# define RADEON_CRTC_VBLANK_STAT (1 << 0)
# define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0)
# define RADEON_CRTC2_VBLANK_STAT (1 << 9)
# define RADEON_CRTC2_VBLANK_STAT_ACK (1 << 9)
# define RADEON_SW_INT_FIRE (1 << 26)
# define RADEON_SW_INT_TEST (1 << 25)
# define RADEON_SW_INT_TEST_ACK (1 << 25)
1942,6 → 1945,11
# define RADEON_TXFORMAT_DXT1 (12 << 0)
# define RADEON_TXFORMAT_DXT23 (14 << 0)
# define RADEON_TXFORMAT_DXT45 (15 << 0)
# define RADEON_TXFORMAT_SHADOW16 (16 << 0)
# define RADEON_TXFORMAT_SHADOW32 (17 << 0)
# define RADEON_TXFORMAT_DUDV88 (18 << 0)
# define RADEON_TXFORMAT_LDUDV655 (19 << 0)
# define RADEON_TXFORMAT_LDUDUV8888 (20 << 0)
# define RADEON_TXFORMAT_FORMAT_MASK (31 << 0)
# define RADEON_TXFORMAT_FORMAT_SHIFT 0
# define RADEON_TXFORMAT_APPLE_YUV_MODE (1 << 5)
2200,7 → 2208,7
# define RADEON_ROP_ENABLE (1 << 6)
# define RADEON_STENCIL_ENABLE (1 << 7)
# define RADEON_Z_ENABLE (1 << 8)
# define RADEON_DEPTH_XZ_OFFEST_ENABLE (1 << 9)
# define RADEON_DEPTHXY_OFFSET_ENABLE (1 << 9)
# define RADEON_RB3D_COLOR_FORMAT_SHIFT 10
 
# define RADEON_COLOR_FORMAT_ARGB1555 3
2334,6 → 2342,9
# define RADEON_RE_WIDTH_SHIFT 0
# define RADEON_RE_HEIGHT_SHIFT 16
 
#define RADEON_RB3D_ZPASS_DATA 0x3290
#define RADEON_RB3D_ZPASS_ADDR 0x3294
 
#define RADEON_SE_CNTL 0x1c4c
# define RADEON_FFACE_CULL_CW (0 << 0)
# define RADEON_FFACE_CULL_CCW (1 << 0)
2767,7 → 2778,12
# define R200_TXFORMAT_DXT1 (12 << 0)
# define R200_TXFORMAT_DXT23 (14 << 0)
# define R200_TXFORMAT_DXT45 (15 << 0)
# define R200_TXFORMAT_DVDU88 (18 << 0)
# define R200_TXFORMAT_LDVDU655 (19 << 0)
# define R200_TXFORMAT_LDVDU8888 (20 << 0)
# define R200_TXFORMAT_GR1616 (21 << 0)
# define R200_TXFORMAT_ABGR8888 (22 << 0)
# define R200_TXFORMAT_BGR111110 (23 << 0)
# define R200_TXFORMAT_FORMAT_MASK (31 << 0)
# define R200_TXFORMAT_FORMAT_SHIFT 0
# define R200_TXFORMAT_ALPHA_IN_MAP (1 << 6)
2812,6 → 2828,13
#define R200_PP_TXPITCH_4 0x2c90 /* NPOT only */
#define R200_PP_TXPITCH_5 0x2cb0 /* NPOT only */
 
#define R200_PP_CUBIC_FACES_0 0x2c18
#define R200_PP_CUBIC_FACES_1 0x2c38
#define R200_PP_CUBIC_FACES_2 0x2c58
#define R200_PP_CUBIC_FACES_3 0x2c78
#define R200_PP_CUBIC_FACES_4 0x2c98
#define R200_PP_CUBIC_FACES_5 0x2cb8
 
#define R200_PP_TXOFFSET_0 0x2d00
# define R200_TXO_ENDIAN_NO_SWAP (0 << 0)
# define R200_TXO_ENDIAN_BYTE_SWAP (1 << 0)
2823,11 → 2846,44
# define R200_TXO_MICRO_TILE (1 << 3)
# define R200_TXO_OFFSET_MASK 0xffffffe0
# define R200_TXO_OFFSET_SHIFT 5
#define R200_PP_CUBIC_OFFSET_F1_0 0x2d04
#define R200_PP_CUBIC_OFFSET_F2_0 0x2d08
#define R200_PP_CUBIC_OFFSET_F3_0 0x2d0c
#define R200_PP_CUBIC_OFFSET_F4_0 0x2d10
#define R200_PP_CUBIC_OFFSET_F5_0 0x2d14
 
#define R200_PP_TXOFFSET_1 0x2d18
#define R200_PP_CUBIC_OFFSET_F1_1 0x2d1c
#define R200_PP_CUBIC_OFFSET_F2_1 0x2d20
#define R200_PP_CUBIC_OFFSET_F3_1 0x2d24
#define R200_PP_CUBIC_OFFSET_F4_1 0x2d28
#define R200_PP_CUBIC_OFFSET_F5_1 0x2d2c
 
#define R200_PP_TXOFFSET_2 0x2d30
#define R200_PP_CUBIC_OFFSET_F1_2 0x2d34
#define R200_PP_CUBIC_OFFSET_F2_2 0x2d38
#define R200_PP_CUBIC_OFFSET_F3_2 0x2d3c
#define R200_PP_CUBIC_OFFSET_F4_2 0x2d40
#define R200_PP_CUBIC_OFFSET_F5_2 0x2d44
 
#define R200_PP_TXOFFSET_3 0x2d48
#define R200_PP_CUBIC_OFFSET_F1_3 0x2d4c
#define R200_PP_CUBIC_OFFSET_F2_3 0x2d50
#define R200_PP_CUBIC_OFFSET_F3_3 0x2d54
#define R200_PP_CUBIC_OFFSET_F4_3 0x2d58
#define R200_PP_CUBIC_OFFSET_F5_3 0x2d5c
#define R200_PP_TXOFFSET_4 0x2d60
#define R200_PP_CUBIC_OFFSET_F1_4 0x2d64
#define R200_PP_CUBIC_OFFSET_F2_4 0x2d68
#define R200_PP_CUBIC_OFFSET_F3_4 0x2d6c
#define R200_PP_CUBIC_OFFSET_F4_4 0x2d70
#define R200_PP_CUBIC_OFFSET_F5_4 0x2d74
#define R200_PP_TXOFFSET_5 0x2d78
#define R200_PP_CUBIC_OFFSET_F1_5 0x2d7c
#define R200_PP_CUBIC_OFFSET_F2_5 0x2d80
#define R200_PP_CUBIC_OFFSET_F3_5 0x2d84
#define R200_PP_CUBIC_OFFSET_F4_5 0x2d88
#define R200_PP_CUBIC_OFFSET_F5_5 0x2d8c
 
#define R200_PP_TFACTOR_0 0x2ee0
#define R200_PP_TFACTOR_1 0x2ee4
3169,6 → 3225,11
# define R200_FORCE_INORDER_PROC (1<<31)
#define R200_PP_CNTL_X 0x2cc4
#define R200_PP_TXMULTI_CTL_0 0x2c1c
#define R200_PP_TXMULTI_CTL_1 0x2c3c
#define R200_PP_TXMULTI_CTL_2 0x2c5c
#define R200_PP_TXMULTI_CTL_3 0x2c7c
#define R200_PP_TXMULTI_CTL_4 0x2c9c
#define R200_PP_TXMULTI_CTL_5 0x2cbc
#define R200_SE_VTX_STATE_CNTL 0x2180
# define R200_UPDATE_USER_COLOR_0_ENA_MASK (1<<16)
 
3194,6 → 3255,24
#define RADEON_CP_RB_WPTR 0x0714
#define RADEON_CP_RB_RPTR_WR 0x071c
 
#define RADEON_SCRATCH_UMSK 0x0770
#define RADEON_SCRATCH_ADDR 0x0774
 
#define R600_CP_RB_BASE 0xc100
#define R600_CP_RB_CNTL 0xc104
# define R600_RB_BUFSZ(x) ((x) << 0)
# define R600_RB_BLKSZ(x) ((x) << 8)
# define R600_RB_NO_UPDATE (1 << 27)
# define R600_RB_RPTR_WR_ENA (1 << 31)
#define R600_CP_RB_RPTR_WR 0xc108
#define R600_CP_RB_RPTR_ADDR 0xc10c
#define R600_CP_RB_RPTR_ADDR_HI 0xc110
#define R600_CP_RB_WPTR 0xc114
#define R600_CP_RB_WPTR_ADDR 0xc118
#define R600_CP_RB_WPTR_ADDR_HI 0xc11c
#define R600_CP_RB_RPTR 0x8700
#define R600_CP_RB_WPTR_DELAY 0x8704
 
#define RADEON_CP_IB_BASE 0x0738
#define RADEON_CP_IB_BUFSZ 0x073c
 
3401,7 → 3480,9
# define RADEON_RGB_CONVERT_BY_PASS (1 << 10)
# define RADEON_UVRAM_READ_MARGIN_SHIFT 16
# define RADEON_FIFORAM_FFMACRO_READ_MARGIN_SHIFT 20
# define RADEON_RGB_ATTEN_SEL(x) ((x) << 24)
# define RADEON_TVOUT_SCALE_EN (1 << 26)
# define RADEON_RGB_ATTEN_VAL(x) ((x) << 28)
#define RADEON_TV_SYNC_CNTL 0x0808
# define RADEON_SYNC_OE (1 << 0)
# define RADEON_SYNC_OUT (1 << 1)
3568,4 → 3649,6
#define RADEON_SCRATCH_REG4 0x15f0
#define RADEON_SCRATCH_REG5 0x15f4
 
#define RV530_GB_PIPE_SELECT2 0x4124
 
#endif
/drivers/video/drm/radeon/radeon_ring.c
25,7 → 25,7
* Alex Deucher
* Jerome Glisse
*/
//#include <linux/seq_file.h>
#include <linux/seq_file.h>
#include "drmP.h"
#include "radeon_drm.h"
#include "radeon_reg.h"
32,7 → 32,6
#include "radeon.h"
#include "atom.h"
 
 
int radeon_debugfs_ib_init(struct radeon_device *rdev);
 
/*
60,10 → 59,12
set_bit(i, rdev->ib_pool.alloc_bm);
rdev->ib_pool.ibs[i].length_dw = 0;
*ib = &rdev->ib_pool.ibs[i];
mutex_unlock(&rdev->ib_pool.mutex);
goto out;
}
if (list_empty(&rdev->ib_pool.scheduled_ibs)) {
/* we go do nothings here */
mutex_unlock(&rdev->ib_pool.mutex);
DRM_ERROR("all IB allocated none scheduled.\n");
r = -EINVAL;
goto out;
73,10 → 74,13
struct radeon_ib, list);
if (nib->fence == NULL) {
/* we go do nothings here */
mutex_unlock(&rdev->ib_pool.mutex);
DRM_ERROR("IB %lu scheduled without a fence.\n", nib->idx);
r = -EINVAL;
goto out;
}
mutex_unlock(&rdev->ib_pool.mutex);
 
r = radeon_fence_wait(nib->fence, false);
if (r) {
DRM_ERROR("radeon: IB(%lu:0x%016lX:%u)\n", nib->idx,
85,12 → 89,17
goto out;
}
radeon_fence_unref(&nib->fence);
 
nib->length_dw = 0;
 
/* scheduled list is accessed here */
mutex_lock(&rdev->ib_pool.mutex);
list_del(&nib->list);
INIT_LIST_HEAD(&nib->list);
mutex_unlock(&rdev->ib_pool.mutex);
 
*ib = nib;
out:
mutex_unlock(&rdev->ib_pool.mutex);
if (r) {
radeon_fence_unref(&fence);
} else {
115,60 → 124,36
}
list_del(&tmp->list);
INIT_LIST_HEAD(&tmp->list);
if (tmp->fence) {
if (tmp->fence)
radeon_fence_unref(&tmp->fence);
}
 
tmp->length_dw = 0;
clear_bit(tmp->idx, rdev->ib_pool.alloc_bm);
mutex_unlock(&rdev->ib_pool.mutex);
}
 
static void radeon_ib_align(struct radeon_device *rdev, struct radeon_ib *ib)
{
while ((ib->length_dw & rdev->cp.align_mask)) {
ib->ptr[ib->length_dw++] = PACKET2(0);
}
}
 
static void radeon_ib_cpu_flush(struct radeon_device *rdev,
struct radeon_ib *ib)
{
unsigned long tmp;
unsigned i;
 
/* To force CPU cache flush ugly but seems reliable */
for (i = 0; i < ib->length_dw; i += (rdev->cp.align_mask + 1)) {
tmp = readl(&ib->ptr[i]);
}
}
 
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
{
int r = 0;
 
mutex_lock(&rdev->ib_pool.mutex);
radeon_ib_align(rdev, ib);
radeon_ib_cpu_flush(rdev, ib);
if (!ib->length_dw || !rdev->cp.ready) {
/* TODO: Nothings in the ib we should report. */
mutex_unlock(&rdev->ib_pool.mutex);
DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx);
return -EINVAL;
}
/* 64 dwords should be enought for fence too */
 
/* 64 dwords should be enough for fence too */
r = radeon_ring_lock(rdev, 64);
if (r) {
DRM_ERROR("radeon: scheduling IB failled (%d).\n", r);
mutex_unlock(&rdev->ib_pool.mutex);
return r;
}
radeon_ring_write(rdev, PACKET0(RADEON_CP_IB_BASE, 1));
radeon_ring_write(rdev, ib->gpu_addr);
radeon_ring_write(rdev, ib->length_dw);
radeon_ring_ib_execute(rdev, ib);
radeon_fence_emit(rdev, ib->fence);
radeon_ring_unlock_commit(rdev);
mutex_lock(&rdev->ib_pool.mutex);
list_add_tail(&ib->list, &rdev->ib_pool.scheduled_ibs);
mutex_unlock(&rdev->ib_pool.mutex);
radeon_ring_unlock_commit(rdev);
return 0;
}
#endif
180,6 → 165,8
int i;
int r = 0;
 
if (rdev->ib_pool.robj)
return 0;
/* Allocate 1M object buffer */
INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs);
r = radeon_object_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024,
223,7 → 210,7
if (!rdev->ib_pool.ready) {
return;
}
// mutex_lock(&rdev->ib_pool.mutex);
mutex_lock(&rdev->ib_pool.mutex);
bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
if (rdev->ib_pool.robj) {
// radeon_object_kunmap(rdev->ib_pool.robj);
230,74 → 217,18
// radeon_object_unref(&rdev->ib_pool.robj);
rdev->ib_pool.robj = NULL;
}
// mutex_unlock(&rdev->ib_pool.mutex);
mutex_unlock(&rdev->ib_pool.mutex);
}
 
#if 0
 
int radeon_ib_test(struct radeon_device *rdev)
{
struct radeon_ib *ib;
uint32_t scratch;
uint32_t tmp = 0;
unsigned i;
int r;
 
r = radeon_scratch_get(rdev, &scratch);
if (r) {
DRM_ERROR("radeon: failed to get scratch reg (%d).\n", r);
return r;
}
WREG32(scratch, 0xCAFEDEAD);
r = radeon_ib_get(rdev, &ib);
if (r) {
return r;
}
ib->ptr[0] = PACKET0(scratch, 0);
ib->ptr[1] = 0xDEADBEEF;
ib->ptr[2] = PACKET2(0);
ib->ptr[3] = PACKET2(0);
ib->ptr[4] = PACKET2(0);
ib->ptr[5] = PACKET2(0);
ib->ptr[6] = PACKET2(0);
ib->ptr[7] = PACKET2(0);
ib->length_dw = 8;
r = radeon_ib_schedule(rdev, ib);
if (r) {
radeon_scratch_free(rdev, scratch);
radeon_ib_free(rdev, &ib);
return r;
}
r = radeon_fence_wait(ib->fence, false);
if (r) {
return r;
}
for (i = 0; i < rdev->usec_timeout; i++) {
tmp = RREG32(scratch);
if (tmp == 0xDEADBEEF) {
break;
}
DRM_UDELAY(1);
}
if (i < rdev->usec_timeout) {
DRM_INFO("ib test succeeded in %u usecs\n", i);
} else {
DRM_ERROR("radeon: ib test failed (sracth(0x%04X)=0x%08X)\n",
scratch, tmp);
r = -EINVAL;
}
radeon_scratch_free(rdev, scratch);
radeon_ib_free(rdev, &ib);
return r;
}
 
#endif
 
/*
* Ring.
*/
void radeon_ring_free_size(struct radeon_device *rdev)
{
if (rdev->family >= CHIP_R600)
rdev->cp.rptr = RREG32(R600_CP_RB_RPTR);
else
rdev->cp.rptr = RREG32(RADEON_CP_RB_RPTR);
/* This works because ring_size is a power of 2 */
rdev->cp.ring_free_dw = (rdev->cp.rptr + (rdev->cp.ring_size / 4));
315,14 → 246,12
/* Align requested size with padding so unlock_commit can
* pad safely */
ndw = (ndw + rdev->cp.align_mask) & ~rdev->cp.align_mask;
// mutex_lock(&rdev->cp.mutex);
mutex_lock(&rdev->cp.mutex);
while (ndw > (rdev->cp.ring_free_dw - 1)) {
radeon_ring_free_size(rdev);
if (ndw < rdev->cp.ring_free_dw) {
break;
}
delay(1);
 
// r = radeon_fence_wait_next(rdev);
// if (r) {
// mutex_unlock(&rdev->cp.mutex);
343,79 → 272,26
count_dw_pad = (rdev->cp.align_mask + 1) -
(rdev->cp.wptr & rdev->cp.align_mask);
for (i = 0; i < count_dw_pad; i++) {
radeon_ring_write(rdev, PACKET2(0));
radeon_ring_write(rdev, 2 << 30);
}
DRM_MEMORYBARRIER();
WREG32(RADEON_CP_RB_WPTR, rdev->cp.wptr);
(void)RREG32(RADEON_CP_RB_WPTR);
// mutex_unlock(&rdev->cp.mutex);
radeon_cp_commit(rdev);
mutex_unlock(&rdev->cp.mutex);
}
 
void radeon_ring_unlock_undo(struct radeon_device *rdev)
{
rdev->cp.wptr = rdev->cp.wptr_old;
// mutex_unlock(&rdev->cp.mutex);
mutex_unlock(&rdev->cp.mutex);
}
 
 
int radeon_ring_test(struct radeon_device *rdev)
{
uint32_t scratch;
uint32_t tmp = 0;
unsigned i;
int r;
 
dbgprintf("%s\n",__FUNCTION__);
 
r = radeon_scratch_get(rdev, &scratch);
if (r) {
DRM_ERROR("radeon: cp failed to get scratch reg (%d).\n", r);
return r;
}
WREG32(scratch, 0xCAFEDEAD);
r = radeon_ring_lock(rdev, 2);
if (r) {
DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
radeon_scratch_free(rdev, scratch);
return r;
}
radeon_ring_write(rdev, PACKET0(scratch, 0));
radeon_ring_write(rdev, 0xDEADBEEF);
radeon_ring_unlock_commit(rdev);
for (i = 0; i < 100000; i++) {
tmp = RREG32(scratch);
if (tmp == 0xDEADBEEF) {
break;
}
DRM_UDELAY(1);
}
if (i < 100000) {
DRM_INFO("ring test succeeded in %d usecs\n", i);
} else {
DRM_ERROR("radeon: ring test failed (sracth(0x%04X)=0x%08X)\n",
scratch, tmp);
r = -EINVAL;
}
radeon_scratch_free(rdev, scratch);
 
dbgprintf("done %s\n",__FUNCTION__);
return r;
}
 
 
int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
int pages, u32_t *pagelist);
 
 
 
int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size)
{
int r;
 
dbgprintf("%s\n",__FUNCTION__);
ENTER();
 
rdev->cp.ring_size = ring_size;
 
/* Allocate ring buffer */
if (rdev->cp.ring_obj == NULL) {
r = radeon_object_create(rdev, NULL, rdev->cp.ring_size,
425,7 → 301,7
&rdev->cp.ring_obj);
if (r) {
DRM_ERROR("radeon: failed to create ring buffer (%d).\n", r);
// mutex_unlock(&rdev->cp.mutex);
mutex_unlock(&rdev->cp.mutex);
return r;
}
r = radeon_object_pin(rdev->cp.ring_obj,
433,7 → 309,7
&rdev->cp.gpu_addr);
if (r) {
DRM_ERROR("radeon: failed to pin ring buffer (%d).\n", r);
// mutex_unlock(&rdev->cp.mutex);
mutex_unlock(&rdev->cp.mutex);
return r;
}
r = radeon_object_kmap(rdev->cp.ring_obj,
440,7 → 316,7
(void **)&rdev->cp.ring);
if (r) {
DRM_ERROR("radeon: failed to map ring buffer (%d).\n", r);
// mutex_unlock(&rdev->cp.mutex);
mutex_unlock(&rdev->cp.mutex);
return r;
}
}
461,7 → 337,7
rdev->cp.ptr_mask = (rdev->cp.ring_size / 4) - 1;
rdev->cp.ring_free_dw = rdev->cp.ring_size / 4;
 
dbgprintf("done %s\n",__FUNCTION__);
LEAVE();
 
return 0;
}
468,7 → 344,7
 
void radeon_ring_fini(struct radeon_device *rdev)
{
// mutex_lock(&rdev->cp.mutex);
mutex_lock(&rdev->cp.mutex);
if (rdev->cp.ring_obj) {
// radeon_object_kunmap(rdev->cp.ring_obj);
// radeon_object_unpin(rdev->cp.ring_obj);
476,7 → 352,7
rdev->cp.ring = NULL;
rdev->cp.ring_obj = NULL;
}
// mutex_unlock(&rdev->cp.mutex);
mutex_unlock(&rdev->cp.mutex);
}
 
 
524,18 → 400,3
return 0;
#endif
}
 
 
int drm_order(unsigned long size)
{
int order;
unsigned long tmp;
 
for (order = 0, tmp = size >> 1; tmp; tmp >>= 1, order++) ;
 
if (size & (size - 1))
++order;
 
return order;
}
 
/drivers/video/drm/radeon/radeon_share.h
0,0 → 1,39
/*
* Copyright 2008 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
* Copyright 2009 Jerome Glisse.
*
* 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
* Jerome Glisse
*/
#ifndef __RADEON_SHARE_H__
#define __RADEON_SHARE_H__
 
void r100_vram_init_sizes(struct radeon_device *rdev);
 
void rs690_line_buffer_adjust(struct radeon_device *rdev,
struct drm_display_mode *mode1,
struct drm_display_mode *mode2);
 
void rv515_bandwidth_avivo_update(struct radeon_device *rdev);
 
#endif
/drivers/video/drm/radeon/rn50_reg_safe.h
0,0 → 1,28
static const unsigned rn50_reg_safe_bm[102] = {
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF,
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF,
};
/drivers/video/drm/radeon/rs400.c
25,8 → 25,8
* Alex Deucher
* Jerome Glisse
*/
//#include <linux/seq_file.h>
#include <drmP.h>
#include <linux/seq_file.h>
#include <drm/drmP.h>
#include "radeon_reg.h"
#include "radeon.h"
 
62,7 → 62,7
break;
default:
DRM_ERROR("Unable to use IGP GART size %uM\n",
rdev->mc.gtt_size >> 20);
(unsigned)(rdev->mc.gtt_size >> 20));
DRM_ERROR("Valid GART size for IGP are 32M,64M,128M,256M,512M,1G,2G\n");
DRM_ERROR("Forcing to 32M GART size\n");
rdev->mc.gtt_size = 32 * 1024 * 1024;
92,21 → 92,42
WREG32_MC(RS480_GART_CACHE_CNTRL, 0);
}
 
int rs400_gart_enable(struct radeon_device *rdev)
int rs400_gart_init(struct radeon_device *rdev)
{
uint32_t size_reg;
uint32_t tmp;
int r;
 
if (rdev->gart.table.ram.ptr) {
WARN(1, "RS400 GART already initialized.\n");
return 0;
}
/* Check gart size */
switch(rdev->mc.gtt_size / (1024 * 1024)) {
case 32:
case 64:
case 128:
case 256:
case 512:
case 1024:
case 2048:
break;
default:
return -EINVAL;
}
/* Initialize common gart structure */
r = radeon_gart_init(rdev);
if (r) {
if (r)
return r;
}
if (rs400_debugfs_pcie_gart_info_init(rdev)) {
if (rs400_debugfs_pcie_gart_info_init(rdev))
DRM_ERROR("Failed to register debugfs file for RS400 GART !\n");
rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
return radeon_gart_table_ram_alloc(rdev);
}
 
int rs400_gart_enable(struct radeon_device *rdev)
{
uint32_t size_reg;
uint32_t tmp;
 
tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH);
tmp |= RS690_DIS_OUT_OF_PCI_GART_ACCESS;
WREG32_MC(RS690_AIC_CTRL_SCRATCH, tmp);
136,13 → 157,6
default:
return -EINVAL;
}
if (rdev->gart.table.ram.ptr == NULL) {
rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
r = radeon_gart_table_ram_alloc(rdev);
if (r) {
return r;
}
}
/* It should be fine to program it to max value */
if (rdev->family == CHIP_RS690 || (rdev->family == CHIP_RS740)) {
WREG32_MC(RS690_MCCFG_AGP_BASE, 0xFFFFFFFF);
164,7 → 178,9
WREG32(RADEON_BUS_CNTL, tmp);
}
/* Table should be in 32bits address space so ignore bits above. */
tmp = rdev->gart.table_addr & 0xfffff000;
tmp = (u32)rdev->gart.table_addr & 0xfffff000;
tmp |= (upper_32_bits(rdev->gart.table_addr) & 0xff) << 4;
 
WREG32_MC(RS480_GART_BASE, tmp);
/* TODO: more tweaking here */
WREG32_MC(RS480_GART_FEATURE_ID,
199,12 → 215,26
WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, 0);
}
 
void rs400_gart_fini(struct radeon_device *rdev)
{
rs400_gart_disable(rdev);
radeon_gart_table_ram_free(rdev);
radeon_gart_fini(rdev);
}
 
int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
{
uint32_t entry;
 
if (i < 0 || i > rdev->gart.num_gpu_pages) {
return -EINVAL;
}
rdev->gart.table.ram.ptr[i] = cpu_to_le32(((uint32_t)addr) | 0xC);
 
entry = (lower_32_bits(addr) & PAGE_MASK) |
((upper_32_bits(addr) & 0xff) << 4) |
0xc;
entry = cpu_to_le32(entry);
rdev->gart.table.ram.ptr[i] = entry;
return 0;
}
 
223,10 → 253,9
 
rs400_gpu_init(rdev);
rs400_gart_disable(rdev);
rdev->mc.gtt_location = rdev->mc.vram_size;
rdev->mc.gtt_location = rdev->mc.mc_vram_size;
rdev->mc.gtt_location += (rdev->mc.gtt_size - 1);
rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1);
rdev->mc.vram_location = 0xFFFFFFFFUL;
r = radeon_mc_setup(rdev);
if (r) {
return r;
238,7 → 267,7
"programming pipes. Bad things might happen.\n");
}
 
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1;
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16);
tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16);
WREG32(RADEON_MC_FB_LOCATION, tmp);
247,14 → 276,12
(void)RREG32(RADEON_HOST_PATH_CNTL);
WREG32(RADEON_HOST_PATH_CNTL, tmp);
(void)RREG32(RADEON_HOST_PATH_CNTL);
 
return 0;
}
 
void rs400_mc_fini(struct radeon_device *rdev)
{
rs400_gart_disable(rdev);
radeon_gart_table_ram_free(rdev);
radeon_gart_fini(rdev);
}
 
 
284,21 → 311,12
*/
void rs400_vram_info(struct radeon_device *rdev)
{
uint32_t tom;
 
rs400_gart_adjust_size(rdev);
/* DDR for all card after R300 & IGP */
rdev->mc.vram_is_ddr = true;
rdev->mc.vram_width = 128;
 
/* read NB_TOM to get the amount of ram stolen for the GPU */
tom = RREG32(RADEON_NB_TOM);
rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16);
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size);
 
/* Could aper size report 0 ? */
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
r100_vram_init_sizes(rdev);
}
 
 
/drivers/video/drm/radeon/rs600.c
28,7 → 28,10
#include "drmP.h"
#include "radeon_reg.h"
#include "radeon.h"
#include "avivod.h"
 
#include "rs600_reg_safe.h"
 
/* rs600 depends on : */
void r100_hdp_reset(struct radeon_device *rdev);
int r100_gui_wait_for_idle(struct radeon_device *rdev);
223,7 → 226,7
printk(KERN_WARNING "Failed to wait MC idle while "
"programming pipes. Bad things might happen.\n");
}
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1;
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(RS600_MC_FB_TOP, tmp >> 16);
tmp |= REG_SET(RS600_MC_FB_START, rdev->mc.vram_location >> 16);
WREG32_MC(RS600_MC_FB_LOCATION, tmp);
301,7 → 304,12
rdev->mc.vram_width = 128;
}
 
void rs600_bandwidth_update(struct radeon_device *rdev)
{
/* FIXME: implement, should this be like rs690 ? */
}
 
 
/*
* Indirect registers accessor
*/
/drivers/video/drm/radeon/rs600_reg_safe.h
0,0 → 1,57
static const unsigned rs600_reg_safe_bm[219] = {
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF,
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000,
0xF0000078, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFC78, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
0x38FF8F50, 0xFFF88082, 0xF000000C, 0xFAE009FF,
0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
0x00000000, 0x0000C100, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0xFFFF0000, 0xFFFFFFFF, 0xFF80FFFF,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x0003FC01, 0xFFFFFCF8, 0xFF800B19, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
};
/drivers/video/drm/radeon/rs690.c
28,6 → 28,9
#include "drmP.h"
#include "radeon_reg.h"
#include "radeon.h"
#include "rs690r.h"
#include "atom.h"
#include "atom-bits.h"
 
/* rs690,rs740 depends on : */
void r100_hdp_reset(struct radeon_device *rdev);
64,7 → 67,7
rs400_gart_disable(rdev);
 
/* Setup GPU memory space */
rdev->mc.gtt_location = rdev->mc.vram_size;
rdev->mc.gtt_location = rdev->mc.mc_vram_size;
rdev->mc.gtt_location += (rdev->mc.gtt_size - 1);
rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1);
rdev->mc.vram_location = 0xFFFFFFFFUL;
79,7 → 82,7
printk(KERN_WARNING "Failed to wait MC idle while "
"programming pipes. Bad things might happen.\n");
}
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1;
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(RS690_MC_FB_TOP, tmp >> 16);
tmp |= REG_SET(RS690_MC_FB_START, rdev->mc.vram_location >> 16);
WREG32_MC(RS690_MCCFG_FB_LOCATION, tmp);
91,9 → 94,6
 
void rs690_mc_fini(struct radeon_device *rdev)
{
rs400_gart_disable(rdev);
radeon_gart_table_ram_free(rdev);
radeon_gart_fini(rdev);
}
 
 
138,9 → 138,82
/*
* VRAM info.
*/
void rs690_pm_info(struct radeon_device *rdev)
{
int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo);
struct _ATOM_INTEGRATED_SYSTEM_INFO *info;
struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *info_v2;
void *ptr;
uint16_t data_offset;
uint8_t frev, crev;
fixed20_12 tmp;
 
atom_parse_data_header(rdev->mode_info.atom_context, index, NULL,
&frev, &crev, &data_offset);
ptr = rdev->mode_info.atom_context->bios + data_offset;
info = (struct _ATOM_INTEGRATED_SYSTEM_INFO *)ptr;
info_v2 = (struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 *)ptr;
/* Get various system informations from bios */
switch (crev) {
case 1:
tmp.full = rfixed_const(100);
rdev->pm.igp_sideport_mclk.full = rfixed_const(info->ulBootUpMemoryClock);
rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
rdev->pm.igp_system_mclk.full = rfixed_const(le16_to_cpu(info->usK8MemoryClock));
rdev->pm.igp_ht_link_clk.full = rfixed_const(le16_to_cpu(info->usFSBClock));
rdev->pm.igp_ht_link_width.full = rfixed_const(info->ucHTLinkWidth);
break;
case 2:
tmp.full = rfixed_const(100);
rdev->pm.igp_sideport_mclk.full = rfixed_const(info_v2->ulBootUpSidePortClock);
rdev->pm.igp_sideport_mclk.full = rfixed_div(rdev->pm.igp_sideport_mclk, tmp);
rdev->pm.igp_system_mclk.full = rfixed_const(info_v2->ulBootUpUMAClock);
rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp);
rdev->pm.igp_ht_link_clk.full = rfixed_const(info_v2->ulHTLinkFreq);
rdev->pm.igp_ht_link_clk.full = rfixed_div(rdev->pm.igp_ht_link_clk, tmp);
rdev->pm.igp_ht_link_width.full = rfixed_const(le16_to_cpu(info_v2->usMinHTLinkWidth));
break;
default:
tmp.full = rfixed_const(100);
/* We assume the slower possible clock ie worst case */
/* DDR 333Mhz */
rdev->pm.igp_sideport_mclk.full = rfixed_const(333);
/* FIXME: system clock ? */
rdev->pm.igp_system_mclk.full = rfixed_const(100);
rdev->pm.igp_system_mclk.full = rfixed_div(rdev->pm.igp_system_mclk, tmp);
rdev->pm.igp_ht_link_clk.full = rfixed_const(200);
rdev->pm.igp_ht_link_width.full = rfixed_const(8);
DRM_ERROR("No integrated system info for your GPU, using safe default\n");
break;
}
/* Compute various bandwidth */
/* k8_bandwidth = (memory_clk / 2) * 2 * 8 * 0.5 = memory_clk * 4 */
tmp.full = rfixed_const(4);
rdev->pm.k8_bandwidth.full = rfixed_mul(rdev->pm.igp_system_mclk, tmp);
/* ht_bandwidth = ht_clk * 2 * ht_width / 8 * 0.8
* = ht_clk * ht_width / 5
*/
tmp.full = rfixed_const(5);
rdev->pm.ht_bandwidth.full = rfixed_mul(rdev->pm.igp_ht_link_clk,
rdev->pm.igp_ht_link_width);
rdev->pm.ht_bandwidth.full = rfixed_div(rdev->pm.ht_bandwidth, tmp);
if (tmp.full < rdev->pm.max_bandwidth.full) {
/* HT link is a limiting factor */
rdev->pm.max_bandwidth.full = tmp.full;
}
/* sideport_bandwidth = (sideport_clk / 2) * 2 * 2 * 0.7
* = (sideport_clk * 14) / 10
*/
tmp.full = rfixed_const(14);
rdev->pm.sideport_bandwidth.full = rfixed_mul(rdev->pm.igp_sideport_mclk, tmp);
tmp.full = rfixed_const(10);
rdev->pm.sideport_bandwidth.full = rfixed_div(rdev->pm.sideport_bandwidth, tmp);
}
 
void rs690_vram_info(struct radeon_device *rdev)
{
uint32_t tmp;
fixed20_12 a;
 
rs400_gart_adjust_size(rdev);
/* DDR for all card after R300 & IGP */
152,14 → 225,411
} else {
rdev->mc.vram_width = 64;
}
rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
 
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
rs690_pm_info(rdev);
/* FIXME: we should enforce default clock in case GPU is not in
* default setup
*/
a.full = rfixed_const(100);
rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
a.full = rfixed_const(16);
/* core_bandwidth = sclk(Mhz) * 16 */
rdev->pm.core_bandwidth.full = rfixed_div(rdev->pm.sclk, a);
}
 
void rs690_line_buffer_adjust(struct radeon_device *rdev,
struct drm_display_mode *mode1,
struct drm_display_mode *mode2)
{
u32 tmp;
 
/*
* Line Buffer Setup
* There is a single line buffer shared by both display controllers.
* DC_LB_MEMORY_SPLIT controls how that line buffer is shared between
* the display controllers. The paritioning can either be done
* manually or via one of four preset allocations specified in bits 1:0:
* 0 - line buffer is divided in half and shared between crtc
* 1 - D1 gets 3/4 of the line buffer, D2 gets 1/4
* 2 - D1 gets the whole buffer
* 3 - D1 gets 1/4 of the line buffer, D2 gets 3/4
* Setting bit 2 of DC_LB_MEMORY_SPLIT controls switches to manual
* allocation mode. In manual allocation mode, D1 always starts at 0,
* D1 end/2 is specified in bits 14:4; D2 allocation follows D1.
*/
tmp = RREG32(DC_LB_MEMORY_SPLIT) & ~DC_LB_MEMORY_SPLIT_MASK;
tmp &= ~DC_LB_MEMORY_SPLIT_SHIFT_MODE;
/* auto */
if (mode1 && mode2) {
if (mode1->hdisplay > mode2->hdisplay) {
if (mode1->hdisplay > 2560)
tmp |= DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q;
else
tmp |= DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
} else if (mode2->hdisplay > mode1->hdisplay) {
if (mode2->hdisplay > 2560)
tmp |= DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
else
tmp |= DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
} else
tmp |= AVIVO_DC_LB_MEMORY_SPLIT_D1HALF_D2HALF;
} else if (mode1) {
tmp |= DC_LB_MEMORY_SPLIT_D1_ONLY;
} else if (mode2) {
tmp |= DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q;
}
WREG32(DC_LB_MEMORY_SPLIT, tmp);
}
 
struct rs690_watermark {
u32 lb_request_fifo_depth;
fixed20_12 num_line_pair;
fixed20_12 estimated_width;
fixed20_12 worst_case_latency;
fixed20_12 consumption_rate;
fixed20_12 active_time;
fixed20_12 dbpp;
fixed20_12 priority_mark_max;
fixed20_12 priority_mark;
fixed20_12 sclk;
};
 
void rs690_crtc_bandwidth_compute(struct radeon_device *rdev,
struct radeon_crtc *crtc,
struct rs690_watermark *wm)
{
struct drm_display_mode *mode = &crtc->base.mode;
fixed20_12 a, b, c;
fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width;
fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency;
/* FIXME: detect IGP with sideport memory, i don't think there is any
* such product available
*/
bool sideport = false;
 
if (!crtc->base.enabled) {
/* FIXME: wouldn't it better to set priority mark to maximum */
wm->lb_request_fifo_depth = 4;
return;
}
 
if (crtc->vsc.full > rfixed_const(2))
wm->num_line_pair.full = rfixed_const(2);
else
wm->num_line_pair.full = rfixed_const(1);
 
b.full = rfixed_const(mode->crtc_hdisplay);
c.full = rfixed_const(256);
a.full = rfixed_mul(wm->num_line_pair, b);
request_fifo_depth.full = rfixed_div(a, c);
if (a.full < rfixed_const(4)) {
wm->lb_request_fifo_depth = 4;
} else {
wm->lb_request_fifo_depth = rfixed_trunc(request_fifo_depth);
}
 
/* Determine consumption rate
* pclk = pixel clock period(ns) = 1000 / (mode.clock / 1000)
* vtaps = number of vertical taps,
* vsc = vertical scaling ratio, defined as source/destination
* hsc = horizontal scaling ration, defined as source/destination
*/
a.full = rfixed_const(mode->clock);
b.full = rfixed_const(1000);
a.full = rfixed_div(a, b);
pclk.full = rfixed_div(b, a);
if (crtc->rmx_type != RMX_OFF) {
b.full = rfixed_const(2);
if (crtc->vsc.full > b.full)
b.full = crtc->vsc.full;
b.full = rfixed_mul(b, crtc->hsc);
c.full = rfixed_const(2);
b.full = rfixed_div(b, c);
consumption_time.full = rfixed_div(pclk, b);
} else {
consumption_time.full = pclk.full;
}
a.full = rfixed_const(1);
wm->consumption_rate.full = rfixed_div(a, consumption_time);
 
 
/* Determine line time
* LineTime = total time for one line of displayhtotal
* LineTime = total number of horizontal pixels
* pclk = pixel clock period(ns)
*/
a.full = rfixed_const(crtc->base.mode.crtc_htotal);
line_time.full = rfixed_mul(a, pclk);
 
/* Determine active time
* ActiveTime = time of active region of display within one line,
* hactive = total number of horizontal active pixels
* htotal = total number of horizontal pixels
*/
a.full = rfixed_const(crtc->base.mode.crtc_htotal);
b.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
wm->active_time.full = rfixed_mul(line_time, b);
wm->active_time.full = rfixed_div(wm->active_time, a);
 
/* Maximun bandwidth is the minimun bandwidth of all component */
rdev->pm.max_bandwidth = rdev->pm.core_bandwidth;
if (sideport) {
if (rdev->pm.max_bandwidth.full > rdev->pm.sideport_bandwidth.full &&
rdev->pm.sideport_bandwidth.full)
rdev->pm.max_bandwidth = rdev->pm.sideport_bandwidth;
read_delay_latency.full = rfixed_const(370 * 800 * 1000);
read_delay_latency.full = rfixed_div(read_delay_latency,
rdev->pm.igp_sideport_mclk);
} else {
if (rdev->pm.max_bandwidth.full > rdev->pm.k8_bandwidth.full &&
rdev->pm.k8_bandwidth.full)
rdev->pm.max_bandwidth = rdev->pm.k8_bandwidth;
if (rdev->pm.max_bandwidth.full > rdev->pm.ht_bandwidth.full &&
rdev->pm.ht_bandwidth.full)
rdev->pm.max_bandwidth = rdev->pm.ht_bandwidth;
read_delay_latency.full = rfixed_const(5000);
}
 
/* sclk = system clocks(ns) = 1000 / max_bandwidth / 16 */
a.full = rfixed_const(16);
rdev->pm.sclk.full = rfixed_mul(rdev->pm.max_bandwidth, a);
a.full = rfixed_const(1000);
rdev->pm.sclk.full = rfixed_div(a, rdev->pm.sclk);
/* Determine chunk time
* ChunkTime = the time it takes the DCP to send one chunk of data
* to the LB which consists of pipeline delay and inter chunk gap
* sclk = system clock(ns)
*/
a.full = rfixed_const(256 * 13);
chunk_time.full = rfixed_mul(rdev->pm.sclk, a);
a.full = rfixed_const(10);
chunk_time.full = rfixed_div(chunk_time, a);
 
/* Determine the worst case latency
* NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines)
* WorstCaseLatency = worst case time from urgent to when the MC starts
* to return data
* READ_DELAY_IDLE_MAX = constant of 1us
* ChunkTime = time it takes the DCP to send one chunk of data to the LB
* which consists of pipeline delay and inter chunk gap
*/
if (rfixed_trunc(wm->num_line_pair) > 1) {
a.full = rfixed_const(3);
wm->worst_case_latency.full = rfixed_mul(a, chunk_time);
wm->worst_case_latency.full += read_delay_latency.full;
} else {
a.full = rfixed_const(2);
wm->worst_case_latency.full = rfixed_mul(a, chunk_time);
wm->worst_case_latency.full += read_delay_latency.full;
}
 
/* Determine the tolerable latency
* TolerableLatency = Any given request has only 1 line time
* for the data to be returned
* LBRequestFifoDepth = Number of chunk requests the LB can
* put into the request FIFO for a display
* LineTime = total time for one line of display
* ChunkTime = the time it takes the DCP to send one chunk
* of data to the LB which consists of
* pipeline delay and inter chunk gap
*/
if ((2+wm->lb_request_fifo_depth) >= rfixed_trunc(request_fifo_depth)) {
tolerable_latency.full = line_time.full;
} else {
tolerable_latency.full = rfixed_const(wm->lb_request_fifo_depth - 2);
tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full;
tolerable_latency.full = rfixed_mul(tolerable_latency, chunk_time);
tolerable_latency.full = line_time.full - tolerable_latency.full;
}
/* We assume worst case 32bits (4 bytes) */
wm->dbpp.full = rfixed_const(4 * 8);
 
/* Determine the maximum priority mark
* width = viewport width in pixels
*/
a.full = rfixed_const(16);
wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a);
 
/* Determine estimated width */
estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full;
estimated_width.full = rfixed_div(estimated_width, consumption_time);
if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) {
wm->priority_mark.full = rfixed_const(10);
} else {
a.full = rfixed_const(16);
wm->priority_mark.full = rfixed_div(estimated_width, a);
wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full;
}
}
 
void rs690_bandwidth_update(struct radeon_device *rdev)
{
struct drm_display_mode *mode0 = NULL;
struct drm_display_mode *mode1 = NULL;
struct rs690_watermark wm0;
struct rs690_watermark wm1;
u32 tmp;
fixed20_12 priority_mark02, priority_mark12, fill_rate;
fixed20_12 a, b;
 
if (rdev->mode_info.crtcs[0]->base.enabled)
mode0 = &rdev->mode_info.crtcs[0]->base.mode;
if (rdev->mode_info.crtcs[1]->base.enabled)
mode1 = &rdev->mode_info.crtcs[1]->base.mode;
/*
* Set display0/1 priority up in the memory controller for
* modes if the user specifies HIGH for displaypriority
* option.
*/
if (rdev->disp_priority == 2) {
tmp = RREG32_MC(MC_INIT_MISC_LAT_TIMER);
tmp &= ~MC_DISP1R_INIT_LAT_MASK;
tmp &= ~MC_DISP0R_INIT_LAT_MASK;
if (mode1)
tmp |= (1 << MC_DISP1R_INIT_LAT_SHIFT);
if (mode0)
tmp |= (1 << MC_DISP0R_INIT_LAT_SHIFT);
WREG32_MC(MC_INIT_MISC_LAT_TIMER, tmp);
}
rs690_line_buffer_adjust(rdev, mode0, mode1);
 
if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740))
WREG32(DCP_CONTROL, 0);
if ((rdev->family == CHIP_RS780) || (rdev->family == CHIP_RS880))
WREG32(DCP_CONTROL, 2);
 
rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0);
rs690_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1);
 
tmp = (wm0.lb_request_fifo_depth - 1);
tmp |= (wm1.lb_request_fifo_depth - 1) << 16;
WREG32(LB_MAX_REQ_OUTSTANDING, tmp);
 
if (mode0 && mode1) {
if (rfixed_trunc(wm0.dbpp) > 64)
a.full = rfixed_mul(wm0.dbpp, wm0.num_line_pair);
else
a.full = wm0.num_line_pair.full;
if (rfixed_trunc(wm1.dbpp) > 64)
b.full = rfixed_mul(wm1.dbpp, wm1.num_line_pair);
else
b.full = wm1.num_line_pair.full;
a.full += b.full;
fill_rate.full = rfixed_div(wm0.sclk, a);
if (wm0.consumption_rate.full > fill_rate.full) {
b.full = wm0.consumption_rate.full - fill_rate.full;
b.full = rfixed_mul(b, wm0.active_time);
a.full = rfixed_mul(wm0.worst_case_latency,
wm0.consumption_rate);
a.full = a.full + b.full;
b.full = rfixed_const(16 * 1000);
priority_mark02.full = rfixed_div(a, b);
} else {
a.full = rfixed_mul(wm0.worst_case_latency,
wm0.consumption_rate);
b.full = rfixed_const(16 * 1000);
priority_mark02.full = rfixed_div(a, b);
}
if (wm1.consumption_rate.full > fill_rate.full) {
b.full = wm1.consumption_rate.full - fill_rate.full;
b.full = rfixed_mul(b, wm1.active_time);
a.full = rfixed_mul(wm1.worst_case_latency,
wm1.consumption_rate);
a.full = a.full + b.full;
b.full = rfixed_const(16 * 1000);
priority_mark12.full = rfixed_div(a, b);
} else {
a.full = rfixed_mul(wm1.worst_case_latency,
wm1.consumption_rate);
b.full = rfixed_const(16 * 1000);
priority_mark12.full = rfixed_div(a, b);
}
if (wm0.priority_mark.full > priority_mark02.full)
priority_mark02.full = wm0.priority_mark.full;
if (rfixed_trunc(priority_mark02) < 0)
priority_mark02.full = 0;
if (wm0.priority_mark_max.full > priority_mark02.full)
priority_mark02.full = wm0.priority_mark_max.full;
if (wm1.priority_mark.full > priority_mark12.full)
priority_mark12.full = wm1.priority_mark.full;
if (rfixed_trunc(priority_mark12) < 0)
priority_mark12.full = 0;
if (wm1.priority_mark_max.full > priority_mark12.full)
priority_mark12.full = wm1.priority_mark_max.full;
WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
} else if (mode0) {
if (rfixed_trunc(wm0.dbpp) > 64)
a.full = rfixed_mul(wm0.dbpp, wm0.num_line_pair);
else
a.full = wm0.num_line_pair.full;
fill_rate.full = rfixed_div(wm0.sclk, a);
if (wm0.consumption_rate.full > fill_rate.full) {
b.full = wm0.consumption_rate.full - fill_rate.full;
b.full = rfixed_mul(b, wm0.active_time);
a.full = rfixed_mul(wm0.worst_case_latency,
wm0.consumption_rate);
a.full = a.full + b.full;
b.full = rfixed_const(16 * 1000);
priority_mark02.full = rfixed_div(a, b);
} else {
a.full = rfixed_mul(wm0.worst_case_latency,
wm0.consumption_rate);
b.full = rfixed_const(16 * 1000);
priority_mark02.full = rfixed_div(a, b);
}
if (wm0.priority_mark.full > priority_mark02.full)
priority_mark02.full = wm0.priority_mark.full;
if (rfixed_trunc(priority_mark02) < 0)
priority_mark02.full = 0;
if (wm0.priority_mark_max.full > priority_mark02.full)
priority_mark02.full = wm0.priority_mark_max.full;
WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
} else {
if (rfixed_trunc(wm1.dbpp) > 64)
a.full = rfixed_mul(wm1.dbpp, wm1.num_line_pair);
else
a.full = wm1.num_line_pair.full;
fill_rate.full = rfixed_div(wm1.sclk, a);
if (wm1.consumption_rate.full > fill_rate.full) {
b.full = wm1.consumption_rate.full - fill_rate.full;
b.full = rfixed_mul(b, wm1.active_time);
a.full = rfixed_mul(wm1.worst_case_latency,
wm1.consumption_rate);
a.full = a.full + b.full;
b.full = rfixed_const(16 * 1000);
priority_mark12.full = rfixed_div(a, b);
} else {
a.full = rfixed_mul(wm1.worst_case_latency,
wm1.consumption_rate);
b.full = rfixed_const(16 * 1000);
priority_mark12.full = rfixed_div(a, b);
}
if (wm1.priority_mark.full > priority_mark12.full)
priority_mark12.full = wm1.priority_mark.full;
if (rfixed_trunc(priority_mark12) < 0)
priority_mark12.full = 0;
if (wm1.priority_mark_max.full > priority_mark12.full)
priority_mark12.full = wm1.priority_mark_max.full;
WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
}
}
 
/*
* Indirect registers accessor
*/
uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg)
/drivers/video/drm/radeon/rs690r.h
0,0 → 1,99
/*
* Copyright 2008 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
* Copyright 2009 Jerome Glisse.
*
* 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
* Jerome Glisse
*/
#ifndef RS690R_H
#define RS690R_H
 
/* RS690/RS740 registers */
#define MC_INDEX 0x0078
# define MC_INDEX_MASK 0x1FF
# define MC_INDEX_WR_EN (1 << 9)
# define MC_INDEX_WR_ACK 0x7F
#define MC_DATA 0x007C
#define HDP_FB_LOCATION 0x0134
#define DC_LB_MEMORY_SPLIT 0x6520
#define DC_LB_MEMORY_SPLIT_MASK 0x00000003
#define DC_LB_MEMORY_SPLIT_SHIFT 0
#define DC_LB_MEMORY_SPLIT_D1HALF_D2HALF 0
#define DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q 1
#define DC_LB_MEMORY_SPLIT_D1_ONLY 2
#define DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q 3
#define DC_LB_MEMORY_SPLIT_SHIFT_MODE (1 << 2)
#define DC_LB_DISP1_END_ADR_SHIFT 4
#define DC_LB_DISP1_END_ADR_MASK 0x00007FF0
#define D1MODE_PRIORITY_A_CNT 0x6548
#define MODE_PRIORITY_MARK_MASK 0x00007FFF
#define MODE_PRIORITY_OFF (1 << 16)
#define MODE_PRIORITY_ALWAYS_ON (1 << 20)
#define MODE_PRIORITY_FORCE_MASK (1 << 24)
#define D1MODE_PRIORITY_B_CNT 0x654C
#define LB_MAX_REQ_OUTSTANDING 0x6D58
#define LB_D1_MAX_REQ_OUTSTANDING_MASK 0x0000000F
#define LB_D1_MAX_REQ_OUTSTANDING_SHIFT 0
#define LB_D2_MAX_REQ_OUTSTANDING_MASK 0x000F0000
#define LB_D2_MAX_REQ_OUTSTANDING_SHIFT 16
#define DCP_CONTROL 0x6C9C
#define D2MODE_PRIORITY_A_CNT 0x6D48
#define D2MODE_PRIORITY_B_CNT 0x6D4C
 
/* MC indirect registers */
#define MC_STATUS_IDLE (1 << 0)
#define MC_MISC_CNTL 0x18
#define DISABLE_GTW (1 << 1)
#define GART_INDEX_REG_EN (1 << 12)
#define BLOCK_GFX_D3_EN (1 << 14)
#define GART_FEATURE_ID 0x2B
#define HANG_EN (1 << 11)
#define TLB_ENABLE (1 << 18)
#define P2P_ENABLE (1 << 19)
#define GTW_LAC_EN (1 << 25)
#define LEVEL2_GART (0 << 30)
#define LEVEL1_GART (1 << 30)
#define PDC_EN (1 << 31)
#define GART_BASE 0x2C
#define GART_CACHE_CNTRL 0x2E
# define GART_CACHE_INVALIDATE (1 << 0)
#define MC_STATUS 0x90
#define MCCFG_FB_LOCATION 0x100
#define MC_FB_START_MASK 0x0000FFFF
#define MC_FB_START_SHIFT 0
#define MC_FB_TOP_MASK 0xFFFF0000
#define MC_FB_TOP_SHIFT 16
#define MCCFG_AGP_LOCATION 0x101
#define MC_AGP_START_MASK 0x0000FFFF
#define MC_AGP_START_SHIFT 0
#define MC_AGP_TOP_MASK 0xFFFF0000
#define MC_AGP_TOP_SHIFT 16
#define MCCFG_AGP_BASE 0x102
#define MCCFG_AGP_BASE_2 0x103
#define MC_INIT_MISC_LAT_TIMER 0x104
#define MC_DISP0R_INIT_LAT_SHIFT 8
#define MC_DISP0R_INIT_LAT_MASK 0x00000F00
#define MC_DISP1R_INIT_LAT_SHIFT 12
#define MC_DISP1R_INIT_LAT_MASK 0x0000F000
 
#endif
/drivers/video/drm/radeon/rv515.c
25,11 → 25,12
* Alex Deucher
* Jerome Glisse
*/
//#include <linux/seq_file.h>
#include <linux/seq_file.h>
#include "drmP.h"
#include "radeon_reg.h"
#include "rv515d.h"
#include "radeon.h"
 
#include "rv515_reg_safe.h"
/* rv515 depends on : */
void r100_hdp_reset(struct radeon_device *rdev);
int r100_cp_reset(struct radeon_device *rdev);
36,8 → 37,6
int r100_rb2d_reset(struct radeon_device *rdev);
int r100_gui_wait_for_idle(struct radeon_device *rdev);
int r100_cp_init(struct radeon_device *rdev, unsigned ring_size);
int rv370_pcie_gart_enable(struct radeon_device *rdev);
void rv370_pcie_gart_disable(struct radeon_device *rdev);
void r420_pipes_init(struct radeon_device *rdev);
void rs600_mc_disable_clients(struct radeon_device *rdev);
void rs600_disable_vga(struct radeon_device *rdev);
52,6 → 51,7
void rv515_gpu_init(struct radeon_device *rdev);
int rv515_mc_wait_for_idle(struct radeon_device *rdev);
 
 
/*
* MC
*/
76,16 → 76,16
/* Setup GPU memory space */
rdev->mc.vram_location = 0xFFFFFFFFUL;
rdev->mc.gtt_location = 0xFFFFFFFFUL;
if (rdev->flags & RADEON_IS_AGP) {
r = radeon_agp_init(rdev);
if (r) {
printk(KERN_WARNING "[drm] Disabling AGP\n");
rdev->flags &= ~RADEON_IS_AGP;
rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
} else {
rdev->mc.gtt_location = rdev->mc.agp_base;
}
}
// if (rdev->flags & RADEON_IS_AGP) {
// r = radeon_agp_init(rdev);
// if (r) {
// printk(KERN_WARNING "[drm] Disabling AGP\n");
// rdev->flags &= ~RADEON_IS_AGP;
// rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
// } else {
// rdev->mc.gtt_location = rdev->mc.agp_base;
// }
// }
r = radeon_mc_setup(rdev);
if (r) {
return r;
98,26 → 98,26
"programming pipes. Bad things might happen.\n");
}
/* Write VRAM size in case we are limiting it */
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size);
tmp = REG_SET(RV515_MC_FB_START, rdev->mc.vram_location >> 16);
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
tmp = REG_SET(MC_FB_START, rdev->mc.vram_location >> 16);
WREG32(0x134, tmp);
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1;
tmp = REG_SET(RV515_MC_FB_TOP, tmp >> 16);
tmp |= REG_SET(RV515_MC_FB_START, rdev->mc.vram_location >> 16);
WREG32_MC(RV515_MC_FB_LOCATION, tmp);
WREG32(RS690_HDP_FB_LOCATION, rdev->mc.vram_location >> 16);
tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(MC_FB_TOP, tmp >> 16);
tmp |= REG_SET(MC_FB_START, rdev->mc.vram_location >> 16);
WREG32_MC(MC_FB_LOCATION, tmp);
WREG32(HDP_FB_LOCATION, rdev->mc.vram_location >> 16);
WREG32(0x310, rdev->mc.vram_location);
if (rdev->flags & RADEON_IS_AGP) {
tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1;
tmp = REG_SET(RV515_MC_AGP_TOP, tmp >> 16);
tmp |= REG_SET(RV515_MC_AGP_START, rdev->mc.gtt_location >> 16);
WREG32_MC(RV515_MC_AGP_LOCATION, tmp);
WREG32_MC(RV515_MC_AGP_BASE, rdev->mc.agp_base);
WREG32_MC(RV515_MC_AGP_BASE_2, 0);
tmp = REG_SET(MC_AGP_TOP, tmp >> 16);
tmp |= REG_SET(MC_AGP_START, rdev->mc.gtt_location >> 16);
WREG32_MC(MC_AGP_LOCATION, tmp);
WREG32_MC(MC_AGP_BASE, rdev->mc.agp_base);
WREG32_MC(MC_AGP_BASE_2, 0);
} else {
WREG32_MC(RV515_MC_AGP_LOCATION, 0x0FFFFFFF);
WREG32_MC(RV515_MC_AGP_BASE, 0);
WREG32_MC(RV515_MC_AGP_BASE_2, 0);
WREG32_MC(MC_AGP_LOCATION, 0x0FFFFFFF);
WREG32_MC(MC_AGP_BASE, 0);
WREG32_MC(MC_AGP_BASE_2, 0);
}
return 0;
}
124,9 → 124,6
 
void rv515_mc_fini(struct radeon_device *rdev)
{
rv370_pcie_gart_disable(rdev);
radeon_gart_table_vram_free(rdev);
radeon_gart_fini(rdev);
}
 
 
135,101 → 132,74
*/
void rv515_ring_start(struct radeon_device *rdev)
{
unsigned gb_tile_config;
int r;
 
dbgprintf("%s\n",__FUNCTION__);
/* Sub pixel 1/12 so we can have 4K rendering according to doc */
gb_tile_config = R300_ENABLE_TILING | R300_TILE_SIZE_16;
switch (rdev->num_gb_pipes) {
case 2:
gb_tile_config |= R300_PIPE_COUNT_R300;
break;
case 3:
gb_tile_config |= R300_PIPE_COUNT_R420_3P;
break;
case 4:
gb_tile_config |= R300_PIPE_COUNT_R420;
break;
case 1:
default:
gb_tile_config |= R300_PIPE_COUNT_RV350;
break;
}
ENTER();
 
r = radeon_ring_lock(rdev, 64);
if (r) {
return;
}
radeon_ring_write(rdev, PACKET0(RADEON_ISYNC_CNTL, 0));
radeon_ring_write(rdev, PACKET0(ISYNC_CNTL, 0));
radeon_ring_write(rdev,
RADEON_ISYNC_ANY2D_IDLE3D |
RADEON_ISYNC_ANY3D_IDLE2D |
RADEON_ISYNC_WAIT_IDLEGUI |
RADEON_ISYNC_CPSCRATCH_IDLEGUI);
radeon_ring_write(rdev, PACKET0(R300_GB_TILE_CONFIG, 0));
radeon_ring_write(rdev, gb_tile_config);
radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
radeon_ring_write(rdev,
RADEON_WAIT_2D_IDLECLEAN |
RADEON_WAIT_3D_IDLECLEAN);
ISYNC_ANY2D_IDLE3D |
ISYNC_ANY3D_IDLE2D |
ISYNC_WAIT_IDLEGUI |
ISYNC_CPSCRATCH_IDLEGUI);
radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0));
radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN);
radeon_ring_write(rdev, PACKET0(0x170C, 0));
radeon_ring_write(rdev, 1 << 31);
radeon_ring_write(rdev, PACKET0(R300_GB_SELECT, 0));
radeon_ring_write(rdev, PACKET0(GB_SELECT, 0));
radeon_ring_write(rdev, 0);
radeon_ring_write(rdev, PACKET0(R300_GB_ENABLE, 0));
radeon_ring_write(rdev, PACKET0(GB_ENABLE, 0));
radeon_ring_write(rdev, 0);
radeon_ring_write(rdev, PACKET0(0x42C8, 0));
radeon_ring_write(rdev, (1 << rdev->num_gb_pipes) - 1);
radeon_ring_write(rdev, PACKET0(R500_VAP_INDEX_OFFSET, 0));
radeon_ring_write(rdev, PACKET0(VAP_INDEX_OFFSET, 0));
radeon_ring_write(rdev, 0);
radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
radeon_ring_write(rdev, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE);
radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
radeon_ring_write(rdev, R300_ZC_FLUSH | R300_ZC_FREE);
radeon_ring_write(rdev, PACKET0(RADEON_WAIT_UNTIL, 0));
radeon_ring_write(rdev,
RADEON_WAIT_2D_IDLECLEAN |
RADEON_WAIT_3D_IDLECLEAN);
radeon_ring_write(rdev, PACKET0(R300_GB_AA_CONFIG, 0));
radeon_ring_write(rdev, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0));
radeon_ring_write(rdev, RB3D_DC_FLUSH | RB3D_DC_FREE);
radeon_ring_write(rdev, PACKET0(ZB_ZCACHE_CTLSTAT, 0));
radeon_ring_write(rdev, ZC_FLUSH | ZC_FREE);
radeon_ring_write(rdev, PACKET0(WAIT_UNTIL, 0));
radeon_ring_write(rdev, WAIT_2D_IDLECLEAN | WAIT_3D_IDLECLEAN);
radeon_ring_write(rdev, PACKET0(GB_AA_CONFIG, 0));
radeon_ring_write(rdev, 0);
radeon_ring_write(rdev, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
radeon_ring_write(rdev, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE);
radeon_ring_write(rdev, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
radeon_ring_write(rdev, R300_ZC_FLUSH | R300_ZC_FREE);
radeon_ring_write(rdev, PACKET0(R300_GB_MSPOS0, 0));
radeon_ring_write(rdev, PACKET0(RB3D_DSTCACHE_CTLSTAT, 0));
radeon_ring_write(rdev, RB3D_DC_FLUSH | RB3D_DC_FREE);
radeon_ring_write(rdev, PACKET0(ZB_ZCACHE_CTLSTAT, 0));
radeon_ring_write(rdev, ZC_FLUSH | ZC_FREE);
radeon_ring_write(rdev, PACKET0(GB_MSPOS0, 0));
radeon_ring_write(rdev,
((6 << R300_MS_X0_SHIFT) |
(6 << R300_MS_Y0_SHIFT) |
(6 << R300_MS_X1_SHIFT) |
(6 << R300_MS_Y1_SHIFT) |
(6 << R300_MS_X2_SHIFT) |
(6 << R300_MS_Y2_SHIFT) |
(6 << R300_MSBD0_Y_SHIFT) |
(6 << R300_MSBD0_X_SHIFT)));
radeon_ring_write(rdev, PACKET0(R300_GB_MSPOS1, 0));
((6 << MS_X0_SHIFT) |
(6 << MS_Y0_SHIFT) |
(6 << MS_X1_SHIFT) |
(6 << MS_Y1_SHIFT) |
(6 << MS_X2_SHIFT) |
(6 << MS_Y2_SHIFT) |
(6 << MSBD0_Y_SHIFT) |
(6 << MSBD0_X_SHIFT)));
radeon_ring_write(rdev, PACKET0(GB_MSPOS1, 0));
radeon_ring_write(rdev,
((6 << R300_MS_X3_SHIFT) |
(6 << R300_MS_Y3_SHIFT) |
(6 << R300_MS_X4_SHIFT) |
(6 << R300_MS_Y4_SHIFT) |
(6 << R300_MS_X5_SHIFT) |
(6 << R300_MS_Y5_SHIFT) |
(6 << R300_MSBD1_SHIFT)));
radeon_ring_write(rdev, PACKET0(R300_GA_ENHANCE, 0));
radeon_ring_write(rdev, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL);
radeon_ring_write(rdev, PACKET0(R300_GA_POLY_MODE, 0));
radeon_ring_write(rdev,
R300_FRONT_PTYPE_TRIANGE | R300_BACK_PTYPE_TRIANGE);
radeon_ring_write(rdev, PACKET0(R300_GA_ROUND_MODE, 0));
radeon_ring_write(rdev,
R300_GEOMETRY_ROUND_NEAREST |
R300_COLOR_ROUND_NEAREST);
((6 << MS_X3_SHIFT) |
(6 << MS_Y3_SHIFT) |
(6 << MS_X4_SHIFT) |
(6 << MS_Y4_SHIFT) |
(6 << MS_X5_SHIFT) |
(6 << MS_Y5_SHIFT) |
(6 << MSBD1_SHIFT)));
radeon_ring_write(rdev, PACKET0(GA_ENHANCE, 0));
radeon_ring_write(rdev, GA_DEADLOCK_CNTL | GA_FASTSYNC_CNTL);
radeon_ring_write(rdev, PACKET0(GA_POLY_MODE, 0));
radeon_ring_write(rdev, FRONT_PTYPE_TRIANGE | BACK_PTYPE_TRIANGE);
radeon_ring_write(rdev, PACKET0(GA_ROUND_MODE, 0));
radeon_ring_write(rdev, GEOMETRY_ROUND_NEAREST | COLOR_ROUND_NEAREST);
radeon_ring_write(rdev, PACKET0(0x20C8, 0));
radeon_ring_write(rdev, 0);
radeon_ring_unlock_commit(rdev);
 
dbgprintf("done %s\n",__FUNCTION__);
LEAVE();
 
}
 
245,8 → 215,8
 
for (i = 0; i < rdev->usec_timeout; i++) {
/* read MC_STATUS */
tmp = RREG32_MC(RV515_MC_STATUS);
if (tmp & RV515_MC_STATUS_IDLE) {
tmp = RREG32_MC(MC_STATUS);
if (tmp & MC_STATUS_IDLE) {
return 0;
}
DRM_UDELAY(1);
285,7 → 255,6
}
}
 
 
int rv515_ga_reset(struct radeon_device *rdev)
{
uint32_t tmp;
292,25 → 261,25
bool reinit_cp;
int i;
 
dbgprintf("%s\n",__FUNCTION__);
ENTER();
 
reinit_cp = rdev->cp.ready;
rdev->cp.ready = false;
for (i = 0; i < rdev->usec_timeout; i++) {
WREG32(RADEON_CP_CSQ_MODE, 0);
WREG32(RADEON_CP_CSQ_CNTL, 0);
WREG32(RADEON_RBBM_SOFT_RESET, 0x32005);
(void)RREG32(RADEON_RBBM_SOFT_RESET);
WREG32(CP_CSQ_MODE, 0);
WREG32(CP_CSQ_CNTL, 0);
WREG32(RBBM_SOFT_RESET, 0x32005);
(void)RREG32(RBBM_SOFT_RESET);
udelay(200);
WREG32(RADEON_RBBM_SOFT_RESET, 0);
WREG32(RBBM_SOFT_RESET, 0);
/* Wait to prevent race in RBBM_STATUS */
mdelay(1);
tmp = RREG32(RADEON_RBBM_STATUS);
tmp = RREG32(RBBM_STATUS);
if (tmp & ((1 << 20) | (1 << 26))) {
DRM_ERROR("VAP & CP still busy (RBBM_STATUS=0x%08X)\n", tmp);
/* GA still busy soft reset it */
WREG32(0x429C, 0x200);
WREG32(R300_VAP_PVS_STATE_FLUSH_REG, 0);
WREG32(VAP_PVS_STATE_FLUSH_REG, 0);
WREG32(0x43E0, 0);
WREG32(0x43E4, 0);
WREG32(0x24AC, 0);
317,13 → 286,13
}
/* Wait to prevent race in RBBM_STATUS */
mdelay(1);
tmp = RREG32(RADEON_RBBM_STATUS);
tmp = RREG32(RBBM_STATUS);
if (!(tmp & ((1 << 20) | (1 << 26)))) {
break;
}
}
for (i = 0; i < rdev->usec_timeout; i++) {
tmp = RREG32(RADEON_RBBM_STATUS);
tmp = RREG32(RBBM_STATUS);
if (!(tmp & ((1 << 20) | (1 << 26)))) {
DRM_INFO("GA reset succeed (RBBM_STATUS=0x%08X)\n",
tmp);
337,7 → 306,7
}
DRM_UDELAY(1);
}
tmp = RREG32(RADEON_RBBM_STATUS);
tmp = RREG32(RBBM_STATUS);
DRM_ERROR("Failed to reset GA ! (RBBM_STATUS=0x%08X)\n", tmp);
return -1;
}
346,10 → 315,10
{
uint32_t status;
 
dbgprintf("%s\n",__FUNCTION__);
ENTER();
 
/* reset order likely matter */
status = RREG32(RADEON_RBBM_STATUS);
status = RREG32(RBBM_STATUS);
/* reset HDP */
r100_hdp_reset(rdev);
/* reset rb2d */
361,12 → 330,12
rv515_ga_reset(rdev);
}
/* reset CP */
status = RREG32(RADEON_RBBM_STATUS);
status = RREG32(RBBM_STATUS);
if (status & (1 << 16)) {
r100_cp_reset(rdev);
}
/* Check if GPU is idle */
status = RREG32(RADEON_RBBM_STATUS);
status = RREG32(RBBM_STATUS);
if (status & (1 << 31)) {
DRM_ERROR("Failed to reset GPU (RBBM_STATUS=0x%08X)\n", status);
return -1;
385,8 → 354,7
 
rdev->mc.vram_width = 128;
rdev->mc.vram_is_ddr = true;
tmp = RREG32_MC(RV515_MC_CNTL);
tmp &= RV515_MEM_NUM_CHANNELS_MASK;
tmp = RREG32_MC(RV515_MC_CNTL) & MEM_NUM_CHANNELS_MASK;
switch (tmp) {
case 0:
rdev->mc.vram_width = 64;
402,11 → 370,17
 
void rv515_vram_info(struct radeon_device *rdev)
{
fixed20_12 a;
 
rv515_vram_get_type(rdev);
rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
 
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
r100_vram_init_sizes(rdev);
/* FIXME: we should enforce default clock in case GPU is not in
* default setup
*/
a.full = rfixed_const(100);
rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
}
 
 
417,38 → 391,19
{
uint32_t r;
 
WREG32(R520_MC_IND_INDEX, 0x7f0000 | (reg & 0xffff));
r = RREG32(R520_MC_IND_DATA);
WREG32(R520_MC_IND_INDEX, 0);
WREG32(MC_IND_INDEX, 0x7f0000 | (reg & 0xffff));
r = RREG32(MC_IND_DATA);
WREG32(MC_IND_INDEX, 0);
return r;
}
 
void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
{
WREG32(R520_MC_IND_INDEX, 0xff0000 | ((reg) & 0xffff));
WREG32(R520_MC_IND_DATA, (v));
WREG32(R520_MC_IND_INDEX, 0);
WREG32(MC_IND_INDEX, 0xff0000 | ((reg) & 0xffff));
WREG32(MC_IND_DATA, (v));
WREG32(MC_IND_INDEX, 0);
}
 
uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg)
{
uint32_t r;
 
WREG32(RADEON_PCIE_INDEX, ((reg) & 0x7ff));
(void)RREG32(RADEON_PCIE_INDEX);
r = RREG32(RADEON_PCIE_DATA);
return r;
}
 
void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
{
WREG32(RADEON_PCIE_INDEX, ((reg) & 0x7ff));
(void)RREG32(RADEON_PCIE_INDEX);
WREG32(RADEON_PCIE_DATA, (v));
(void)RREG32(RADEON_PCIE_DATA);
}
 
 
/*
* Debugfs info
*/
460,13 → 415,13
struct radeon_device *rdev = dev->dev_private;
uint32_t tmp;
 
tmp = RREG32(R400_GB_PIPE_SELECT);
tmp = RREG32(GB_PIPE_SELECT);
seq_printf(m, "GB_PIPE_SELECT 0x%08x\n", tmp);
tmp = RREG32(R500_SU_REG_DEST);
tmp = RREG32(SU_REG_DEST);
seq_printf(m, "SU_REG_DEST 0x%08x\n", tmp);
tmp = RREG32(R300_GB_TILE_CONFIG);
tmp = RREG32(GB_TILE_CONFIG);
seq_printf(m, "GB_TILE_CONFIG 0x%08x\n", tmp);
tmp = RREG32(R300_DST_PIPE_CONFIG);
tmp = RREG32(DST_PIPE_CONFIG);
seq_printf(m, "DST_PIPE_CONFIG 0x%08x\n", tmp);
return 0;
}
513,60 → 468,564
#endif
}
 
 
/*
* Asic initialization
*/
static const unsigned r500_reg_safe_bm[159] = {
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFBF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF,
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000,
0xF0000038, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x1FFFFC78, 0xFFFFE000, 0xFFFFFFFE, 0xFFFFFFFF,
0x38CF8F50, 0xFFF88082, 0xFF0000FC, 0xFAE009FF,
0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
0xFFFF8CFC, 0xFFFFC1FF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF80FFFF,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x0003FC01, 0x3FFFFCF8, 0xFE800B19,
int rv515_init(struct radeon_device *rdev)
{
ENTER();
 
rdev->config.r300.reg_safe_bm = rv515_reg_safe_bm;
rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(rv515_reg_safe_bm);
return 0;
}
 
void atom_rv515_force_tv_scaler(struct radeon_device *rdev, struct radeon_crtc *crtc)
{
int index_reg = 0x6578 + crtc->crtc_offset;
int data_reg = 0x657c + crtc->crtc_offset;
 
WREG32(0x659C + crtc->crtc_offset, 0x0);
WREG32(0x6594 + crtc->crtc_offset, 0x705);
WREG32(0x65A4 + crtc->crtc_offset, 0x10001);
WREG32(0x65D8 + crtc->crtc_offset, 0x0);
WREG32(0x65B0 + crtc->crtc_offset, 0x0);
WREG32(0x65C0 + crtc->crtc_offset, 0x0);
WREG32(0x65D4 + crtc->crtc_offset, 0x0);
WREG32(index_reg, 0x0);
WREG32(data_reg, 0x841880A8);
WREG32(index_reg, 0x1);
WREG32(data_reg, 0x84208680);
WREG32(index_reg, 0x2);
WREG32(data_reg, 0xBFF880B0);
WREG32(index_reg, 0x100);
WREG32(data_reg, 0x83D88088);
WREG32(index_reg, 0x101);
WREG32(data_reg, 0x84608680);
WREG32(index_reg, 0x102);
WREG32(data_reg, 0xBFF080D0);
WREG32(index_reg, 0x200);
WREG32(data_reg, 0x83988068);
WREG32(index_reg, 0x201);
WREG32(data_reg, 0x84A08680);
WREG32(index_reg, 0x202);
WREG32(data_reg, 0xBFF080F8);
WREG32(index_reg, 0x300);
WREG32(data_reg, 0x83588058);
WREG32(index_reg, 0x301);
WREG32(data_reg, 0x84E08660);
WREG32(index_reg, 0x302);
WREG32(data_reg, 0xBFF88120);
WREG32(index_reg, 0x400);
WREG32(data_reg, 0x83188040);
WREG32(index_reg, 0x401);
WREG32(data_reg, 0x85008660);
WREG32(index_reg, 0x402);
WREG32(data_reg, 0xBFF88150);
WREG32(index_reg, 0x500);
WREG32(data_reg, 0x82D88030);
WREG32(index_reg, 0x501);
WREG32(data_reg, 0x85408640);
WREG32(index_reg, 0x502);
WREG32(data_reg, 0xBFF88180);
WREG32(index_reg, 0x600);
WREG32(data_reg, 0x82A08018);
WREG32(index_reg, 0x601);
WREG32(data_reg, 0x85808620);
WREG32(index_reg, 0x602);
WREG32(data_reg, 0xBFF081B8);
WREG32(index_reg, 0x700);
WREG32(data_reg, 0x82608010);
WREG32(index_reg, 0x701);
WREG32(data_reg, 0x85A08600);
WREG32(index_reg, 0x702);
WREG32(data_reg, 0x800081F0);
WREG32(index_reg, 0x800);
WREG32(data_reg, 0x8228BFF8);
WREG32(index_reg, 0x801);
WREG32(data_reg, 0x85E085E0);
WREG32(index_reg, 0x802);
WREG32(data_reg, 0xBFF88228);
WREG32(index_reg, 0x10000);
WREG32(data_reg, 0x82A8BF00);
WREG32(index_reg, 0x10001);
WREG32(data_reg, 0x82A08CC0);
WREG32(index_reg, 0x10002);
WREG32(data_reg, 0x8008BEF8);
WREG32(index_reg, 0x10100);
WREG32(data_reg, 0x81F0BF28);
WREG32(index_reg, 0x10101);
WREG32(data_reg, 0x83608CA0);
WREG32(index_reg, 0x10102);
WREG32(data_reg, 0x8018BED0);
WREG32(index_reg, 0x10200);
WREG32(data_reg, 0x8148BF38);
WREG32(index_reg, 0x10201);
WREG32(data_reg, 0x84408C80);
WREG32(index_reg, 0x10202);
WREG32(data_reg, 0x8008BEB8);
WREG32(index_reg, 0x10300);
WREG32(data_reg, 0x80B0BF78);
WREG32(index_reg, 0x10301);
WREG32(data_reg, 0x85008C20);
WREG32(index_reg, 0x10302);
WREG32(data_reg, 0x8020BEA0);
WREG32(index_reg, 0x10400);
WREG32(data_reg, 0x8028BF90);
WREG32(index_reg, 0x10401);
WREG32(data_reg, 0x85E08BC0);
WREG32(index_reg, 0x10402);
WREG32(data_reg, 0x8018BE90);
WREG32(index_reg, 0x10500);
WREG32(data_reg, 0xBFB8BFB0);
WREG32(index_reg, 0x10501);
WREG32(data_reg, 0x86C08B40);
WREG32(index_reg, 0x10502);
WREG32(data_reg, 0x8010BE90);
WREG32(index_reg, 0x10600);
WREG32(data_reg, 0xBF58BFC8);
WREG32(index_reg, 0x10601);
WREG32(data_reg, 0x87A08AA0);
WREG32(index_reg, 0x10602);
WREG32(data_reg, 0x8010BE98);
WREG32(index_reg, 0x10700);
WREG32(data_reg, 0xBF10BFF0);
WREG32(index_reg, 0x10701);
WREG32(data_reg, 0x886089E0);
WREG32(index_reg, 0x10702);
WREG32(data_reg, 0x8018BEB0);
WREG32(index_reg, 0x10800);
WREG32(data_reg, 0xBED8BFE8);
WREG32(index_reg, 0x10801);
WREG32(data_reg, 0x89408940);
WREG32(index_reg, 0x10802);
WREG32(data_reg, 0xBFE8BED8);
WREG32(index_reg, 0x20000);
WREG32(data_reg, 0x80008000);
WREG32(index_reg, 0x20001);
WREG32(data_reg, 0x90008000);
WREG32(index_reg, 0x20002);
WREG32(data_reg, 0x80008000);
WREG32(index_reg, 0x20003);
WREG32(data_reg, 0x80008000);
WREG32(index_reg, 0x20100);
WREG32(data_reg, 0x80108000);
WREG32(index_reg, 0x20101);
WREG32(data_reg, 0x8FE0BF70);
WREG32(index_reg, 0x20102);
WREG32(data_reg, 0xBFE880C0);
WREG32(index_reg, 0x20103);
WREG32(data_reg, 0x80008000);
WREG32(index_reg, 0x20200);
WREG32(data_reg, 0x8018BFF8);
WREG32(index_reg, 0x20201);
WREG32(data_reg, 0x8F80BF08);
WREG32(index_reg, 0x20202);
WREG32(data_reg, 0xBFD081A0);
WREG32(index_reg, 0x20203);
WREG32(data_reg, 0xBFF88000);
WREG32(index_reg, 0x20300);
WREG32(data_reg, 0x80188000);
WREG32(index_reg, 0x20301);
WREG32(data_reg, 0x8EE0BEC0);
WREG32(index_reg, 0x20302);
WREG32(data_reg, 0xBFB082A0);
WREG32(index_reg, 0x20303);
WREG32(data_reg, 0x80008000);
WREG32(index_reg, 0x20400);
WREG32(data_reg, 0x80188000);
WREG32(index_reg, 0x20401);
WREG32(data_reg, 0x8E00BEA0);
WREG32(index_reg, 0x20402);
WREG32(data_reg, 0xBF8883C0);
WREG32(index_reg, 0x20403);
WREG32(data_reg, 0x80008000);
WREG32(index_reg, 0x20500);
WREG32(data_reg, 0x80188000);
WREG32(index_reg, 0x20501);
WREG32(data_reg, 0x8D00BE90);
WREG32(index_reg, 0x20502);
WREG32(data_reg, 0xBF588500);
WREG32(index_reg, 0x20503);
WREG32(data_reg, 0x80008008);
WREG32(index_reg, 0x20600);
WREG32(data_reg, 0x80188000);
WREG32(index_reg, 0x20601);
WREG32(data_reg, 0x8BC0BE98);
WREG32(index_reg, 0x20602);
WREG32(data_reg, 0xBF308660);
WREG32(index_reg, 0x20603);
WREG32(data_reg, 0x80008008);
WREG32(index_reg, 0x20700);
WREG32(data_reg, 0x80108000);
WREG32(index_reg, 0x20701);
WREG32(data_reg, 0x8A80BEB0);
WREG32(index_reg, 0x20702);
WREG32(data_reg, 0xBF0087C0);
WREG32(index_reg, 0x20703);
WREG32(data_reg, 0x80008008);
WREG32(index_reg, 0x20800);
WREG32(data_reg, 0x80108000);
WREG32(index_reg, 0x20801);
WREG32(data_reg, 0x8920BED0);
WREG32(index_reg, 0x20802);
WREG32(data_reg, 0xBED08920);
WREG32(index_reg, 0x20803);
WREG32(data_reg, 0x80008010);
WREG32(index_reg, 0x30000);
WREG32(data_reg, 0x90008000);
WREG32(index_reg, 0x30001);
WREG32(data_reg, 0x80008000);
WREG32(index_reg, 0x30100);
WREG32(data_reg, 0x8FE0BF90);
WREG32(index_reg, 0x30101);
WREG32(data_reg, 0xBFF880A0);
WREG32(index_reg, 0x30200);
WREG32(data_reg, 0x8F60BF40);
WREG32(index_reg, 0x30201);
WREG32(data_reg, 0xBFE88180);
WREG32(index_reg, 0x30300);
WREG32(data_reg, 0x8EC0BF00);
WREG32(index_reg, 0x30301);
WREG32(data_reg, 0xBFC88280);
WREG32(index_reg, 0x30400);
WREG32(data_reg, 0x8DE0BEE0);
WREG32(index_reg, 0x30401);
WREG32(data_reg, 0xBFA083A0);
WREG32(index_reg, 0x30500);
WREG32(data_reg, 0x8CE0BED0);
WREG32(index_reg, 0x30501);
WREG32(data_reg, 0xBF7884E0);
WREG32(index_reg, 0x30600);
WREG32(data_reg, 0x8BA0BED8);
WREG32(index_reg, 0x30601);
WREG32(data_reg, 0xBF508640);
WREG32(index_reg, 0x30700);
WREG32(data_reg, 0x8A60BEE8);
WREG32(index_reg, 0x30701);
WREG32(data_reg, 0xBF2087A0);
WREG32(index_reg, 0x30800);
WREG32(data_reg, 0x8900BF00);
WREG32(index_reg, 0x30801);
WREG32(data_reg, 0xBF008900);
}
 
struct rv515_watermark {
u32 lb_request_fifo_depth;
fixed20_12 num_line_pair;
fixed20_12 estimated_width;
fixed20_12 worst_case_latency;
fixed20_12 consumption_rate;
fixed20_12 active_time;
fixed20_12 dbpp;
fixed20_12 priority_mark_max;
fixed20_12 priority_mark;
fixed20_12 sclk;
};
 
void rv515_crtc_bandwidth_compute(struct radeon_device *rdev,
struct radeon_crtc *crtc,
struct rv515_watermark *wm)
{
struct drm_display_mode *mode = &crtc->base.mode;
fixed20_12 a, b, c;
fixed20_12 pclk, request_fifo_depth, tolerable_latency, estimated_width;
fixed20_12 consumption_time, line_time, chunk_time, read_delay_latency;
 
if (!crtc->base.enabled) {
/* FIXME: wouldn't it better to set priority mark to maximum */
wm->lb_request_fifo_depth = 4;
return;
}
 
int rv515_init(struct radeon_device *rdev)
if (crtc->vsc.full > rfixed_const(2))
wm->num_line_pair.full = rfixed_const(2);
else
wm->num_line_pair.full = rfixed_const(1);
 
b.full = rfixed_const(mode->crtc_hdisplay);
c.full = rfixed_const(256);
a.full = rfixed_mul(wm->num_line_pair, b);
request_fifo_depth.full = rfixed_div(a, c);
if (a.full < rfixed_const(4)) {
wm->lb_request_fifo_depth = 4;
} else {
wm->lb_request_fifo_depth = rfixed_trunc(request_fifo_depth);
}
 
/* Determine consumption rate
* pclk = pixel clock period(ns) = 1000 / (mode.clock / 1000)
* vtaps = number of vertical taps,
* vsc = vertical scaling ratio, defined as source/destination
* hsc = horizontal scaling ration, defined as source/destination
*/
a.full = rfixed_const(mode->clock);
b.full = rfixed_const(1000);
a.full = rfixed_div(a, b);
pclk.full = rfixed_div(b, a);
if (crtc->rmx_type != RMX_OFF) {
b.full = rfixed_const(2);
if (crtc->vsc.full > b.full)
b.full = crtc->vsc.full;
b.full = rfixed_mul(b, crtc->hsc);
c.full = rfixed_const(2);
b.full = rfixed_div(b, c);
consumption_time.full = rfixed_div(pclk, b);
} else {
consumption_time.full = pclk.full;
}
a.full = rfixed_const(1);
wm->consumption_rate.full = rfixed_div(a, consumption_time);
 
 
/* Determine line time
* LineTime = total time for one line of displayhtotal
* LineTime = total number of horizontal pixels
* pclk = pixel clock period(ns)
*/
a.full = rfixed_const(crtc->base.mode.crtc_htotal);
line_time.full = rfixed_mul(a, pclk);
 
/* Determine active time
* ActiveTime = time of active region of display within one line,
* hactive = total number of horizontal active pixels
* htotal = total number of horizontal pixels
*/
a.full = rfixed_const(crtc->base.mode.crtc_htotal);
b.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
wm->active_time.full = rfixed_mul(line_time, b);
wm->active_time.full = rfixed_div(wm->active_time, a);
 
/* Determine chunk time
* ChunkTime = the time it takes the DCP to send one chunk of data
* to the LB which consists of pipeline delay and inter chunk gap
* sclk = system clock(Mhz)
*/
a.full = rfixed_const(600 * 1000);
chunk_time.full = rfixed_div(a, rdev->pm.sclk);
read_delay_latency.full = rfixed_const(1000);
 
/* Determine the worst case latency
* NumLinePair = Number of line pairs to request(1=2 lines, 2=4 lines)
* WorstCaseLatency = worst case time from urgent to when the MC starts
* to return data
* READ_DELAY_IDLE_MAX = constant of 1us
* ChunkTime = time it takes the DCP to send one chunk of data to the LB
* which consists of pipeline delay and inter chunk gap
*/
if (rfixed_trunc(wm->num_line_pair) > 1) {
a.full = rfixed_const(3);
wm->worst_case_latency.full = rfixed_mul(a, chunk_time);
wm->worst_case_latency.full += read_delay_latency.full;
} else {
wm->worst_case_latency.full = chunk_time.full + read_delay_latency.full;
}
 
/* Determine the tolerable latency
* TolerableLatency = Any given request has only 1 line time
* for the data to be returned
* LBRequestFifoDepth = Number of chunk requests the LB can
* put into the request FIFO for a display
* LineTime = total time for one line of display
* ChunkTime = the time it takes the DCP to send one chunk
* of data to the LB which consists of
* pipeline delay and inter chunk gap
*/
if ((2+wm->lb_request_fifo_depth) >= rfixed_trunc(request_fifo_depth)) {
tolerable_latency.full = line_time.full;
} else {
tolerable_latency.full = rfixed_const(wm->lb_request_fifo_depth - 2);
tolerable_latency.full = request_fifo_depth.full - tolerable_latency.full;
tolerable_latency.full = rfixed_mul(tolerable_latency, chunk_time);
tolerable_latency.full = line_time.full - tolerable_latency.full;
}
/* We assume worst case 32bits (4 bytes) */
wm->dbpp.full = rfixed_const(2 * 16);
 
/* Determine the maximum priority mark
* width = viewport width in pixels
*/
a.full = rfixed_const(16);
wm->priority_mark_max.full = rfixed_const(crtc->base.mode.crtc_hdisplay);
wm->priority_mark_max.full = rfixed_div(wm->priority_mark_max, a);
 
/* Determine estimated width */
estimated_width.full = tolerable_latency.full - wm->worst_case_latency.full;
estimated_width.full = rfixed_div(estimated_width, consumption_time);
if (rfixed_trunc(estimated_width) > crtc->base.mode.crtc_hdisplay) {
wm->priority_mark.full = rfixed_const(10);
} else {
a.full = rfixed_const(16);
wm->priority_mark.full = rfixed_div(estimated_width, a);
wm->priority_mark.full = wm->priority_mark_max.full - wm->priority_mark.full;
}
}
 
void rv515_bandwidth_avivo_update(struct radeon_device *rdev)
{
dbgprintf("%s\n",__FUNCTION__);
struct drm_display_mode *mode0 = NULL;
struct drm_display_mode *mode1 = NULL;
struct rv515_watermark wm0;
struct rv515_watermark wm1;
u32 tmp;
fixed20_12 priority_mark02, priority_mark12, fill_rate;
fixed20_12 a, b;
 
rdev->config.r300.reg_safe_bm = r500_reg_safe_bm;
rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r500_reg_safe_bm);
return 0;
if (rdev->mode_info.crtcs[0]->base.enabled)
mode0 = &rdev->mode_info.crtcs[0]->base.mode;
if (rdev->mode_info.crtcs[1]->base.enabled)
mode1 = &rdev->mode_info.crtcs[1]->base.mode;
rs690_line_buffer_adjust(rdev, mode0, mode1);
 
rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[0], &wm0);
rv515_crtc_bandwidth_compute(rdev, rdev->mode_info.crtcs[1], &wm1);
 
tmp = wm0.lb_request_fifo_depth;
tmp |= wm1.lb_request_fifo_depth << 16;
WREG32(LB_MAX_REQ_OUTSTANDING, tmp);
 
if (mode0 && mode1) {
if (rfixed_trunc(wm0.dbpp) > 64)
a.full = rfixed_div(wm0.dbpp, wm0.num_line_pair);
else
a.full = wm0.num_line_pair.full;
if (rfixed_trunc(wm1.dbpp) > 64)
b.full = rfixed_div(wm1.dbpp, wm1.num_line_pair);
else
b.full = wm1.num_line_pair.full;
a.full += b.full;
fill_rate.full = rfixed_div(wm0.sclk, a);
if (wm0.consumption_rate.full > fill_rate.full) {
b.full = wm0.consumption_rate.full - fill_rate.full;
b.full = rfixed_mul(b, wm0.active_time);
a.full = rfixed_const(16);
b.full = rfixed_div(b, a);
a.full = rfixed_mul(wm0.worst_case_latency,
wm0.consumption_rate);
priority_mark02.full = a.full + b.full;
} else {
a.full = rfixed_mul(wm0.worst_case_latency,
wm0.consumption_rate);
b.full = rfixed_const(16 * 1000);
priority_mark02.full = rfixed_div(a, b);
}
if (wm1.consumption_rate.full > fill_rate.full) {
b.full = wm1.consumption_rate.full - fill_rate.full;
b.full = rfixed_mul(b, wm1.active_time);
a.full = rfixed_const(16);
b.full = rfixed_div(b, a);
a.full = rfixed_mul(wm1.worst_case_latency,
wm1.consumption_rate);
priority_mark12.full = a.full + b.full;
} else {
a.full = rfixed_mul(wm1.worst_case_latency,
wm1.consumption_rate);
b.full = rfixed_const(16 * 1000);
priority_mark12.full = rfixed_div(a, b);
}
if (wm0.priority_mark.full > priority_mark02.full)
priority_mark02.full = wm0.priority_mark.full;
if (rfixed_trunc(priority_mark02) < 0)
priority_mark02.full = 0;
if (wm0.priority_mark_max.full > priority_mark02.full)
priority_mark02.full = wm0.priority_mark_max.full;
if (wm1.priority_mark.full > priority_mark12.full)
priority_mark12.full = wm1.priority_mark.full;
if (rfixed_trunc(priority_mark12) < 0)
priority_mark12.full = 0;
if (wm1.priority_mark_max.full > priority_mark12.full)
priority_mark12.full = wm1.priority_mark_max.full;
WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
} else if (mode0) {
if (rfixed_trunc(wm0.dbpp) > 64)
a.full = rfixed_div(wm0.dbpp, wm0.num_line_pair);
else
a.full = wm0.num_line_pair.full;
fill_rate.full = rfixed_div(wm0.sclk, a);
if (wm0.consumption_rate.full > fill_rate.full) {
b.full = wm0.consumption_rate.full - fill_rate.full;
b.full = rfixed_mul(b, wm0.active_time);
a.full = rfixed_const(16);
b.full = rfixed_div(b, a);
a.full = rfixed_mul(wm0.worst_case_latency,
wm0.consumption_rate);
priority_mark02.full = a.full + b.full;
} else {
a.full = rfixed_mul(wm0.worst_case_latency,
wm0.consumption_rate);
b.full = rfixed_const(16);
priority_mark02.full = rfixed_div(a, b);
}
if (wm0.priority_mark.full > priority_mark02.full)
priority_mark02.full = wm0.priority_mark.full;
if (rfixed_trunc(priority_mark02) < 0)
priority_mark02.full = 0;
if (wm0.priority_mark_max.full > priority_mark02.full)
priority_mark02.full = wm0.priority_mark_max.full;
WREG32(D1MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark02));
WREG32(D1MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark02));
WREG32(D2MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
WREG32(D2MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
} else {
if (rfixed_trunc(wm1.dbpp) > 64)
a.full = rfixed_div(wm1.dbpp, wm1.num_line_pair);
else
a.full = wm1.num_line_pair.full;
fill_rate.full = rfixed_div(wm1.sclk, a);
if (wm1.consumption_rate.full > fill_rate.full) {
b.full = wm1.consumption_rate.full - fill_rate.full;
b.full = rfixed_mul(b, wm1.active_time);
a.full = rfixed_const(16);
b.full = rfixed_div(b, a);
a.full = rfixed_mul(wm1.worst_case_latency,
wm1.consumption_rate);
priority_mark12.full = a.full + b.full;
} else {
a.full = rfixed_mul(wm1.worst_case_latency,
wm1.consumption_rate);
b.full = rfixed_const(16 * 1000);
priority_mark12.full = rfixed_div(a, b);
}
if (wm1.priority_mark.full > priority_mark12.full)
priority_mark12.full = wm1.priority_mark.full;
if (rfixed_trunc(priority_mark12) < 0)
priority_mark12.full = 0;
if (wm1.priority_mark_max.full > priority_mark12.full)
priority_mark12.full = wm1.priority_mark_max.full;
WREG32(D1MODE_PRIORITY_A_CNT, MODE_PRIORITY_OFF);
WREG32(D1MODE_PRIORITY_B_CNT, MODE_PRIORITY_OFF);
WREG32(D2MODE_PRIORITY_A_CNT, rfixed_trunc(priority_mark12));
WREG32(D2MODE_PRIORITY_B_CNT, rfixed_trunc(priority_mark12));
}
}
 
void rv515_bandwidth_update(struct radeon_device *rdev)
{
uint32_t tmp;
struct drm_display_mode *mode0 = NULL;
struct drm_display_mode *mode1 = NULL;
 
if (rdev->mode_info.crtcs[0]->base.enabled)
mode0 = &rdev->mode_info.crtcs[0]->base.mode;
if (rdev->mode_info.crtcs[1]->base.enabled)
mode1 = &rdev->mode_info.crtcs[1]->base.mode;
/*
* Set display0/1 priority up in the memory controller for
* modes if the user specifies HIGH for displaypriority
* option.
*/
if (rdev->disp_priority == 2) {
tmp = RREG32_MC(MC_MISC_LAT_TIMER);
tmp &= ~MC_DISP1R_INIT_LAT_MASK;
tmp &= ~MC_DISP0R_INIT_LAT_MASK;
if (mode1)
tmp |= (1 << MC_DISP1R_INIT_LAT_SHIFT);
if (mode0)
tmp |= (1 << MC_DISP0R_INIT_LAT_SHIFT);
WREG32_MC(MC_MISC_LAT_TIMER, tmp);
}
rv515_bandwidth_avivo_update(rdev);
}
/drivers/video/drm/radeon/rv515_reg_safe.h
0,0 → 1,57
static const unsigned rv515_reg_safe_bm[219] = {
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x17FF1FFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFF30FFBF,
0xFFFFFFF8, 0xC3E6FFFF, 0xFFFFF6DF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF03F,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFEFCE, 0xF00EBFFF, 0x007C0000,
0xF0000038, 0xFF000009, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFF7FF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0x1FFFFC78, 0xFFFFE000, 0xFFFFFFFE, 0xFFFFFFFF,
0x38CF8F50, 0xFFF88082, 0xFF0000FC, 0xFAE009FF,
0x0000FFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
0xFFFF8CFC, 0xFFFFC1FF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF80FFFF,
0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x0003FC01, 0x3FFFFCF8, 0xFF800B19, 0xFFDFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
};
/drivers/video/drm/radeon/rv515d.h
0,0 → 1,220
/*
* Copyright 2008 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
* Copyright 2009 Jerome Glisse.
*
* 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
* Jerome Glisse
*/
#ifndef __RV515D_H__
#define __RV515D_H__
 
/*
* RV515 registers
*/
#define PCIE_INDEX 0x0030
#define PCIE_DATA 0x0034
#define MC_IND_INDEX 0x0070
#define MC_IND_WR_EN (1 << 24)
#define MC_IND_DATA 0x0074
#define RBBM_SOFT_RESET 0x00F0
#define CONFIG_MEMSIZE 0x00F8
#define HDP_FB_LOCATION 0x0134
#define CP_CSQ_CNTL 0x0740
#define CP_CSQ_MODE 0x0744
#define CP_CSQ_ADDR 0x07F0
#define CP_CSQ_DATA 0x07F4
#define CP_CSQ_STAT 0x07F8
#define CP_CSQ2_STAT 0x07FC
#define RBBM_STATUS 0x0E40
#define DST_PIPE_CONFIG 0x170C
#define WAIT_UNTIL 0x1720
#define WAIT_2D_IDLE (1 << 14)
#define WAIT_3D_IDLE (1 << 15)
#define WAIT_2D_IDLECLEAN (1 << 16)
#define WAIT_3D_IDLECLEAN (1 << 17)
#define ISYNC_CNTL 0x1724
#define ISYNC_ANY2D_IDLE3D (1 << 0)
#define ISYNC_ANY3D_IDLE2D (1 << 1)
#define ISYNC_TRIG2D_IDLE3D (1 << 2)
#define ISYNC_TRIG3D_IDLE2D (1 << 3)
#define ISYNC_WAIT_IDLEGUI (1 << 4)
#define ISYNC_CPSCRATCH_IDLEGUI (1 << 5)
#define VAP_INDEX_OFFSET 0x208C
#define VAP_PVS_STATE_FLUSH_REG 0x2284
#define GB_ENABLE 0x4008
#define GB_MSPOS0 0x4010
#define MS_X0_SHIFT 0
#define MS_Y0_SHIFT 4
#define MS_X1_SHIFT 8
#define MS_Y1_SHIFT 12
#define MS_X2_SHIFT 16
#define MS_Y2_SHIFT 20
#define MSBD0_Y_SHIFT 24
#define MSBD0_X_SHIFT 28
#define GB_MSPOS1 0x4014
#define MS_X3_SHIFT 0
#define MS_Y3_SHIFT 4
#define MS_X4_SHIFT 8
#define MS_Y4_SHIFT 12
#define MS_X5_SHIFT 16
#define MS_Y5_SHIFT 20
#define MSBD1_SHIFT 24
#define GB_TILE_CONFIG 0x4018
#define ENABLE_TILING (1 << 0)
#define PIPE_COUNT_MASK 0x0000000E
#define PIPE_COUNT_SHIFT 1
#define TILE_SIZE_8 (0 << 4)
#define TILE_SIZE_16 (1 << 4)
#define TILE_SIZE_32 (2 << 4)
#define SUBPIXEL_1_12 (0 << 16)
#define SUBPIXEL_1_16 (1 << 16)
#define GB_SELECT 0x401C
#define GB_AA_CONFIG 0x4020
#define GB_PIPE_SELECT 0x402C
#define GA_ENHANCE 0x4274
#define GA_DEADLOCK_CNTL (1 << 0)
#define GA_FASTSYNC_CNTL (1 << 1)
#define GA_POLY_MODE 0x4288
#define FRONT_PTYPE_POINT (0 << 4)
#define FRONT_PTYPE_LINE (1 << 4)
#define FRONT_PTYPE_TRIANGE (2 << 4)
#define BACK_PTYPE_POINT (0 << 7)
#define BACK_PTYPE_LINE (1 << 7)
#define BACK_PTYPE_TRIANGE (2 << 7)
#define GA_ROUND_MODE 0x428C
#define GEOMETRY_ROUND_TRUNC (0 << 0)
#define GEOMETRY_ROUND_NEAREST (1 << 0)
#define COLOR_ROUND_TRUNC (0 << 2)
#define COLOR_ROUND_NEAREST (1 << 2)
#define SU_REG_DEST 0x42C8
#define RB3D_DSTCACHE_CTLSTAT 0x4E4C
#define RB3D_DC_FLUSH (2 << 0)
#define RB3D_DC_FREE (2 << 2)
#define RB3D_DC_FINISH (1 << 4)
#define ZB_ZCACHE_CTLSTAT 0x4F18
#define ZC_FLUSH (1 << 0)
#define ZC_FREE (1 << 1)
#define DC_LB_MEMORY_SPLIT 0x6520
#define DC_LB_MEMORY_SPLIT_MASK 0x00000003
#define DC_LB_MEMORY_SPLIT_SHIFT 0
#define DC_LB_MEMORY_SPLIT_D1HALF_D2HALF 0
#define DC_LB_MEMORY_SPLIT_D1_3Q_D2_1Q 1
#define DC_LB_MEMORY_SPLIT_D1_ONLY 2
#define DC_LB_MEMORY_SPLIT_D1_1Q_D2_3Q 3
#define DC_LB_MEMORY_SPLIT_SHIFT_MODE (1 << 2)
#define DC_LB_DISP1_END_ADR_SHIFT 4
#define DC_LB_DISP1_END_ADR_MASK 0x00007FF0
#define D1MODE_PRIORITY_A_CNT 0x6548
#define MODE_PRIORITY_MARK_MASK 0x00007FFF
#define MODE_PRIORITY_OFF (1 << 16)
#define MODE_PRIORITY_ALWAYS_ON (1 << 20)
#define MODE_PRIORITY_FORCE_MASK (1 << 24)
#define D1MODE_PRIORITY_B_CNT 0x654C
#define LB_MAX_REQ_OUTSTANDING 0x6D58
#define LB_D1_MAX_REQ_OUTSTANDING_MASK 0x0000000F
#define LB_D1_MAX_REQ_OUTSTANDING_SHIFT 0
#define LB_D2_MAX_REQ_OUTSTANDING_MASK 0x000F0000
#define LB_D2_MAX_REQ_OUTSTANDING_SHIFT 16
#define D2MODE_PRIORITY_A_CNT 0x6D48
#define D2MODE_PRIORITY_B_CNT 0x6D4C
 
/* ix[MC] registers */
#define MC_FB_LOCATION 0x01
#define MC_FB_START_MASK 0x0000FFFF
#define MC_FB_START_SHIFT 0
#define MC_FB_TOP_MASK 0xFFFF0000
#define MC_FB_TOP_SHIFT 16
#define MC_AGP_LOCATION 0x02
#define MC_AGP_START_MASK 0x0000FFFF
#define MC_AGP_START_SHIFT 0
#define MC_AGP_TOP_MASK 0xFFFF0000
#define MC_AGP_TOP_SHIFT 16
#define MC_AGP_BASE 0x03
#define MC_AGP_BASE_2 0x04
#define MC_CNTL 0x5
#define MEM_NUM_CHANNELS_MASK 0x00000003
#define MC_STATUS 0x08
#define MC_STATUS_IDLE (1 << 4)
#define MC_MISC_LAT_TIMER 0x09
#define MC_CPR_INIT_LAT_MASK 0x0000000F
#define MC_VF_INIT_LAT_MASK 0x000000F0
#define MC_DISP0R_INIT_LAT_MASK 0x00000F00
#define MC_DISP0R_INIT_LAT_SHIFT 8
#define MC_DISP1R_INIT_LAT_MASK 0x0000F000
#define MC_DISP1R_INIT_LAT_SHIFT 12
#define MC_FIXED_INIT_LAT_MASK 0x000F0000
#define MC_E2R_INIT_LAT_MASK 0x00F00000
#define SAME_PAGE_PRIO_MASK 0x0F000000
#define MC_GLOBW_INIT_LAT_MASK 0xF0000000
 
 
/*
* PM4 packet
*/
#define CP_PACKET0 0x00000000
#define PACKET0_BASE_INDEX_SHIFT 0
#define PACKET0_BASE_INDEX_MASK (0x1ffff << 0)
#define PACKET0_COUNT_SHIFT 16
#define PACKET0_COUNT_MASK (0x3fff << 16)
#define CP_PACKET1 0x40000000
#define CP_PACKET2 0x80000000
#define PACKET2_PAD_SHIFT 0
#define PACKET2_PAD_MASK (0x3fffffff << 0)
#define CP_PACKET3 0xC0000000
#define PACKET3_IT_OPCODE_SHIFT 8
#define PACKET3_IT_OPCODE_MASK (0xff << 8)
#define PACKET3_COUNT_SHIFT 16
#define PACKET3_COUNT_MASK (0x3fff << 16)
/* PACKET3 op code */
#define PACKET3_NOP 0x10
#define PACKET3_3D_DRAW_VBUF 0x28
#define PACKET3_3D_DRAW_IMMD 0x29
#define PACKET3_3D_DRAW_INDX 0x2A
#define PACKET3_3D_LOAD_VBPNTR 0x2F
#define PACKET3_INDX_BUFFER 0x33
#define PACKET3_3D_DRAW_VBUF_2 0x34
#define PACKET3_3D_DRAW_IMMD_2 0x35
#define PACKET3_3D_DRAW_INDX_2 0x36
#define PACKET3_BITBLT_MULTI 0x9B
 
#define PACKET0(reg, n) (CP_PACKET0 | \
REG_SET(PACKET0_BASE_INDEX, (reg) >> 2) | \
REG_SET(PACKET0_COUNT, (n)))
#define PACKET2(v) (CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
#define PACKET3(op, n) (CP_PACKET3 | \
REG_SET(PACKET3_IT_OPCODE, (op)) | \
REG_SET(PACKET3_COUNT, (n)))
 
#define PACKET_TYPE0 0
#define PACKET_TYPE1 1
#define PACKET_TYPE2 2
#define PACKET_TYPE3 3
 
#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3)
#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF)
#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2)
#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1)
#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
 
#endif