592 lines
20 KiB
C
592 lines
20 KiB
C
/*
|
|
* Copyright 2007 Jérôme Glisse
|
|
* Copyright 2007 Dave Airlie
|
|
* Copyright 2007 Alex Deucher
|
|
* All Rights Reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, 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 (including the next
|
|
* paragraph) 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
|
|
* PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*/
|
|
/*
|
|
* Authors:
|
|
* Jérôme Glisse <glisse@freedesktop.org>
|
|
*/
|
|
#ifndef __RADEON_MS_H__
|
|
#define __RADEON_MS_H__
|
|
|
|
#include "radeon_ms_drv.h"
|
|
#include "radeon_ms_reg.h"
|
|
#include "radeon_ms_drm.h"
|
|
#include "radeon_ms_rom.h"
|
|
#include "radeon_ms_properties.h"
|
|
#include "amd.h"
|
|
#include "amd_legacy.h"
|
|
|
|
#define DRIVER_AUTHOR "Jerome Glisse, Dave Airlie, Gareth Hughes, "\
|
|
"Keith Whitwell, others."
|
|
#define DRIVER_NAME "radeon_ms"
|
|
#define DRIVER_DESC "radeon kernel modesetting"
|
|
#define DRIVER_DATE "20071108"
|
|
#define DRIVER_MAJOR 1
|
|
#define DRIVER_MINOR 0
|
|
#define DRIVER_PATCHLEVEL 0
|
|
|
|
enum radeon_bus_type {
|
|
RADEON_PCI = 0x10000,
|
|
RADEON_AGP = 0x20000,
|
|
RADEON_PCIE = 0x30000,
|
|
};
|
|
|
|
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_R360,
|
|
CHIP_RV350,
|
|
CHIP_RV370,
|
|
CHIP_RV380,
|
|
CHIP_RS400,
|
|
CHIP_RV410,
|
|
CHIP_R420,
|
|
CHIP_R430,
|
|
CHIP_R480,
|
|
CHIP_LAST,
|
|
};
|
|
|
|
enum radeon_monitor_type {
|
|
MT_UNKNOWN = -1,
|
|
MT_NONE = 0,
|
|
MT_CRT = 1,
|
|
MT_LCD = 2,
|
|
MT_DFP = 3,
|
|
MT_CTV = 4,
|
|
MT_STV = 5
|
|
};
|
|
|
|
enum radeon_connector_type {
|
|
CONNECTOR_NONE,
|
|
CONNECTOR_PROPRIETARY,
|
|
CONNECTOR_VGA,
|
|
CONNECTOR_DVI_I,
|
|
CONNECTOR_DVI_D,
|
|
CONNECTOR_CTV,
|
|
CONNECTOR_STV,
|
|
CONNECTOR_UNSUPPORTED
|
|
};
|
|
|
|
enum radeon_output_type {
|
|
OUTPUT_NONE,
|
|
OUTPUT_DAC1,
|
|
OUTPUT_DAC2,
|
|
OUTPUT_TMDS,
|
|
OUTPUT_LVDS
|
|
};
|
|
|
|
struct radeon_state;
|
|
|
|
struct radeon_ms_crtc {
|
|
int crtc;
|
|
uint16_t lut_r[256];
|
|
uint16_t lut_g[256];
|
|
uint16_t lut_b[256];
|
|
};
|
|
|
|
struct radeon_ms_i2c {
|
|
struct drm_device *drm_dev;
|
|
uint32_t reg;
|
|
struct i2c_adapter adapter;
|
|
struct i2c_algo_bit_data algo;
|
|
};
|
|
|
|
struct radeon_ms_connector {
|
|
struct radeon_ms_i2c *i2c;
|
|
struct edid *edid;
|
|
struct drm_output *output;
|
|
int type;
|
|
int monitor_type;
|
|
int crtc;
|
|
uint32_t i2c_reg;
|
|
char outputs[RADEON_MAX_OUTPUTS];
|
|
char name[32];
|
|
};
|
|
|
|
struct radeon_ms_output {
|
|
int type;
|
|
struct drm_device *dev;
|
|
struct radeon_ms_connector *connector;
|
|
int (*initialize)(struct radeon_ms_output *output);
|
|
enum drm_output_status (*detect)(struct radeon_ms_output *output);
|
|
void (*dpms)(struct radeon_ms_output *output, int mode);
|
|
int (*get_modes)(struct radeon_ms_output *output);
|
|
bool (*mode_fixup)(struct radeon_ms_output *output,
|
|
struct drm_display_mode *mode,
|
|
struct drm_display_mode *adjusted_mode);
|
|
int (*mode_set)(struct radeon_ms_output *output,
|
|
struct drm_display_mode *mode,
|
|
struct drm_display_mode *adjusted_mode);
|
|
void (*restore)(struct radeon_ms_output *output,
|
|
struct radeon_state *state);
|
|
void (*save)(struct radeon_ms_output *output,
|
|
struct radeon_state *state);
|
|
};
|
|
|
|
struct radeon_state {
|
|
/* memory */
|
|
uint32_t config_aper_0_base;
|
|
uint32_t config_aper_1_base;
|
|
uint32_t config_aper_size;
|
|
uint32_t mc_fb_location;
|
|
uint32_t display_base_addr;
|
|
/* irq */
|
|
uint32_t gen_int_cntl;
|
|
/* pci */
|
|
uint32_t aic_ctrl;
|
|
uint32_t aic_pt_base;
|
|
uint32_t aic_pt_base_lo;
|
|
uint32_t aic_pt_base_hi;
|
|
uint32_t aic_lo_addr;
|
|
uint32_t aic_hi_addr;
|
|
/* agp */
|
|
uint32_t agp_cntl;
|
|
uint32_t agp_command;
|
|
uint32_t agp_base;
|
|
uint32_t agp_base_2;
|
|
uint32_t bus_cntl;
|
|
uint32_t mc_agp_location;
|
|
/* cp */
|
|
uint32_t cp_rb_cntl;
|
|
uint32_t cp_rb_base;
|
|
uint32_t cp_rb_rptr_addr;
|
|
uint32_t cp_rb_wptr;
|
|
uint32_t cp_rb_wptr_delay;
|
|
uint32_t scratch_umsk;
|
|
uint32_t scratch_addr;
|
|
/* pcie */
|
|
uint32_t pcie_tx_gart_cntl;
|
|
uint32_t pcie_tx_gart_discard_rd_addr_lo;
|
|
uint32_t pcie_tx_gart_discard_rd_addr_hi;
|
|
uint32_t pcie_tx_gart_base;
|
|
uint32_t pcie_tx_gart_start_lo;
|
|
uint32_t pcie_tx_gart_start_hi;
|
|
uint32_t pcie_tx_gart_end_lo;
|
|
uint32_t pcie_tx_gart_end_hi;
|
|
/* surface */
|
|
uint32_t surface_cntl;
|
|
uint32_t surface0_info;
|
|
uint32_t surface0_lower_bound;
|
|
uint32_t surface0_upper_bound;
|
|
uint32_t surface1_info;
|
|
uint32_t surface1_lower_bound;
|
|
uint32_t surface1_upper_bound;
|
|
uint32_t surface2_info;
|
|
uint32_t surface2_lower_bound;
|
|
uint32_t surface2_upper_bound;
|
|
uint32_t surface3_info;
|
|
uint32_t surface3_lower_bound;
|
|
uint32_t surface3_upper_bound;
|
|
uint32_t surface4_info;
|
|
uint32_t surface4_lower_bound;
|
|
uint32_t surface4_upper_bound;
|
|
uint32_t surface5_info;
|
|
uint32_t surface5_lower_bound;
|
|
uint32_t surface5_upper_bound;
|
|
uint32_t surface6_info;
|
|
uint32_t surface6_lower_bound;
|
|
uint32_t surface6_upper_bound;
|
|
uint32_t surface7_info;
|
|
uint32_t surface7_lower_bound;
|
|
uint32_t surface7_upper_bound;
|
|
/* crtc */
|
|
uint32_t crtc_gen_cntl;
|
|
uint32_t crtc_ext_cntl;
|
|
uint32_t crtc_h_total_disp;
|
|
uint32_t crtc_h_sync_strt_wid;
|
|
uint32_t crtc_v_total_disp;
|
|
uint32_t crtc_v_sync_strt_wid;
|
|
uint32_t crtc_offset;
|
|
uint32_t crtc_offset_cntl;
|
|
uint32_t crtc_pitch;
|
|
uint32_t crtc_more_cntl;
|
|
uint32_t crtc_tile_x0_y0;
|
|
uint32_t fp_h_sync_strt_wid;
|
|
uint32_t fp_v_sync_strt_wid;
|
|
uint32_t fp_crtc_h_total_disp;
|
|
uint32_t fp_crtc_v_total_disp;
|
|
/* pll */
|
|
uint32_t clock_cntl_index;
|
|
uint32_t ppll_cntl;
|
|
uint32_t ppll_ref_div;
|
|
uint32_t ppll_div_0;
|
|
uint32_t ppll_div_1;
|
|
uint32_t ppll_div_2;
|
|
uint32_t ppll_div_3;
|
|
uint32_t vclk_ecp_cntl;
|
|
uint32_t htotal_cntl;
|
|
/* dac */
|
|
uint32_t dac_cntl;
|
|
uint32_t dac_cntl2;
|
|
uint32_t dac_ext_cntl;
|
|
uint32_t disp_misc_cntl;
|
|
uint32_t dac_macro_cntl;
|
|
uint32_t disp_pwr_man;
|
|
uint32_t disp_merge_cntl;
|
|
uint32_t disp_output_cntl;
|
|
uint32_t disp2_merge_cntl;
|
|
uint32_t dac_embedded_sync_cntl;
|
|
uint32_t dac_broad_pulse;
|
|
uint32_t dac_skew_clks;
|
|
uint32_t dac_incr;
|
|
uint32_t dac_neg_sync_level;
|
|
uint32_t dac_pos_sync_level;
|
|
uint32_t dac_blank_level;
|
|
uint32_t dac_sync_equalization;
|
|
uint32_t tv_dac_cntl;
|
|
uint32_t tv_master_cntl;
|
|
};
|
|
|
|
struct drm_radeon_private {
|
|
/* driver family specific functions */
|
|
int (*bus_finish)(struct drm_device *dev);
|
|
int (*bus_init)(struct drm_device *dev);
|
|
void (*bus_restore)(struct drm_device *dev, struct radeon_state *state);
|
|
void (*bus_save)(struct drm_device *dev, struct radeon_state *state);
|
|
struct drm_ttm_backend *(*create_ttm)(struct drm_device *dev);
|
|
void (*irq_emit)(struct drm_device *dev);
|
|
void (*flush_cache)(struct drm_device *dev);
|
|
/* bus informations */
|
|
void *bus;
|
|
uint32_t bus_type;
|
|
/* cp */
|
|
uint32_t ring_buffer_size;
|
|
uint32_t ring_rptr;
|
|
uint32_t ring_wptr;
|
|
uint32_t ring_mask;
|
|
int ring_free;
|
|
uint32_t ring_tail_mask;
|
|
uint32_t write_back_area_size;
|
|
struct drm_buffer_object *ring_buffer_object;
|
|
struct drm_bo_kmap_obj ring_buffer_map;
|
|
uint32_t *ring_buffer;
|
|
uint32_t *write_back_area;
|
|
const uint32_t *microcode;
|
|
/* framebuffer */
|
|
struct amd_fb *fb;
|
|
/* card family */
|
|
uint32_t usec_timeout;
|
|
uint32_t family;
|
|
struct radeon_ms_output *outputs[RADEON_MAX_OUTPUTS];
|
|
struct radeon_ms_connector *connectors[RADEON_MAX_CONNECTORS];
|
|
/* drm map (MMIO, FB) */
|
|
struct drm_map mmio;
|
|
struct drm_map vram;
|
|
/* gpu address space */
|
|
uint32_t gpu_vram_size;
|
|
uint32_t gpu_vram_start;
|
|
uint32_t gpu_vram_end;
|
|
uint32_t gpu_gart_size;
|
|
uint32_t gpu_gart_start;
|
|
uint32_t gpu_gart_end;
|
|
/* state of the card when module was loaded */
|
|
struct radeon_state load_state;
|
|
/* state the driver wants */
|
|
struct radeon_state driver_state;
|
|
/* last emitted fence */
|
|
uint32_t fence_id_last;
|
|
uint32_t fence_reg;
|
|
/* when doing gpu stop we save here current state */
|
|
uint32_t crtc_ext_cntl;
|
|
uint32_t crtc_gen_cntl;
|
|
uint32_t crtc2_gen_cntl;
|
|
uint32_t ov0_scale_cntl;
|
|
/* bool & type on the hw */
|
|
uint8_t crtc1_dpms;
|
|
uint8_t crtc2_dpms;
|
|
uint8_t restore_state;
|
|
uint8_t cp_ready;
|
|
uint8_t bus_ready;
|
|
uint8_t write_back;
|
|
/* command buffer informations */
|
|
struct amd_cmd_module cmd_module;
|
|
/* abstract asic specific structures */
|
|
struct radeon_ms_rom rom;
|
|
struct radeon_ms_properties properties;
|
|
void *fence;
|
|
};
|
|
|
|
|
|
/* radeon_ms_bo.c */
|
|
int radeon_ms_bo_get_gpu_addr(struct drm_device *dev,
|
|
struct drm_bo_mem_reg *mem,
|
|
uint32_t *gpu_addr);
|
|
int radeon_ms_bo_move(struct drm_buffer_object * bo, int evict,
|
|
int no_wait, struct drm_bo_mem_reg * new_mem);
|
|
struct drm_ttm_backend *radeon_ms_create_ttm_backend(struct drm_device * dev);
|
|
uint64_t radeon_ms_evict_flags(struct drm_buffer_object *bo);
|
|
int radeon_ms_init_mem_type(struct drm_device * dev, uint32_t type,
|
|
struct drm_mem_type_manager * man);
|
|
int radeon_ms_invalidate_caches(struct drm_device * dev, uint64_t flags);
|
|
void radeon_ms_ttm_flush(struct drm_ttm *ttm);
|
|
|
|
/* radeon_ms_bus.c */
|
|
int radeon_ms_agp_finish(struct drm_device *dev);
|
|
int radeon_ms_agp_init(struct drm_device *dev);
|
|
void radeon_ms_agp_restore(struct drm_device *dev, struct radeon_state *state);
|
|
void radeon_ms_agp_save(struct drm_device *dev, struct radeon_state *state);
|
|
struct drm_ttm_backend *radeon_ms_pcie_create_ttm(struct drm_device *dev);
|
|
int radeon_ms_pcie_finish(struct drm_device *dev);
|
|
int radeon_ms_pcie_init(struct drm_device *dev);
|
|
void radeon_ms_pcie_restore(struct drm_device *dev, struct radeon_state *state);
|
|
void radeon_ms_pcie_save(struct drm_device *dev, struct radeon_state *state);
|
|
|
|
/* radeon_ms_combios.c */
|
|
int radeon_ms_combios_get_properties(struct drm_device *dev);
|
|
int radeon_ms_connectors_from_combios(struct drm_device *dev);
|
|
int radeon_ms_outputs_from_combios(struct drm_device *dev);
|
|
|
|
/* radeon_ms_compat.c */
|
|
long radeon_ms_compat_ioctl(struct file *filp, unsigned int cmd,
|
|
unsigned long arg);
|
|
|
|
/* radeon_ms_cp.c */
|
|
int radeon_ms_cp_finish(struct drm_device *dev);
|
|
int radeon_ms_cp_init(struct drm_device *dev);
|
|
void radeon_ms_cp_restore(struct drm_device *dev, struct radeon_state *state);
|
|
void radeon_ms_cp_save(struct drm_device *dev, struct radeon_state *state);
|
|
void radeon_ms_cp_stop(struct drm_device *dev);
|
|
int radeon_ms_cp_wait(struct drm_device *dev, int n);
|
|
int radeon_ms_ring_emit(struct drm_device *dev, uint32_t *cmd, uint32_t count);
|
|
int radeon_ms_resetcp(struct drm_device *dev, void *data,
|
|
struct drm_file *file_priv);
|
|
|
|
/* radeon_ms_crtc.c */
|
|
int radeon_ms_crtc_create(struct drm_device *dev, int crtc);
|
|
void radeon_ms_crtc1_restore(struct drm_device *dev,
|
|
struct radeon_state *state);
|
|
void radeon_ms_crtc1_save(struct drm_device *dev, struct radeon_state *state);
|
|
|
|
/* radeon_ms_dac.c */
|
|
int radeon_ms_dac1_initialize(struct radeon_ms_output *output);
|
|
enum drm_output_status radeon_ms_dac1_detect(struct radeon_ms_output *output);
|
|
void radeon_ms_dac1_dpms(struct radeon_ms_output *output, int mode);
|
|
int radeon_ms_dac1_get_modes(struct radeon_ms_output *output);
|
|
bool radeon_ms_dac1_mode_fixup(struct radeon_ms_output *output,
|
|
struct drm_display_mode *mode,
|
|
struct drm_display_mode *adjusted_mode);
|
|
int radeon_ms_dac1_mode_set(struct radeon_ms_output *output,
|
|
struct drm_display_mode *mode,
|
|
struct drm_display_mode *adjusted_mode);
|
|
void radeon_ms_dac1_restore(struct radeon_ms_output *output,
|
|
struct radeon_state *state);
|
|
void radeon_ms_dac1_save(struct radeon_ms_output *output,
|
|
struct radeon_state *state);
|
|
int radeon_ms_dac2_initialize(struct radeon_ms_output *output);
|
|
enum drm_output_status radeon_ms_dac2_detect(struct radeon_ms_output *output);
|
|
void radeon_ms_dac2_dpms(struct radeon_ms_output *output, int mode);
|
|
int radeon_ms_dac2_get_modes(struct radeon_ms_output *output);
|
|
bool radeon_ms_dac2_mode_fixup(struct radeon_ms_output *output,
|
|
struct drm_display_mode *mode,
|
|
struct drm_display_mode *adjusted_mode);
|
|
int radeon_ms_dac2_mode_set(struct radeon_ms_output *output,
|
|
struct drm_display_mode *mode,
|
|
struct drm_display_mode *adjusted_mode);
|
|
void radeon_ms_dac2_restore(struct radeon_ms_output *output,
|
|
struct radeon_state *state);
|
|
void radeon_ms_dac2_save(struct radeon_ms_output *output,
|
|
struct radeon_state *state);
|
|
|
|
/* radeon_ms_drm.c */
|
|
int radeon_ms_driver_dma_ioctl(struct drm_device *dev, void *data,
|
|
struct drm_file *file_priv);
|
|
void radeon_ms_driver_lastclose(struct drm_device * dev);
|
|
int radeon_ms_driver_load(struct drm_device *dev, unsigned long flags);
|
|
int radeon_ms_driver_open(struct drm_device * dev, struct drm_file *file_priv);
|
|
int radeon_ms_driver_unload(struct drm_device *dev);
|
|
|
|
/* radeon_ms_family.c */
|
|
int radeon_ms_family_init(struct drm_device *dev);
|
|
|
|
/* radeon_ms_fence.c */
|
|
void r3xx_fence_handler(struct drm_device * dev);
|
|
int r3xx_fence_types(struct drm_buffer_object *bo,
|
|
uint32_t * class, uint32_t * type);
|
|
|
|
/* radeon_ms_fb.c */
|
|
int radeonfb_probe(struct drm_device *dev, struct drm_crtc *crtc);
|
|
int radeonfb_remove(struct drm_device *dev, struct drm_crtc *crtc);
|
|
|
|
/* radeon_ms_gpu.c */
|
|
int radeon_ms_gpu_initialize(struct drm_device *dev);
|
|
void radeon_ms_gpu_dpms(struct drm_device *dev);
|
|
void radeon_ms_gpu_flush(struct drm_device *dev);
|
|
void radeon_ms_gpu_restore(struct drm_device *dev, struct radeon_state *state);
|
|
void radeon_ms_gpu_save(struct drm_device *dev, struct radeon_state *state);
|
|
int radeon_ms_wait_for_idle(struct drm_device *dev);
|
|
|
|
/* radeon_ms_i2c.c */
|
|
void radeon_ms_i2c_destroy(struct radeon_ms_i2c *i2c);
|
|
struct radeon_ms_i2c *radeon_ms_i2c_create(struct drm_device *dev,
|
|
const uint32_t reg,
|
|
const char *name);
|
|
|
|
/* radeon_ms_irq.c */
|
|
void radeon_ms_irq_emit(struct drm_device *dev);
|
|
irqreturn_t radeon_ms_irq_handler(DRM_IRQ_ARGS);
|
|
void radeon_ms_irq_preinstall(struct drm_device * dev);
|
|
int radeon_ms_irq_postinstall(struct drm_device * dev);
|
|
int radeon_ms_irq_init(struct drm_device *dev);
|
|
void radeon_ms_irq_restore(struct drm_device *dev, struct radeon_state *state);
|
|
void radeon_ms_irq_save(struct drm_device *dev, struct radeon_state *state);
|
|
void radeon_ms_irq_uninstall(struct drm_device * dev);
|
|
|
|
/* radeon_ms_output.c */
|
|
void radeon_ms_connectors_destroy(struct drm_device *dev);
|
|
int radeon_ms_connectors_from_properties(struct drm_device *dev);
|
|
int radeon_ms_connectors_from_rom(struct drm_device *dev);
|
|
void radeon_ms_outputs_destroy(struct drm_device *dev);
|
|
int radeon_ms_outputs_from_properties(struct drm_device *dev);
|
|
int radeon_ms_outputs_from_rom(struct drm_device *dev);
|
|
void radeon_ms_outputs_restore(struct drm_device *dev,
|
|
struct radeon_state *state);
|
|
void radeon_ms_outputs_save(struct drm_device *dev, struct radeon_state *state);
|
|
|
|
/* radeon_ms_properties.c */
|
|
int radeon_ms_properties_init(struct drm_device *dev);
|
|
|
|
/* radeon_ms_rom.c */
|
|
int radeon_ms_rom_get_properties(struct drm_device *dev);
|
|
int radeon_ms_rom_init(struct drm_device *dev);
|
|
|
|
/* radeon_ms_state.c */
|
|
void radeon_ms_state_save(struct drm_device *dev, struct radeon_state *state);
|
|
void radeon_ms_state_restore(struct drm_device *dev,
|
|
struct radeon_state *state);
|
|
|
|
/* helper macro & functions ***************************************************/
|
|
#define REG_S(rn, bn, v) (((v) << rn##__##bn##__SHIFT) & rn##__##bn##__MASK)
|
|
#define REG_G(rn, bn, v) (((v) & rn##__##bn##__MASK) >> rn##__##bn##__SHIFT)
|
|
#define MMIO_R(rid) mmio_read(dev_priv, rid)
|
|
#define MMIO_W(rid, v) mmio_write(dev_priv, rid, v)
|
|
#define PCIE_R(rid) pcie_read(dev_priv, rid)
|
|
#define PCIE_W(rid, v) pcie_write(dev_priv, rid, v)
|
|
#define PPLL_R(rid) pll_read(dev_priv, rid)
|
|
#define PPLL_W(rid, v) pll_write(dev_priv, rid, v)
|
|
|
|
static __inline__ uint32_t mmio_read(struct drm_radeon_private *dev_priv,
|
|
uint32_t offset)
|
|
{
|
|
return DRM_READ32(&dev_priv->mmio, offset);
|
|
}
|
|
|
|
|
|
static __inline__ void mmio_write(struct drm_radeon_private *dev_priv,
|
|
uint32_t offset, uint32_t v)
|
|
{
|
|
DRM_WRITE32(&dev_priv->mmio, offset, v);
|
|
}
|
|
|
|
static __inline__ uint32_t pcie_read(struct drm_radeon_private *dev_priv,
|
|
uint32_t offset)
|
|
{
|
|
MMIO_W(PCIE_INDEX, REG_S(PCIE_INDEX, PCIE_INDEX, offset));
|
|
return MMIO_R(PCIE_DATA);
|
|
}
|
|
|
|
static __inline__ void pcie_write(struct drm_radeon_private *dev_priv,
|
|
uint32_t offset, uint32_t v)
|
|
{
|
|
MMIO_W(PCIE_INDEX, REG_S(PCIE_INDEX, PCIE_INDEX, offset));
|
|
MMIO_W(PCIE_DATA, v);
|
|
}
|
|
|
|
static __inline__ void pll_index_errata(struct drm_radeon_private *dev_priv)
|
|
{
|
|
uint32_t tmp, save;
|
|
|
|
/* This workaround is necessary on rv200 and RS200 or PLL
|
|
* reads may return garbage (among others...)
|
|
*/
|
|
if (dev_priv->properties.pll_dummy_reads) {
|
|
tmp = MMIO_R(CLOCK_CNTL_DATA);
|
|
tmp = MMIO_R(CRTC_GEN_CNTL);
|
|
}
|
|
/* This function is required to workaround a hardware bug in some (all?)
|
|
* revisions of the R300. This workaround should be called after every
|
|
* CLOCK_CNTL_INDEX register access. If not, register reads afterward
|
|
* may not be correct.
|
|
*/
|
|
if (dev_priv->properties.pll_r300_errata) {
|
|
tmp = save = MMIO_R(CLOCK_CNTL_INDEX);
|
|
tmp = tmp & ~CLOCK_CNTL_INDEX__PLL_ADDR__MASK;
|
|
tmp = tmp & ~CLOCK_CNTL_INDEX__PLL_WR_EN;
|
|
MMIO_W(CLOCK_CNTL_INDEX, tmp);
|
|
tmp = MMIO_R(CLOCK_CNTL_DATA);
|
|
MMIO_W(CLOCK_CNTL_INDEX, save);
|
|
}
|
|
}
|
|
|
|
static __inline__ void pll_data_errata(struct drm_radeon_private *dev_priv)
|
|
{
|
|
/* This workarounds is necessary on RV100, RS100 and RS200 chips
|
|
* or the chip could hang on a subsequent access
|
|
*/
|
|
if (dev_priv->properties.pll_delay) {
|
|
/* we can't deal with posted writes here ... */
|
|
udelay(5000);
|
|
}
|
|
}
|
|
|
|
static __inline__ uint32_t pll_read(struct drm_radeon_private *dev_priv,
|
|
uint32_t offset)
|
|
{
|
|
uint32_t clock_cntl_index = dev_priv->driver_state.clock_cntl_index;
|
|
uint32_t data;
|
|
|
|
clock_cntl_index &= ~CLOCK_CNTL_INDEX__PLL_ADDR__MASK;
|
|
clock_cntl_index |= REG_S(CLOCK_CNTL_INDEX, PLL_ADDR, offset);
|
|
MMIO_W(CLOCK_CNTL_INDEX, clock_cntl_index);
|
|
pll_index_errata(dev_priv);
|
|
data = MMIO_R(CLOCK_CNTL_DATA);
|
|
pll_data_errata(dev_priv);
|
|
return data;
|
|
}
|
|
|
|
static __inline__ void pll_write(struct drm_radeon_private *dev_priv,
|
|
uint32_t offset, uint32_t value)
|
|
{
|
|
uint32_t clock_cntl_index = dev_priv->driver_state.clock_cntl_index;
|
|
|
|
clock_cntl_index &= ~CLOCK_CNTL_INDEX__PLL_ADDR__MASK;
|
|
clock_cntl_index |= REG_S(CLOCK_CNTL_INDEX, PLL_ADDR, offset);
|
|
clock_cntl_index |= CLOCK_CNTL_INDEX__PLL_WR_EN;
|
|
MMIO_W(CLOCK_CNTL_INDEX, clock_cntl_index);
|
|
pll_index_errata(dev_priv);
|
|
MMIO_W(CLOCK_CNTL_DATA, value);
|
|
pll_data_errata(dev_priv);
|
|
}
|
|
|
|
#endif
|