From fb30cd43b9346e0f1bf6764f97eabc59d87bd0cb Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Sun, 16 Dec 2012 19:05:06 +0000 Subject: [PATCH] i915 & atikms: update git-svn-id: svn://kolibrios.org@3120 a494cfbc-eb01-0410-851d-a64ba20cac60 --- .../devman/acpica/tools/acpiexec/aetables.o | Bin 12337 -> 0 bytes drivers/include/ddk.h | 1 + drivers/include/drm/drmP.h | 2 +- drivers/include/drm/drm_pciids.h | 1 + drivers/include/linux/backlight.h | 10 + drivers/include/linux/delay.h | 9 + drivers/include/linux/fb.h | 5 +- drivers/include/linux/lockdep.h | 2 + drivers/include/linux/mod_devicetable.h | 3 + drivers/include/linux/stddef.h | 8 - drivers/include/linux/string.h | 9 +- drivers/video/drm/drm_edid.c | 4 +- drivers/video/drm/i2c/i2c-algo-bit.c | 2 +- drivers/video/drm/i915/i915_drv.c | 15 +- drivers/video/drm/i915/intel_bios.c | 12 +- drivers/video/drm/i915/intel_crt.c | 2 +- drivers/video/drm/i915/intel_display.c | 11 + drivers/video/drm/i915/intel_pm.c | 12 +- drivers/video/drm/i915/intel_sdvo.c | 39 +- drivers/video/drm/i915/kms_display.c | 26 +- drivers/video/drm/i915/main.c | 12 +- drivers/video/drm/radeon/Makefile | 2 + drivers/video/drm/radeon/Makefile.lto | 2 + drivers/video/drm/radeon/atombios_crtc.c | 48 +- drivers/video/drm/radeon/atombios_encoders.c | 2 +- drivers/video/drm/radeon/bitmap.c | 485 ++++++++++++++++++ drivers/video/drm/radeon/bitmap.h | 107 ++++ drivers/video/drm/radeon/clip.inc | 121 +++++ drivers/video/drm/radeon/display.h | 10 - drivers/video/drm/radeon/evergreen.c | 4 +- drivers/video/drm/radeon/hmm.c | 71 +++ drivers/video/drm/radeon/hmm.h | 24 + drivers/video/drm/radeon/ni.c | 4 +- drivers/video/drm/radeon/r100.c | 8 + drivers/video/drm/radeon/r300.c | 6 + drivers/video/drm/radeon/r420.c | 6 + drivers/video/drm/radeon/r520.c | 6 + drivers/video/drm/radeon/radeon.h | 1 + drivers/video/drm/radeon/radeon_asic.c | 64 +-- drivers/video/drm/radeon/radeon_bios.c | 2 +- drivers/video/drm/radeon/radeon_connectors.c | 17 +- drivers/video/drm/radeon/radeon_device.c | 47 +- drivers/video/drm/radeon/radeon_irq_kms.c | 189 +++++-- drivers/video/drm/radeon/radeon_legacy_crtc.c | 15 +- .../video/drm/radeon/radeon_legacy_encoders.c | 138 ++++- drivers/video/drm/radeon/radeon_sa.c | 2 +- drivers/video/drm/radeon/rdisplay.c | 3 + drivers/video/drm/radeon/rdisplay_kms.c | 215 +++++++- drivers/video/drm/radeon/rs400.c | 6 + drivers/video/drm/radeon/rv515.c | 6 + drivers/video/drm/radeon/si.c | 18 +- 51 files changed, 1597 insertions(+), 217 deletions(-) delete mode 100644 drivers/devman/acpica/tools/acpiexec/aetables.o create mode 100644 drivers/video/drm/radeon/bitmap.c create mode 100644 drivers/video/drm/radeon/bitmap.h create mode 100644 drivers/video/drm/radeon/clip.inc create mode 100644 drivers/video/drm/radeon/hmm.c create mode 100644 drivers/video/drm/radeon/hmm.h diff --git a/drivers/devman/acpica/tools/acpiexec/aetables.o b/drivers/devman/acpica/tools/acpiexec/aetables.o deleted file mode 100644 index bcb03a6b8c846ba7cf7e257cd4064f5a2233822e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12337 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 diff --git a/drivers/include/ddk.h b/drivers/include/ddk.h index 3840418c9f..429206cfae 100644 --- a/drivers/include/ddk.h +++ b/drivers/include/ddk.h @@ -19,6 +19,7 @@ #define ENTER() dbgprintf("enter %s\n",__FUNCTION__) #define LEAVE() dbgprintf("leave %s\n",__FUNCTION__) +#define FAIL() dbgprintf("fail %s\n",__FUNCTION__) typedef struct { diff --git a/drivers/include/drm/drmP.h b/drivers/include/drm/drmP.h index 1eb8f86ebe..fe892fab0b 100644 --- a/drivers/include/drm/drmP.h +++ b/drivers/include/drm/drmP.h @@ -170,7 +170,7 @@ int drm_err(const char *func, const char *format, ...); /** \name Begin the DRM... */ /*@{*/ -#define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then +#define DRM_DEBUG_CODE 2 /**< Include debugging code if > 1, then also include looping detection. */ #define DRM_MAGIC_HASH_ORDER 4 /**< Size of key hash table. Must be power of 2. */ diff --git a/drivers/include/drm/drm_pciids.h b/drivers/include/drm/drm_pciids.h index f6b19a497e..d216543b13 100644 --- a/drivers/include/drm/drm_pciids.h +++ b/drivers/include/drm/drm_pciids.h @@ -210,6 +210,7 @@ {0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x679B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ diff --git a/drivers/include/linux/backlight.h b/drivers/include/linux/backlight.h index e69de29bb2..915ec8673e 100644 --- a/drivers/include/linux/backlight.h +++ b/drivers/include/linux/backlight.h @@ -0,0 +1,10 @@ +/* + * Backlight Lowlevel Control Abstraction + * + * Copyright (C) 2003,2004 Hewlett-Packard Company + * + */ + +#ifndef _LINUX_BACKLIGHT_H +#define _LINUX_BACKLIGHT_H +#endif diff --git a/drivers/include/linux/delay.h b/drivers/include/linux/delay.h index e69de29bb2..f7f7d72576 100644 --- a/drivers/include/linux/delay.h +++ b/drivers/include/linux/delay.h @@ -0,0 +1,9 @@ +#ifndef _LINUX_DELAY_H +#define _LINUX_DELAY_H + +/* + * Copyright (C) 1993 Linus Torvalds + * + * Delay routines, using a pre-computed "loops_per_jiffy" value. + */ +#endif /* defined(_LINUX_DELAY_H) */ diff --git a/drivers/include/linux/fb.h b/drivers/include/linux/fb.h index 03686f60a8..7c9000ca42 100644 --- a/drivers/include/linux/fb.h +++ b/drivers/include/linux/fb.h @@ -566,6 +566,7 @@ struct fb_blit_caps { u32 flags; }; +extern int fb_notifier_call_chain(unsigned long val, void *v); /* * Pixmap structure definition * @@ -1085,9 +1086,11 @@ extern int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var, extern int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info); extern int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var); -//extern const unsigned char *fb_firmware_edid(struct device *device); +extern const unsigned char *fb_firmware_edid(struct device *device); extern void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs); +extern void fb_edid_add_monspecs(unsigned char *edid, + struct fb_monspecs *specs); extern void fb_destroy_modedb(struct fb_videomode *modedb); extern int fb_find_mode_cvt(struct fb_videomode *mode, int margins, int rb); extern unsigned char *fb_ddc_read(struct i2c_adapter *adapter); diff --git a/drivers/include/linux/lockdep.h b/drivers/include/linux/lockdep.h index 4029437aa3..cca3316411 100644 --- a/drivers/include/linux/lockdep.h +++ b/drivers/include/linux/lockdep.h @@ -386,6 +386,8 @@ struct lock_class_key { }; #define lockdep_assert_held(l) do { } while (0) +#define lockdep_recursing(tsk) (0) + #endif /* !LOCKDEP */ #ifdef CONFIG_LOCK_STAT diff --git a/drivers/include/linux/mod_devicetable.h b/drivers/include/linux/mod_devicetable.h index 6f5491b7fe..3fd3e38e74 100644 --- a/drivers/include/linux/mod_devicetable.h +++ b/drivers/include/linux/mod_devicetable.h @@ -118,6 +118,9 @@ struct usb_device_id { __u8 bInterfaceSubClass; __u8 bInterfaceProtocol; + /* Used for vendor-specific interface matches */ + __u8 bInterfaceNumber; + /* not matched against */ kernel_ulong_t driver_info; }; diff --git a/drivers/include/linux/stddef.h b/drivers/include/linux/stddef.h index c8c7c32fb8..4cf5497667 100644 --- a/drivers/include/linux/stddef.h +++ b/drivers/include/linux/stddef.h @@ -4,13 +4,7 @@ #include #undef NULL -#if defined(__cplusplus) -#define NULL 0 -#else #define NULL ((void *)0) -#endif - -#ifdef __KERNEL__ enum { false = 0, @@ -23,6 +17,4 @@ enum { #else #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) #endif -#endif /* __KERNEL__ */ - #endif diff --git a/drivers/include/linux/string.h b/drivers/include/linux/string.h index e943a99aad..9132d7a2d4 100644 --- a/drivers/include/linux/string.h +++ b/drivers/include/linux/string.h @@ -1,11 +1,6 @@ #ifndef _LINUX_STRING_H_ #define _LINUX_STRING_H_ -/* We don't want strings.h stuff being used by user stuff by accident */ - -#ifndef __KERNEL__ -#include -#else #include /* for inline */ #include /* for size_t */ @@ -144,5 +139,7 @@ static inline bool strstarts(const char *str, const char *prefix) { return strncmp(str, prefix, strlen(prefix)) == 0; } -#endif + +extern size_t memweight(const void *ptr, size_t bytes); + #endif /* _LINUX_STRING_H_ */ diff --git a/drivers/video/drm/drm_edid.c b/drivers/video/drm/drm_edid.c index b1b196f139..00ab7a08d2 100644 --- a/drivers/video/drm/drm_edid.c +++ b/drivers/video/drm/drm_edid.c @@ -184,7 +184,9 @@ bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid) for (i = 0; i < EDID_LENGTH; i++) csum += raw_edid[i]; if (csum) { + if (print_bad_edid) { DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum); + } /* allow CEA to slide through, switches mangle this */ if (raw_edid[0] != 0x02) @@ -210,7 +212,7 @@ bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid) return 1; bad: - if (raw_edid) { + if (raw_edid && print_bad_edid) { printk(KERN_ERR "Raw EDID:\n"); // print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH); } diff --git a/drivers/video/drm/i2c/i2c-algo-bit.c b/drivers/video/drm/i2c/i2c-algo-bit.c index 9731b366d7..e56c32429a 100644 --- a/drivers/video/drm/i2c/i2c-algo-bit.c +++ b/drivers/video/drm/i2c/i2c-algo-bit.c @@ -111,7 +111,7 @@ static int sclhi(struct i2c_algo_bit_data *adap) break; return -ETIMEDOUT; } - udelay(1); + asm volatile("rep; nop" ::: "memory"); } done: udelay(adap->udelay); diff --git a/drivers/video/drm/i915/i915_drv.c b/drivers/video/drm/i915/i915_drv.c index 71cfefbaa3..55249f7f77 100644 --- a/drivers/video/drm/i915/i915_drv.c +++ b/drivers/video/drm/i915/i915_drv.c @@ -640,10 +640,23 @@ __i915_read(64, q) #define __i915_write(x, y) \ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \ + u32 __fifo_ret = 0; \ + trace_i915_reg_rw(true, reg, val, sizeof(val)); \ if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \ - __gen6_gt_wait_for_fifo(dev_priv); \ + __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ } \ + if (IS_VALLEYVIEW(dev_priv->dev) && IS_DISPLAYREG(reg)) { \ + write##y(val, dev_priv->regs + reg + 0x180000); \ + } else { \ write##y(val, dev_priv->regs + reg); \ + } \ + if (unlikely(__fifo_ret)) { \ + gen6_gt_check_fifodbg(dev_priv); \ + } \ + if (IS_HASWELL(dev_priv->dev) && (I915_READ_NOTRACE(GEN7_ERR_INT) & ERR_INT_MMIO_UNCLAIMED)) { \ + DRM_ERROR("Unclaimed write to %x\n", reg); \ + writel(ERR_INT_MMIO_UNCLAIMED, dev_priv->regs + GEN7_ERR_INT); \ + } \ } __i915_write(8, b) __i915_write(16, w) diff --git a/drivers/video/drm/i915/intel_bios.c b/drivers/video/drm/i915/intel_bios.c index 81dac5e0d5..73f08f4843 100644 --- a/drivers/video/drm/i915/intel_bios.c +++ b/drivers/video/drm/i915/intel_bios.c @@ -498,12 +498,8 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) edp = find_section(bdb, BDB_EDP); if (!edp) { - if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) { - DRM_DEBUG_KMS("No eDP BDB found but eDP panel " - "supported, assume %dbpp panel color " - "depth.\n", - dev_priv->edp.bpp); - } + if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) + DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n"); return; } @@ -656,11 +652,9 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) dev_priv->lvds_use_ssc = 1; dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1); DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq); - - /* eDP data */ - dev_priv->edp.bpp = 18; } + /** * intel_parse_bios - find VBT and initialize settings from the BIOS * @dev: DRM device diff --git a/drivers/video/drm/i915/intel_crt.c b/drivers/video/drm/i915/intel_crt.c index 49522ae20a..821f0b8c5b 100644 --- a/drivers/video/drm/i915/intel_crt.c +++ b/drivers/video/drm/i915/intel_crt.c @@ -142,7 +142,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode) int old_dpms; /* PCH platforms and VLV only support on/off. */ - if (INTEL_INFO(dev)->gen < 5 && mode != DRM_MODE_DPMS_ON) + if (INTEL_INFO(dev)->gen >= 5 && mode != DRM_MODE_DPMS_ON) mode = DRM_MODE_DPMS_OFF; if (mode == connector->dpms) diff --git a/drivers/video/drm/i915/intel_display.c b/drivers/video/drm/i915/intel_display.c index ba9af2c4d0..b884410007 100644 --- a/drivers/video/drm/i915/intel_display.c +++ b/drivers/video/drm/i915/intel_display.c @@ -3857,6 +3857,17 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, } } + if (intel_encoder->type == INTEL_OUTPUT_EDP) { + /* Use VBT settings if we have an eDP panel */ + unsigned int edp_bpc = dev_priv->edp.bpp / 3; + + if (edp_bpc < display_bpc) { + DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); + display_bpc = edp_bpc; + } + continue; + } + /* * HDMI is either 12 or 8, so if the display lets 10bpc sneak * through, clamp it down. (Note: >12bpc will be caught below.) diff --git a/drivers/video/drm/i915/intel_pm.c b/drivers/video/drm/i915/intel_pm.c index ebdbc05c5d..b533b1d87c 100644 --- a/drivers/video/drm/i915/intel_pm.c +++ b/drivers/video/drm/i915/intel_pm.c @@ -2398,15 +2398,9 @@ int intel_enable_rc6(const struct drm_device *dev) if (i915_enable_rc6 >= 0) return i915_enable_rc6; - if (INTEL_INFO(dev)->gen == 5) { -#ifdef CONFIG_INTEL_IOMMU - /* Disable rc6 on ilk if VT-d is on. */ - if (intel_iommu_gfx_mapped) - return false; -#endif - DRM_DEBUG_DRIVER("Ironlake: only RC6 available\n"); - return INTEL_RC6_ENABLE; - } + /* Disable RC6 on Ironlake */ + if (INTEL_INFO(dev)->gen == 5) + return 0; if (IS_HASWELL(dev)) { DRM_DEBUG_DRIVER("Haswell: only RC6 available\n"); diff --git a/drivers/video/drm/i915/intel_sdvo.c b/drivers/video/drm/i915/intel_sdvo.c index 20c58a2ace..7d5a17347a 100644 --- a/drivers/video/drm/i915/intel_sdvo.c +++ b/drivers/video/drm/i915/intel_sdvo.c @@ -2212,7 +2212,6 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; intel_sdvo->is_hdmi = true; } - intel_sdvo->base.cloneable = true; intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); if (intel_sdvo->is_hdmi) @@ -2243,7 +2242,6 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) intel_sdvo->is_tv = true; intel_sdvo->base.needs_tv_clock = true; - intel_sdvo->base.cloneable = false; intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); @@ -2286,8 +2284,6 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device) intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1; } - intel_sdvo->base.cloneable = true; - intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); return true; @@ -2318,9 +2314,6 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1; } - /* SDVO LVDS is not cloneable because the input mode gets adjusted by the encoder */ - intel_sdvo->base.cloneable = false; - intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo); if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) goto err; @@ -2393,6 +2386,18 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags) return true; } +static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo) +{ + struct drm_device *dev = intel_sdvo->base.base.dev; + struct drm_connector *connector, *tmp; + + list_for_each_entry_safe(connector, tmp, + &dev->mode_config.connector_list, head) { + if (intel_attached_encoder(connector) == &intel_sdvo->base) + intel_sdvo_destroy(connector); + } +} + static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo, struct intel_sdvo_connector *intel_sdvo_connector, int type) @@ -2716,9 +2721,20 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) intel_sdvo->caps.output_flags) != true) { DRM_DEBUG_KMS("SDVO output failed to setup on %s\n", SDVO_NAME(intel_sdvo)); - goto err; + /* Output_setup can leave behind connectors! */ + goto err_output; } + /* + * Cloning SDVO with anything is often impossible, since the SDVO + * encoder can request a special input timing mode. And even if that's + * not the case we have evidence that cloning a plain unscaled mode with + * VGA doesn't really work. Furthermore the cloning flags are way too + * simplistic anyway to express such constraints, so just give up on + * cloning for SDVO encoders. + */ + intel_sdvo->base.cloneable = false; + /* Only enable the hotplug irq if we need it, to work around noisy * hotplug lines. */ @@ -2729,12 +2745,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) /* Set the input timing to the screen. Assume always input 0. */ if (!intel_sdvo_set_target_input(intel_sdvo)) - goto err; + goto err_output; if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo, &intel_sdvo->pixel_clock_min, &intel_sdvo->pixel_clock_max)) - goto err; + goto err_output; DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, " "clock range %dMHz - %dMHz, " @@ -2754,6 +2770,9 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob) (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); return true; +err_output: + intel_sdvo_output_cleanup(intel_sdvo); + err: drm_encoder_cleanup(&intel_encoder->base); // i2c_del_adapter(&intel_sdvo->ddc); diff --git a/drivers/video/drm/i915/kms_display.c b/drivers/video/drm/i915/kms_display.c index a2697c287a..5c3862b6a0 100644 --- a/drivers/video/drm/i915/kms_display.c +++ b/drivers/video/drm/i915/kms_display.c @@ -680,7 +680,7 @@ i915_gem_execbuffer_retire_commands(struct drm_device *dev, (void)i915_add_request(ring, file, NULL); } -int blit_video(u32 hbitmap, int dst_x, int dst_y, +int srv_blit_bitmap(u32 hbitmap, int dst_x, int dst_y, int src_x, int src_y, u32 w, u32 h) { drm_i915_private_t *dev_priv = main_device->dev_private; @@ -713,6 +713,18 @@ int blit_video(u32 hbitmap, int dst_x, int dst_y, return -1; GetWindowRect(&winrc); + { + static warn_count; + + if(warn_count < 1) + { + printf("left %d top %d right %d bottom %d\n", + winrc.left, winrc.top, winrc.right, winrc.bottom); + printf("bitmap width %d height %d\n", w, h); + warn_count++; + }; + }; + dst_clip.xmin = 0; dst_clip.ymin = 0; @@ -852,6 +864,18 @@ int blit_video(u32 hbitmap, int dst_x, int dst_y, } #endif + { + static warn_count; + + if(warn_count < 1) + { + printf("blit width %d height %d\n", + width, height); + warn_count++; + }; + }; + + if((context->cmd_buffer & 0xFC0)==0xFC0) context->cmd_buffer&= 0xFFFFF000; diff --git a/drivers/video/drm/i915/main.c b/drivers/video/drm/i915/main.c index fb3fa12f1a..d320eb8c0a 100644 --- a/drivers/video/drm/i915/main.c +++ b/drivers/video/drm/i915/main.c @@ -21,7 +21,7 @@ void parse_cmdline(char *cmdline, char *log); int _stdcall display_handler(ioctl_t *io); int init_agp(void); -int blit_video(u32 hbitmap, int dst_x, int dst_y, +int srv_blit_bitmap(u32 hbitmap, int dst_x, int dst_y, int src_x, int src_y, u32 w, u32 h); int blit_textured(u32 hbitmap, int dst_x, int dst_y, @@ -101,9 +101,9 @@ u32_t drvEntry(int action, char *cmdline) #define SRV_LOCK_SURFACE 12 #define SRV_UNLOCK_SURFACE 13 #define SRV_RESIZE_SURFACE 14 - - -#define SRV_BLIT_VIDEO 20 +#define SRV_BLIT_BITMAP 15 +#define SRV_BLIT_TEXTURE 16 +#define SRV_BLIT_VIDEO 17 #define check_input(size) \ if( unlikely((inp==NULL)||(io->inp_size != (size))) ) \ @@ -164,8 +164,8 @@ int _stdcall display_handler(ioctl_t *io) retval = resize_surface((struct io_call_14*)inp); break; - case SRV_BLIT_VIDEO: - blit_video( inp[0], inp[1], inp[2], + case SRV_BLIT_BITMAP: + srv_blit_bitmap( inp[0], inp[1], inp[2], inp[3], inp[4], inp[5], inp[6]); // blit_tex( inp[0], inp[1], inp[2], diff --git a/drivers/video/drm/radeon/Makefile b/drivers/video/drm/radeon/Makefile index d3b1d83628..d712f53872 100644 --- a/drivers/video/drm/radeon/Makefile +++ b/drivers/video/drm/radeon/Makefile @@ -54,6 +54,8 @@ NAME_SRC= \ $(DRM_TOPDIR)/drm_stub.c \ $(DRM_TOPDIR)/i2c/i2c-core.c \ $(DRM_TOPDIR)/i2c/i2c-algo-bit.c \ + bitmap.c \ + hmm.c \ r700_vs.c \ radeon_device.c \ evergreen.c \ diff --git a/drivers/video/drm/radeon/Makefile.lto b/drivers/video/drm/radeon/Makefile.lto index 375a1ac570..ade7ce20a5 100644 --- a/drivers/video/drm/radeon/Makefile.lto +++ b/drivers/video/drm/radeon/Makefile.lto @@ -54,6 +54,8 @@ NAME_SRC= \ $(DRM_TOPDIR)/drm_stub.c \ $(DRM_TOPDIR)/i2c/i2c-core.c \ $(DRM_TOPDIR)/i2c/i2c-algo-bit.c \ + bitmap.c \ + hmm.c \ r700_vs.c \ radeon_device.c \ evergreen.c \ diff --git a/drivers/video/drm/radeon/atombios_crtc.c b/drivers/video/drm/radeon/atombios_crtc.c index d9a2992a50..45fc955ec4 100644 --- a/drivers/video/drm/radeon/atombios_crtc.c +++ b/drivers/video/drm/radeon/atombios_crtc.c @@ -1696,42 +1696,22 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) return ATOM_PPLL2; DRM_ERROR("unable to allocate a PPLL\n"); return ATOM_PPLL_INVALID; - } else if (ASIC_IS_AVIVO(rdev)) { - /* in DP mode, the DP ref clock can come from either PPLL - * depending on the asic: - * DCE3: PPLL1 or PPLL2 - */ - if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) { - /* use the same PPLL for all DP monitors */ - pll = radeon_get_shared_dp_ppll(crtc); - if (pll != ATOM_PPLL_INVALID) - return pll; } else { - /* use the same PPLL for all monitors with the same clock */ - pll = radeon_get_shared_nondp_ppll(crtc); - if (pll != ATOM_PPLL_INVALID) - return pll; - } - /* all other cases */ - pll_in_use = radeon_get_pll_use_mask(crtc); - /* the order shouldn't matter here, but we probably - * need this until we have atomic modeset - */ - if (rdev->flags & RADEON_IS_IGP) { - if (!(pll_in_use & (1 << ATOM_PPLL1))) - return ATOM_PPLL1; - if (!(pll_in_use & (1 << ATOM_PPLL2))) - return ATOM_PPLL2; - } else { - if (!(pll_in_use & (1 << ATOM_PPLL2))) - return ATOM_PPLL2; - if (!(pll_in_use & (1 << ATOM_PPLL1))) - return ATOM_PPLL1; - } - DRM_ERROR("unable to allocate a PPLL\n"); - return ATOM_PPLL_INVALID; - } else { /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */ + /* some atombios (observed in some DCE2/DCE3) code have a bug, + * the matching btw pll and crtc is done through + * PCLK_CRTC[1|2]_CNTL (0x480/0x484) but atombios code use the + * pll (1 or 2) to select which register to write. ie if using + * pll1 it will use PCLK_CRTC1_CNTL (0x480) and if using pll2 + * it will use PCLK_CRTC2_CNTL (0x484), it then use crtc id to + * choose which value to write. Which is reverse order from + * register logic. So only case that works is when pllid is + * same as crtcid or when both pll and crtc are enabled and + * both use same clock. + * + * So just return crtc id as if crtc and pll were hard linked + * together even if they aren't + */ return radeon_crtc->crtc_id; } } diff --git a/drivers/video/drm/radeon/atombios_encoders.c b/drivers/video/drm/radeon/atombios_encoders.c index d3e0bd6216..ba2d3af2f0 100644 --- a/drivers/video/drm/radeon/atombios_encoders.c +++ b/drivers/video/drm/radeon/atombios_encoders.c @@ -1625,7 +1625,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); /* some early dce3.2 boards have a bug in their transmitter control table */ - if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730)) + if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730)) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { diff --git a/drivers/video/drm/radeon/bitmap.c b/drivers/video/drm/radeon/bitmap.c new file mode 100644 index 0000000000..1d89cd38f7 --- /dev/null +++ b/drivers/video/drm/radeon/bitmap.c @@ -0,0 +1,485 @@ + +#include +#include +#include "radeon.h" +#include "hmm.h" +#include "bitmap.h" + +//#define DRIVER_CAPS_0 HW_BIT_BLIT + +#define DRIVER_CAPS_0 0 +#define DRIVER_CAPS_1 0 + +struct context *context_map[256]; + +struct hmm bm_mm; + +extern struct drm_device *main_drm_device; + + +void __attribute__((regparm(1))) destroy_bitmap(bitmap_t *bitmap) +{ +// dma_addr_t *pages = bitmap->obj->allocated_pages; + int i; + + free_handle(&bm_mm, bitmap->handle); + bitmap->handle = 0; +// bitmap->obj->base.read_domains = I915_GEM_DOMAIN_GTT; +// bitmap->obj->base.write_domain = I915_GEM_DOMAIN_CPU; + +// mutex_lock(&main_device->struct_mutex); +// drm_gem_object_unreference(&bitmap->obj->base); +// mutex_unlock(&main_device->struct_mutex); + +// if(pages != NULL) +// { +// for (i = 0; i < bitmap->page_count; i++) +// FreePage(pages[i]); + +// DRM_DEBUG("%s release %d pages\n", __FUNCTION__, bitmap->page_count); + +// free(pages); +// }; + UserFree(bitmap->uaddr); + __DestroyObject(bitmap); +}; + +#if 0 +static int bitmap_get_pages_gtt(struct drm_i915_gem_object *obj) +{ + int page_count; + + /* Get the list of pages out of our struct file. They'll be pinned + * at this point until we release them. + */ + + page_count = obj->base.size / PAGE_SIZE; + BUG_ON(obj->allocated_pages == NULL); + BUG_ON(obj->pages.page != NULL); + + obj->pages.page = obj->allocated_pages; + obj->pages.nents = page_count; + + +// if (obj->tiling_mode != I915_TILING_NONE) +// i915_gem_object_do_bit_17_swizzle(obj); + + return 0; +} + +static void bitmap_put_pages_gtt(struct drm_i915_gem_object *obj) +{ + int ret, i; + + BUG_ON(obj->madv == __I915_MADV_PURGED); + + ret = i915_gem_object_set_to_cpu_domain(obj, true); + if (ret) { + /* In the event of a disaster, abandon all caches and + * hope for the best. + */ + WARN_ON(ret != -EIO); + i915_gem_clflush_object(obj); + obj->base.read_domains = obj->base.write_domain = I915_GEM_DOMAIN_CPU; + } + + if (obj->madv == I915_MADV_DONTNEED) + obj->dirty = 0; + + obj->dirty = 0; +} + +static const struct drm_i915_gem_object_ops bitmap_object_ops = { + .get_pages = bitmap_get_pages_gtt, + .put_pages = bitmap_put_pages_gtt, +}; + + + +struct io_call_10 /* SRV_CREATE_SURFACE */ +{ + u32 handle; // ignored + void *data; // ignored + + u32 width; + u32 height; + u32 pitch; // ignored + + u32 max_width; + u32 max_height; + u32 format; // reserved mbz +}; + +#endif + +int create_surface(struct drm_device *dev, struct io_call_10 *pbitmap) +{ + struct radeon_device *rdev = dev->dev_private; + struct radeon_bo *obj = NULL; + + bitmap_t *bitmap; + u32 handle; + u32 width, max_width; + u32 height, max_height; + u32 size, max_size; + u32 pitch, max_pitch; + void *uaddr; + dma_addr_t *pages; + u32 page_count; + + int i; + + int ret; + + pbitmap->handle = 0; + pbitmap->data = (void*)-1; + + width = pbitmap->width; + height = pbitmap->height; + + if((width == 0)||(height == 0)||(width > 4096)||(height > 4096)) + goto err1; + + max_width = (pbitmap->max_width ==0) ? width : pbitmap->max_width; + max_height = (pbitmap->max_height==0) ? height : pbitmap->max_height; + + handle = alloc_handle(&bm_mm); +// printf("%s %d\n",__FUNCTION__, handle); + + if(handle == 0) + goto err1; + + bitmap = CreateObject(GetPid(), sizeof(*bitmap)); +// printf("bitmap %x\n", bitmap); + if( bitmap == NULL) + goto err2; + + bitmap->handle = handle; + bitmap->header.destroy = destroy_bitmap; + bitmap->obj = NULL; + + hmm_set_data(&bm_mm, handle, bitmap); + + pitch = ALIGN(width*4,64); + size = roundup(pitch*height, PAGE_SIZE); + +// printf("pitch %d size %d\n", pitch, size); + + max_pitch = ALIGN(max_width*4,64); + max_size = roundup(max_pitch*max_height, PAGE_SIZE); + +// printf("max_pitch %d max_size %d\n", max_pitch, max_size); + + ret = radeon_bo_create(rdev, size, PAGE_SIZE, false, RADEON_GEM_DOMAIN_GTT, NULL, &obj); + + if (unlikely(ret != 0)) + goto err3; + + ret = radeon_bo_reserve(obj, false); + if (unlikely(ret != 0)) + goto err3; + + ret = radeon_bo_pin(obj, RADEON_GEM_DOMAIN_GTT, NULL); + if (unlikely(ret != 0)) + goto err3; + + ret = radeon_bo_user_map(obj, (void**)&uaddr); + if (unlikely(ret != 0)) + goto err3; + + bitmap->page_count = size/PAGE_SIZE; + bitmap->max_count = max_size/PAGE_SIZE; + + DRM_DEBUG("%s alloc %d pages\n", __FUNCTION__, page_count); + + bitmap->handle = handle; + bitmap->uaddr = uaddr; + bitmap->pitch = pitch; + bitmap->gaddr = radeon_bo_gpu_offset(obj); + + bitmap->width = width; + bitmap->height = height; + bitmap->max_width = max_width; + bitmap->max_height = max_height; + + bitmap->obj = obj; + bitmap->header.destroy = destroy_bitmap; + + pbitmap->handle = handle; + pbitmap->data = uaddr; + pbitmap->pitch = pitch; + + + DRM_DEBUG("%s handle: %d pitch: %d gpu_addr: %x user_addr: %x\n", + __FUNCTION__, handle, pitch, bitmap->gaddr, uaddr); + + return 0; + +err5: +// mutex_lock(&dev->struct_mutex); +// drm_gem_object_unreference(&obj->base); +// mutex_unlock(&dev->struct_mutex); + +err4: +// while (i--) +// FreePage(pages[i]); +// free(pages); +// UserFree(uaddr); + +err3: + __DestroyObject(bitmap); +err2: + free_handle(&bm_mm, handle); +err1: + return -1; +}; + + +int lock_surface(struct io_call_12 *pbitmap) +{ + int ret; + + bitmap_t *bitmap; + + if(unlikely(pbitmap->handle == 0)) + return -1; + + bitmap = (bitmap_t*)hmm_get_data(&bm_mm, pbitmap->handle); + + if(unlikely(bitmap==NULL)) + return -1; +/* + mutex_lock(&main_device->struct_mutex); + ret = i915_gem_object_set_to_cpu_domain(bitmap->obj, true); + mutex_unlock(&main_device->struct_mutex); + + if(ret != 0 ) + { + pbitmap->data = NULL; + pbitmap->pitch = 0; + + dbgprintf("%s fail\n", __FUNCTION__); + return ret; + }; +*/ + pbitmap->data = bitmap->uaddr; + pbitmap->pitch = bitmap->pitch; + + return 0; +}; + + +#if 0 + +int resize_surface(struct io_call_14 *pbitmap) +{ + bitmap_t *bitmap; + dma_addr_t page, *pages; + u32 size, page_count; + u32 width, height; + u32 pitch; + int i; + int ret = 0; + + + if(unlikely(pbitmap->handle == 0)) + return -1; + + bitmap = (bitmap_t*)hmm_get_data(&bm_mm, pbitmap->handle); + + if(unlikely(bitmap==NULL)) + return -1; + + if( pbitmap->new_width > bitmap->max_width || + pbitmap->new_height > bitmap->max_height) + return -1; + + width = pbitmap->new_width; + height = pbitmap->new_height; + + pitch = ALIGN(width*4,64); + size = roundup(pitch * height, PAGE_SIZE); + page_count = size/PAGE_SIZE; + + DRM_DEBUG("new width %d height %d pitch %d size %d\n", + width, height, pitch, size); + + if(page_count > bitmap->page_count) + { + char *vaddr = bitmap->uaddr + PAGE_SIZE * bitmap->page_count; + + pages = bitmap->obj->allocated_pages; + + DRM_DEBUG("old pages %d new_pages %d vaddr %x\n", + bitmap->page_count, page_count, vaddr); + + for(i = bitmap->page_count; i < page_count; i++, vaddr+= PAGE_SIZE) + { + page = AllocPage(); + if ( page == 0 ) + goto err4; + pages[i] = page; + MapPage(vaddr, page, 0x207); //map as shared page + }; + + DRM_DEBUG("%s alloc %d pages\n", __FUNCTION__, + page_count - bitmap->page_count); + + i915_gem_object_unpin(bitmap->obj); + i915_gem_object_unbind(bitmap->obj); + bitmap->obj->base.size = size; + bitmap->obj->pages.nents = page_count; + + ret = i915_gem_object_pin(bitmap->obj, PAGE_SIZE, true,true); + if (ret) + goto err4; + + bitmap->page_count = page_count; + bitmap->gaddr = bitmap->obj->gtt_offset; + } + else if(page_count < bitmap->page_count) + { + char *vaddr = bitmap->uaddr + PAGE_SIZE * page_count; + + i915_gem_object_unpin(bitmap->obj); + i915_gem_object_unbind(bitmap->obj); + + pages = bitmap->obj->allocated_pages; + + DRM_DEBUG("old pages %d new_pages %d vaddr %x\n", + bitmap->page_count, page_count, vaddr); + + for(i = page_count; i < bitmap->page_count; i++, vaddr+= PAGE_SIZE) + { + MapPage(vaddr, 0, 0); //unmap + + FreePage(pages[i]); + pages[i] = 0; + }; + + DRM_DEBUG("%s release %d pages\n", __FUNCTION__, + bitmap->page_count - page_count); + + bitmap->obj->base.size = size; + bitmap->obj->pages.nents = page_count; + + ret = i915_gem_object_pin(bitmap->obj, PAGE_SIZE, true,true); + if (ret) + goto err3; + + bitmap->page_count = page_count; + bitmap->gaddr = bitmap->obj->gtt_offset; + }; + + bitmap->width = width; + bitmap->height = height; + bitmap->pitch = pitch; + + + pbitmap->data = bitmap->uaddr; + pbitmap->pitch = bitmap->pitch; + + return 0; + +err4: + while (i-- > bitmap->page_count) + FreePage(pages[i]); + +err3: + return -1; +}; +#endif + + +int init_bitmaps() +{ + int ret; + + ret = init_hmm(&bm_mm, 1024); + + return ret; +}; + + + +int get_driver_caps(hwcaps_t *caps) +{ + int ret = 0; + + ENTER(); + switch(caps->idx) + { + case 0: + caps->opt[0] = DRIVER_CAPS_0; + caps->opt[1] = DRIVER_CAPS_1; + break; + + case 1: + caps->cap1.max_tex_width = 4096; + caps->cap1.max_tex_height = 4096; + break; + default: + ret = 1; + }; + caps->idx = 1; + LEAVE(); + return ret; +} + + +void __attribute__((regparm(1))) destroy_context(struct context *context) +{ + struct radeon_device *rdev = main_drm_device->dev_private; + + DRM_DEBUG("destroy context %x\n", context); + + context_map[context->slot] = NULL; + + radeon_ib_free(rdev, &context->ib); + + __DestroyObject(context); +}; + + +#define CURRENT_TASK (0x80003000) + +struct context *get_context(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + struct context *context; + struct io_call_10 io_10; + int slot = *((u8*)CURRENT_TASK); + int ret; + + context = context_map[slot]; + + if( context != NULL) + return context; + + context = CreateObject(GetPid(), sizeof(*context)); + + if( context != NULL) + { + ret = radeon_ib_get(rdev, RADEON_RING_TYPE_GFX_INDEX, &context->ib, NULL, 4096); + if (ret) { + DRM_ERROR("radeon: failed to get ib (%d).\n", ret); + goto err; + }; + + context->cmd_buffer = context->ib.ptr; + + context->header.destroy = destroy_context; + context->mask = NULL; + context->seqno = 0; + context->slot = slot; + + context_map[slot] = context; + }; + return context; + +err: + __DestroyObject(context); + return NULL; +}; + + diff --git a/drivers/video/drm/radeon/bitmap.h b/drivers/video/drm/radeon/bitmap.h new file mode 100644 index 0000000000..b3ece3f030 --- /dev/null +++ b/drivers/video/drm/radeon/bitmap.h @@ -0,0 +1,107 @@ + +typedef struct tag_object kobj_t; +typedef struct tag_display display_t; + + +struct tag_object +{ + uint32_t magic; + void *destroy; + kobj_t *fd; + kobj_t *bk; + uint32_t pid; +}; + +typedef struct +{ + kobj_t header; + + u32 handle; + char *uaddr; + + u32 pitch; + u32 gaddr; + + u32 width; + u32 height; + u32 max_width; + u32 max_height; + u32 page_count; + u32 max_count; + + u32 format; + struct radeon_bo *obj; +}bitmap_t; + + +struct io_call_10 /* SRV_CREATE_SURFACE */ +{ + u32 handle; // ignored + void *data; // ignored + + u32 width; + u32 height; + u32 pitch; // ignored + + u32 max_width; + u32 max_height; + u32 format; // reserved mbz +}; + +struct io_call_12 /* SRV_LOCK_SURFACE */ +{ + u32 handle; + void *data; + u32 pitch; +}; + +struct io_call_14 /* SRV_RESIZE_SURFACE */ +{ + u32 handle; + void *data; + u32 new_width; + u32 new_height; + u32 pitch; +}; + +typedef struct +{ + uint32_t idx; + union + { + uint32_t opt[2]; + struct { + uint32_t max_tex_width; + uint32_t max_tex_height; + }cap1; + }; +}hwcaps_t; + +#define HW_BIT_BLIT (1<<0) /* BGRX blitter */ +#define HW_TEX_BLIT (1<<1) /* stretch blit */ +#define HW_VID_BLIT (1<<2) /* planar and packed video */ + /* 3 - 63 reserved */ +struct context +{ + kobj_t header; + + struct radeon_ib ib; + + u32 cmd_buffer; + u32 cmd_offset; + + bitmap_t *mask; + u32 seqno; + int slot; + +}; + +int get_driver_caps(hwcaps_t *caps); +int create_surface(struct drm_device *dev, struct io_call_10 *pbitmap); +int lock_surface(struct io_call_12 *pbitmap); +int resize_surface(struct io_call_14 *pbitmap); + +struct context *get_context(struct drm_device *dev); + +int init_bitmaps(); + diff --git a/drivers/video/drm/radeon/clip.inc b/drivers/video/drm/radeon/clip.inc new file mode 100644 index 0000000000..607cab97d2 --- /dev/null +++ b/drivers/video/drm/radeon/clip.inc @@ -0,0 +1,121 @@ + +#define CLIP_TOP 1 +#define CLIP_BOTTOM 2 +#define CLIP_RIGHT 4 +#define CLIP_LEFT 8 + +typedef struct +{ + int xmin; + int ymin; + int xmax; + int ymax; +}clip_t; + + +static int _L1OutCode( clip_t *clip, int x, int y ) +/*================================= + + Verify that a point is inside or outside the active viewport. */ +{ + int flag; + + flag = 0; + if( x < clip->xmin ) { + flag |= CLIP_LEFT; + } else if( x > clip->xmax ) { + flag |= CLIP_RIGHT; + } + if( y < clip->ymin ) { + flag |= CLIP_TOP; + } else if( y > clip->ymax ) { + flag |= CLIP_BOTTOM; + } + return( flag ); +}; + +static void block_inter( clip_t *clip, int *x, int *y, int flag ) +/*====================================================== + + Find the intersection of a block with a boundary of the viewport. */ +{ + if( flag & CLIP_TOP ) { + *y = clip->ymin; + } else if( flag & CLIP_BOTTOM ) { + *y = clip->ymax; + } else if( flag & CLIP_RIGHT ) { + *x = clip->xmax; + } else if( flag & CLIP_LEFT ) { + *x = clip->xmin; + } +} + + +int BlockClip(clip_t *clip, int *x1, int *y1, int *x2, int* y2 ) +/*============================================================== + + Clip a block with opposite corners (x1,y1) and (x2,y2) to the + active viewport based on the Cohen-Sutherland algorithm for line + clipping. Return the clipped coordinates and a decision drawing + flag ( 0 draw : 1 don't draw ). */ +{ + int flag1; + int flag2; + + flag1 = _L1OutCode( clip, *x1, *y1 ); + flag2 = _L1OutCode( clip, *x2, *y2 ); + for( ;; ) { + if( flag1 & flag2 ) break; /* trivially outside */ + if( flag1 == flag2 ) break; /* completely inside */ + if( flag1 == 0 ) { + block_inter( clip, x2, y2, flag2 ); + flag2 = _L1OutCode( clip, *x2, *y2 ); + } else { + block_inter( clip, x1, y1, flag1 ); + flag1 = _L1OutCode( clip, *x1, *y1 ); + } + } + return( flag1 & flag2 ); +} + + +int blit_clip(clip_t *dst_clip,int *dst_x,int *dst_y, + clip_t *src_clip,int *src_x, int *src_y, + u32_t *w, u32_t *h) +{ + int sx0, sy0, sx1, sy1; + + sx0 = *src_x; + sy0 = *src_y; + + sx1 = sx0 + *w - 1; + sy1 = sy0 + *h - 1; + + + if( ! BlockClip( src_clip, &sx0, &sy0, &sx1, &sy1)) + { + int dx0, dy0, dx1, dy1; + + dx0 = *dst_x + sx0 - *src_x; + dy0 = *dst_y + sy0 - *src_y; + + dx1 = dx0 + sx1 - sx0; + dy1 = dy0 + sy1 - sy0; + + if( ! BlockClip( dst_clip, &dx0, &dy0, &dx1, &dy1)) + { + *w = dx1 - dx0 + 1; + *h = dy1 - dy0 + 1; + + *src_x += dx0 - *dst_x; + *src_y += dy0 - *dst_y; + + *dst_x = dx0; + *dst_y = dy0; + + return 0; + }; + } + return 1; +}; + diff --git a/drivers/video/drm/radeon/display.h b/drivers/video/drm/radeon/display.h index 6f695a01b4..0fe33c21f2 100644 --- a/drivers/video/drm/radeon/display.h +++ b/drivers/video/drm/radeon/display.h @@ -1,16 +1,6 @@ -typedef struct tag_object kobj_t; typedef struct tag_display display_t; -struct tag_object -{ - uint32_t magic; - void *destroy; - kobj_t *fd; - kobj_t *bk; - uint32_t pid; -}; - typedef struct { kobj_t header; diff --git a/drivers/video/drm/radeon/evergreen.c b/drivers/video/drm/radeon/evergreen.c index 71b83b2285..8ccbee04a4 100644 --- a/drivers/video/drm/radeon/evergreen.c +++ b/drivers/video/drm/radeon/evergreen.c @@ -1243,6 +1243,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav break; udelay(1); } + } else { + save->crtc_enabled[i] = false; } } @@ -1561,7 +1563,7 @@ static int evergreen_cp_resume(struct radeon_device *rdev) ring->wptr = 0; WREG32(CP_RB_WPTR, ring->wptr); - /* set the wb address wether it's enabled or not */ + /* set the wb address whether it's enabled or not */ WREG32(CP_RB_RPTR_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC)); WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF); diff --git a/drivers/video/drm/radeon/hmm.c b/drivers/video/drm/radeon/hmm.c new file mode 100644 index 0000000000..01c5cf8916 --- /dev/null +++ b/drivers/video/drm/radeon/hmm.c @@ -0,0 +1,71 @@ + +#include +#include +#include "hmm.h" + +int init_hmm(struct hmm *mm, u32 count) +{ + u32* data; + + if( mm == NULL) + return -EINVAL; + + data = malloc(count*sizeof(u32*)); + if( data ) + { + int i; + + for(i = 0; i < count-1; ) + data[i] = ++i; + data[i] = 0; + + mm->table = data; + mm->next = 0; + mm->avail = count; + mm->count = count; + + return 0; + }; + return -ENOMEM; +}; + +u32 alloc_handle(struct hmm *mm) +{ + u32 handle = 0; + u32 ifl; + + ifl = safe_cli(); + if(mm->avail) + { + handle = mm->next; + mm->next = mm->table[handle]; + mm->avail--; + handle++; + } + safe_sti(ifl); + + return handle; +}; + +int free_handle(struct hmm *mm, u32 handle) +{ + int ret = -1; + u32 ifl; + + handle--; + + ifl = safe_cli(); + if(handle < mm->count) + { + mm->table[handle] = mm->next; + mm->next = handle; + mm->avail++; + ret = 0; + }; + safe_sti(ifl); + + return ret; +}; + + + diff --git a/drivers/video/drm/radeon/hmm.h b/drivers/video/drm/radeon/hmm.h new file mode 100644 index 0000000000..dfb43d6128 --- /dev/null +++ b/drivers/video/drm/radeon/hmm.h @@ -0,0 +1,24 @@ + +#ifndef __HMM_H__ +#define __HMM_H__ + +struct hmm +{ + u32 *table; + u32 next; + u32 avail; + u32 count; +}; + +int init_hmm(struct hmm *mm, u32 count); +u32 alloc_handle(struct hmm *mm); +int free_handle(struct hmm *mm, u32 handle); + +#define hmm_get_data(mm, handle) \ + ((mm)->table[(handle)-1]) + +#define hmm_set_data(mm, handle, val) \ + ((mm)->table[(handle)-1]) = (u32)(val) + + +#endif /* __HMM_H__ */ diff --git a/drivers/video/drm/radeon/ni.c b/drivers/video/drm/radeon/ni.c index b76cacf573..027a415d1e 100644 --- a/drivers/video/drm/radeon/ni.c +++ b/drivers/video/drm/radeon/ni.c @@ -1044,7 +1044,7 @@ static int cayman_cp_resume(struct radeon_device *rdev) WREG32(CP_DEBUG, (1 << 27)); - /* set the wb address wether it's enabled or not */ + /* set the wb address whether it's enabled or not */ WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); WREG32(SCRATCH_UMSK, 0xff); @@ -1061,7 +1061,7 @@ static int cayman_cp_resume(struct radeon_device *rdev) #endif WREG32(cp_rb_cntl[i], rb_cntl); - /* set the wb address wether it's enabled or not */ + /* set the wb address whether it's enabled or not */ addr = rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET; WREG32(cp_rb_rptr_addr[i], addr & 0xFFFFFFFC); WREG32(cp_rb_rptr_addr_hi[i], upper_32_bits(addr) & 0xFF); diff --git a/drivers/video/drm/radeon/r100.c b/drivers/video/drm/radeon/r100.c index 58da96971f..2828bd477f 100644 --- a/drivers/video/drm/radeon/r100.c +++ b/drivers/video/drm/radeon/r100.c @@ -391,6 +391,7 @@ int r100_irq_process(struct radeon_device *rdev) uint32_t status, msi_rearm; bool queue_hotplug = false; + status = r100_irq_ack(rdev); if (!status) { return IRQ_NONE; @@ -3576,6 +3577,12 @@ static int r100_startup(struct radeon_device *rdev) if (r) return r; + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + /* Enable IRQ */ r100_irq_set(rdev); rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); @@ -3591,6 +3598,7 @@ static int r100_startup(struct radeon_device *rdev) dev_err(rdev->dev, "IB initialization failed (%d).\n", r); return r; } + return 0; } diff --git a/drivers/video/drm/radeon/r300.c b/drivers/video/drm/radeon/r300.c index d507811a2e..bb27935ca5 100644 --- a/drivers/video/drm/radeon/r300.c +++ b/drivers/video/drm/radeon/r300.c @@ -1380,6 +1380,12 @@ static int r300_startup(struct radeon_device *rdev) if (r) return r; + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + /* Enable IRQ */ r100_irq_set(rdev); rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); diff --git a/drivers/video/drm/radeon/r420.c b/drivers/video/drm/radeon/r420.c index f03d2523b2..e745842301 100644 --- a/drivers/video/drm/radeon/r420.c +++ b/drivers/video/drm/radeon/r420.c @@ -219,6 +219,12 @@ static int r420_startup(struct radeon_device *rdev) if (r) return r; + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + /* Enable IRQ */ r100_irq_set(rdev); rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); diff --git a/drivers/video/drm/radeon/r520.c b/drivers/video/drm/radeon/r520.c index 4f3727fb4b..0aa88eaa67 100644 --- a/drivers/video/drm/radeon/r520.c +++ b/drivers/video/drm/radeon/r520.c @@ -187,6 +187,12 @@ static int r520_startup(struct radeon_device *rdev) if (r) return r; + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + /* Enable IRQ */ rs600_irq_set(rdev); rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); diff --git a/drivers/video/drm/radeon/radeon.h b/drivers/video/drm/radeon/radeon.h index 71f6c395bc..4f85c1d4e5 100644 --- a/drivers/video/drm/radeon/radeon.h +++ b/drivers/video/drm/radeon/radeon.h @@ -370,6 +370,7 @@ struct radeon_bo { /* Constant after initialization */ struct radeon_device *rdev; struct drm_gem_object gem_base; + u32 domain; int vmapping_count; }; diff --git a/drivers/video/drm/radeon/radeon_asic.c b/drivers/video/drm/radeon/radeon_asic.c index 49b033fd94..29c7932ef9 100644 --- a/drivers/video/drm/radeon/radeon_asic.c +++ b/drivers/video/drm/radeon/radeon_asic.c @@ -685,8 +685,8 @@ static struct radeon_asic rs600_asic = { // .set_engine_clock = &radeon_atom_set_engine_clock, // .get_memory_clock = &radeon_atom_get_memory_clock, // .set_memory_clock = &radeon_atom_set_memory_clock, -// .get_pcie_lanes = NULL, -// .set_pcie_lanes = NULL, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, // .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = { @@ -761,8 +761,8 @@ static struct radeon_asic rs690_asic = { // .set_engine_clock = &radeon_atom_set_engine_clock, // .get_memory_clock = &radeon_atom_get_memory_clock, // .set_memory_clock = &radeon_atom_set_memory_clock, -// .get_pcie_lanes = NULL, -// .set_pcie_lanes = NULL, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, // .set_clock_gating = &radeon_atom_set_clock_gating, }, .pflip = { @@ -990,7 +990,7 @@ static struct radeon_asic r600_asic = { // .set_memory_clock = &radeon_atom_set_memory_clock, // .get_pcie_lanes = &r600_get_pcie_lanes, // .set_pcie_lanes = &r600_set_pcie_lanes, -// .set_clock_gating = NULL, + .set_clock_gating = NULL, }, .pflip = { // .pre_page_flip = &rs600_pre_page_flip, @@ -1061,11 +1061,11 @@ static struct radeon_asic rs780_asic = { // .get_dynpm_state = &r600_pm_get_dynpm_state, // .get_engine_clock = &radeon_atom_get_engine_clock, // .set_engine_clock = &radeon_atom_set_engine_clock, -// .get_memory_clock = NULL, -// .set_memory_clock = NULL, -// .get_pcie_lanes = NULL, -// .set_pcie_lanes = NULL, -// .set_clock_gating = NULL, + .get_memory_clock = NULL, + .set_memory_clock = NULL, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = NULL, }, .pflip = { // .pre_page_flip = &rs600_pre_page_flip, @@ -1286,11 +1286,11 @@ static struct radeon_asic sumo_asic = { // .get_dynpm_state = &r600_pm_get_dynpm_state, // .get_engine_clock = &radeon_atom_get_engine_clock, // .set_engine_clock = &radeon_atom_set_engine_clock, -// .get_memory_clock = NULL, -// .set_memory_clock = NULL, -// .get_pcie_lanes = NULL, -// .set_pcie_lanes = NULL, -// .set_clock_gating = NULL, + .get_memory_clock = NULL, + .set_memory_clock = NULL, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = NULL, }, .pflip = { // .pre_page_flip = &evergreen_pre_page_flip, @@ -1363,9 +1363,9 @@ static struct radeon_asic btc_asic = { // .set_engine_clock = &radeon_atom_set_engine_clock, // .get_memory_clock = &radeon_atom_get_memory_clock, // .set_memory_clock = &radeon_atom_set_memory_clock, -// .get_pcie_lanes = NULL, -// .set_pcie_lanes = NULL, -// .set_clock_gating = NULL, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = NULL, }, .pflip = { // .pre_page_flip = &evergreen_pre_page_flip, @@ -1468,9 +1468,9 @@ static struct radeon_asic cayman_asic = { // .set_engine_clock = &radeon_atom_set_engine_clock, // .get_memory_clock = &radeon_atom_get_memory_clock, // .set_memory_clock = &radeon_atom_set_memory_clock, -// .get_pcie_lanes = NULL, -// .set_pcie_lanes = NULL, -// .set_clock_gating = NULL, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = NULL, }, .pflip = { // .pre_page_flip = &evergreen_pre_page_flip, @@ -1571,11 +1571,11 @@ static struct radeon_asic trinity_asic = { // .get_dynpm_state = &r600_pm_get_dynpm_state, // .get_engine_clock = &radeon_atom_get_engine_clock, // .set_engine_clock = &radeon_atom_set_engine_clock, -// .get_memory_clock = NULL, -// .set_memory_clock = NULL, -// .get_pcie_lanes = NULL, -// .set_pcie_lanes = NULL, -// .set_clock_gating = NULL, + .get_memory_clock = NULL, + .set_memory_clock = NULL, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = NULL, }, .pflip = { // .pre_page_flip = &evergreen_pre_page_flip, @@ -1610,7 +1610,7 @@ static struct radeon_asic si_asic = { // .ib_parse = &si_ib_parse, .emit_fence = &si_fence_ring_emit, .emit_semaphore = &r600_semaphore_ring_emit, -// .cs_parse = NULL, + .cs_parse = NULL, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, .is_lockup = &si_gpu_is_lockup, @@ -1621,7 +1621,7 @@ static struct radeon_asic si_asic = { // .ib_parse = &si_ib_parse, .emit_fence = &si_fence_ring_emit, .emit_semaphore = &r600_semaphore_ring_emit, -// .cs_parse = NULL, + .cs_parse = NULL, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, .is_lockup = &si_gpu_is_lockup, @@ -1632,7 +1632,7 @@ static struct radeon_asic si_asic = { // .ib_parse = &si_ib_parse, .emit_fence = &si_fence_ring_emit, .emit_semaphore = &r600_semaphore_ring_emit, -// .cs_parse = NULL, + .cs_parse = NULL, .ring_test = &r600_ring_test, .ib_test = &r600_ib_test, .is_lockup = &si_gpu_is_lockup, @@ -1678,9 +1678,9 @@ static struct radeon_asic si_asic = { // .set_engine_clock = &radeon_atom_set_engine_clock, // .get_memory_clock = &radeon_atom_get_memory_clock, // .set_memory_clock = &radeon_atom_set_memory_clock, -// .get_pcie_lanes = NULL, -// .set_pcie_lanes = NULL, -// .set_clock_gating = NULL, + .get_pcie_lanes = NULL, + .set_pcie_lanes = NULL, + .set_clock_gating = NULL, }, .pflip = { // .pre_page_flip = &evergreen_pre_page_flip, diff --git a/drivers/video/drm/radeon/radeon_bios.c b/drivers/video/drm/radeon/radeon_bios.c index 676ab705ea..03cfbdb176 100644 --- a/drivers/video/drm/radeon/radeon_bios.c +++ b/drivers/video/drm/radeon/radeon_bios.c @@ -198,7 +198,7 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) return true; } #else -static bool radeon_atrm_get_bios(struct radeon_device *rdev) +static inline bool radeon_atrm_get_bios(struct radeon_device *rdev) { return false; } diff --git a/drivers/video/drm/radeon/radeon_connectors.c b/drivers/video/drm/radeon/radeon_connectors.c index e2024dd673..9ff2099ddc 100644 --- a/drivers/video/drm/radeon/radeon_connectors.c +++ b/drivers/video/drm/radeon/radeon_connectors.c @@ -941,7 +941,8 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) struct drm_mode_object *obj; int i; enum drm_connector_status ret = connector_status_disconnected; - bool dret = false; + bool dret = false, broken_edid = false; + if (!force && radeon_check_hpd_status_unchanged(connector)) return connector->status; @@ -965,6 +966,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) ret = connector_status_disconnected; DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector)); radeon_connector->ddc_bus = NULL; + } else { + ret = connector_status_connected; + broken_edid = true; /* defer use_digital to later */ } } else { radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); @@ -1047,13 +1051,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) encoder_funcs = encoder->helper_private; if (encoder_funcs->detect) { + if (!broken_edid) { if (ret != connector_status_connected) { + /* deal with analog monitors without DDC */ ret = encoder_funcs->detect(encoder, connector); if (ret == connector_status_connected) { radeon_connector->use_digital = false; } if (ret != connector_status_disconnected) radeon_connector->detected_by_load = true; + } + } else { + enum drm_connector_status lret; + /* assume digital unless load detected otherwise */ + radeon_connector->use_digital = true; + lret = encoder_funcs->detect(encoder, connector); + DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret); + if (lret == connector_status_connected) + radeon_connector->use_digital = false; } break; } diff --git a/drivers/video/drm/radeon/radeon_device.c b/drivers/video/drm/radeon/radeon_device.c index 6ac5ccd4ec..405b9177ac 100644 --- a/drivers/video/drm/radeon/radeon_device.c +++ b/drivers/video/drm/radeon/radeon_device.c @@ -33,8 +33,11 @@ #include "radeon_reg.h" #include "radeon.h" #include "atom.h" + +#include "bitmap.h" #include "display.h" + #include @@ -62,6 +65,8 @@ int irq_override = 0; extern display_t *rdisplay; +struct drm_device *main_drm_device; + void parse_cmdline(char *cmdline, videomode_t *mode, char *log, int *kms); int init_display(struct radeon_device *rdev, videomode_t *mode); @@ -1242,6 +1247,8 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) goto err_g4; + main_drm_device = dev; + if( radeon_modeset ) init_display_kms(dev->dev_private, &usermode); else @@ -1317,15 +1324,25 @@ static struct pci_device_id pciidlist[] = { }; -#define API_VERSION 0x01000100 +#define CURRENT_API 0x0200 /* 2.00 */ +#define COMPATIBLE_API 0x0100 /* 1.00 */ + +#define API_VERSION (COMPATIBLE_API << 16) | CURRENT_API #define SRV_GETVERSION 0 #define SRV_ENUM_MODES 1 #define SRV_SET_MODE 2 +#define SRV_GET_CAPS 3 + +#define SRV_CREATE_SURFACE 10 +#define SRV_DESTROY_SURFACE 11 +#define SRV_LOCK_SURFACE 12 +#define SRV_UNLOCK_SURFACE 13 +#define SRV_RESIZE_SURFACE 14 +#define SRV_BLIT_BITMAP 15 +#define SRV_BLIT_TEXTURE 16 +#define SRV_BLIT_VIDEO 17 -#define SRV_CREATE_VIDEO 9 -#define SRV_BLIT_VIDEO 10 -#define SRV_CREATE_BITMAP 11 int r600_video_blit(uint64_t src_offset, int x, int y, @@ -1372,23 +1389,23 @@ int _stdcall display_handler(ioctl_t *io) retval = set_user_mode((videomode_t*)inp); break; - case SRV_CREATE_VIDEO: -// retval = r600_create_video(inp[0], inp[1], outp); + case SRV_GET_CAPS: + retval = get_driver_caps((hwcaps_t*)inp); break; - case SRV_BLIT_VIDEO: -// r600_video_blit( ((uint64_t*)inp)[0], inp[2], inp[3], -// inp[4], inp[5], inp[6]); - - retval = 0; + case SRV_CREATE_SURFACE: +// check_input(8); + retval = create_surface(main_drm_device, (struct io_call_10*)inp); break; - case SRV_CREATE_BITMAP: - check_input(8); - check_output(4); -// retval = create_bitmap(outp, inp[0], inp[1]); + case SRV_LOCK_SURFACE: + retval = lock_surface((struct io_call_12*)inp); break; + case SRV_BLIT_BITMAP: + srv_blit_bitmap( inp[0], inp[1], inp[2], + inp[3], inp[4], inp[5], inp[6]); + }; return retval; diff --git a/drivers/video/drm/radeon/radeon_irq_kms.c b/drivers/video/drm/radeon/radeon_irq_kms.c index 9072850e3c..322e3c3dc1 100644 --- a/drivers/video/drm/radeon/radeon_irq_kms.c +++ b/drivers/video/drm/radeon/radeon_irq_kms.c @@ -34,7 +34,13 @@ #define RADEON_WAIT_IDLE_TIMEOUT 200 -struct radeon_device *main_device; +#define DRM_IRQ_ARGS void *arg + +struct drm_driver { + irqreturn_t(*irq_handler) (DRM_IRQ_ARGS); + void (*irq_preinstall) (struct drm_device *dev); + int (*irq_postinstall) (struct drm_device *dev); +}; extern int irq_override; @@ -48,9 +54,12 @@ extern int irq_override; * radeon_irq_process is a macro that points to the per-asic * irq handler callback. */ -void irq_handler_kms() +irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) { - radeon_irq_process(main_device); + struct drm_device *dev = (struct drm_device *) arg; + struct radeon_device *rdev = dev->dev_private; + + return radeon_irq_process(rdev); } /** @@ -61,8 +70,9 @@ void irq_handler_kms() * Gets the hw ready to enable irqs (all asics). * This function disables all interrupt sources on the GPU. */ -void radeon_irq_preinstall_kms(struct radeon_device *rdev) +void radeon_driver_irq_preinstall_kms(struct drm_device *dev) { + struct radeon_device *rdev = dev->dev_private; unsigned long irqflags; unsigned i; @@ -91,17 +101,45 @@ void radeon_irq_preinstall_kms(struct radeon_device *rdev) * Handles stuff to be done after enabling irqs (all asics). * Returns 0 on success. */ - -int radeon_driver_irq_postinstall_kms(struct radeon_device *rdev) +int radeon_driver_irq_postinstall_kms(struct drm_device *dev) { -// struct radeon_device *rdev = dev->dev_private; - -// dev->max_vblank_count = 0x001fffff; - - radeon_irq_set(rdev); - return 0; + dev->max_vblank_count = 0x001fffff; + return 0; } +/** + * radeon_driver_irq_uninstall_kms - drm irq uninstall callback + * + * @dev: drm dev pointer + * + * This function disables all interrupt sources on the GPU (all asics). + */ +void radeon_driver_irq_uninstall_kms(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + unsigned long irqflags; + unsigned i; + + if (rdev == NULL) { + return; + } + spin_lock_irqsave(&rdev->irq.lock, irqflags); + /* Disable *all* interrupts */ + for (i = 0; i < RADEON_NUM_RINGS; i++) + atomic_set(&rdev->irq.ring_int[i], 0); + for (i = 0; i < RADEON_MAX_HPD_PINS; i++) + rdev->irq.hpd[i] = false; + for (i = 0; i < RADEON_MAX_CRTCS; i++) { + rdev->irq.crtc_vblank_int[i] = false; + atomic_set(&rdev->irq.pflip[i], 0); + rdev->irq.afmt[i] = false; + } + radeon_irq_set(rdev); + spin_unlock_irqrestore(&rdev->irq.lock, irqflags); +} + + + /** * radeon_irq_kms_init - init driver interrupt info * @@ -117,44 +155,16 @@ int radeon_irq_kms_init(struct radeon_device *rdev) ENTER(); -// INIT_WORK(&rdev->hotplug_work, radeon_hotplug_work_func); -// INIT_WORK(&rdev->audio_work, r600_audio_update_hdmi); spin_lock_init(&rdev->irq.lock); -// r = drm_vblank_init(rdev->ddev, rdev->num_crtc); -// if (r) { -// return r; -// } /* enable msi */ rdev->msi_enabled = 0; -// if (radeon_msi_ok(rdev)) { -// int ret = pci_enable_msi(rdev->pdev); -// if (!ret) { -// rdev->msi_enabled = 1; -// dev_info(rdev->dev, "radeon: using MSI.\n"); -// } -// } rdev->irq.installed = true; - main_device = rdev; - - radeon_irq_preinstall_kms(rdev); - - if (irq_override) - irq_line = irq_override; - else - irq_line = rdev->pdev->irq; - - dbgprintf("%s install irq %d\n", __FUNCTION__, irq_line); - - AttachIntHandler(irq_line, irq_handler_kms, 2); - -// r = drm_irq_install(rdev->ddev); - - r = radeon_driver_irq_postinstall_kms(rdev); + r = drm_irq_install(rdev->ddev); if (r) { rdev->irq.installed = false; - LEAVE(); + FAIL(); return r; } DRM_INFO("radeon: irq initialized.\n"); @@ -228,4 +238,99 @@ void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring) } } +/** + * radeon_irq_kms_enable_hpd - enable hotplug detect interrupt + * + * @rdev: radeon device pointer + * @hpd_mask: mask of hpd pins you want to enable. + * + * Enables the hotplug detect interrupt for a specific hpd pin (all asics). + */ +void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask) +{ + unsigned long irqflags; + int i; + spin_lock_irqsave(&rdev->irq.lock, irqflags); + for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) + rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i)); + radeon_irq_set(rdev); + spin_unlock_irqrestore(&rdev->irq.lock, irqflags); +} + +/** + * radeon_irq_kms_disable_hpd - disable hotplug detect interrupt + * + * @rdev: radeon device pointer + * @hpd_mask: mask of hpd pins you want to disable. + * + * Disables the hotplug detect interrupt for a specific hpd pin (all asics). + */ +void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask) +{ + unsigned long irqflags; + int i; + + spin_lock_irqsave(&rdev->irq.lock, irqflags); + for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) + rdev->irq.hpd[i] &= !(hpd_mask & (1 << i)); + radeon_irq_set(rdev); + spin_unlock_irqrestore(&rdev->irq.lock, irqflags); +} + + +static struct drm_driver drm_driver = { + .irq_preinstall = radeon_driver_irq_preinstall_kms, + .irq_postinstall = radeon_driver_irq_postinstall_kms, + .irq_handler = radeon_driver_irq_handler_kms +}; + +static struct drm_driver *driver = &drm_driver; + +int drm_irq_install(struct drm_device *dev) +{ + unsigned long sh_flags = 0; + int irq_line; + int ret = 0; + + char *irqname; + + mutex_lock(&dev->struct_mutex); + + /* Driver must have been initialized */ + if (!dev->dev_private) { + mutex_unlock(&dev->struct_mutex); + return -EINVAL; + } + + if (dev->irq_enabled) { + mutex_unlock(&dev->struct_mutex); + return -EBUSY; + } + dev->irq_enabled = 1; + mutex_unlock(&dev->struct_mutex); + + irq_line = drm_dev_to_irq(dev); + + DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev)); + + /* Before installing handler */ + if (driver->irq_preinstall) + driver->irq_preinstall(dev); + + ret = AttachIntHandler(irq_line, driver->irq_handler, (u32)dev); + + /* After installing handler */ + if (driver->irq_postinstall) + ret = driver->irq_postinstall(dev); + + if (ret < 0) { + DRM_ERROR(__FUNCTION__); + } + + u16_t cmd = PciRead16(dev->pdev->busnr, dev->pdev->devfn, 4); + cmd&= ~(1<<10); + PciWrite16(dev->pdev->busnr, dev->pdev->devfn, 4, cmd); + + return ret; +} diff --git a/drivers/video/drm/radeon/radeon_legacy_crtc.c b/drivers/video/drm/radeon/radeon_legacy_crtc.c index b7498116ea..0e71f5fb18 100644 --- a/drivers/video/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/video/drm/radeon/radeon_legacy_crtc.c @@ -295,6 +295,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; + uint32_t crtc_ext_cntl = 0; uint32_t mask; if (radeon_crtc->crtc_id) @@ -307,6 +308,16 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) RADEON_CRTC_VSYNC_DIS | RADEON_CRTC_HSYNC_DIS); + /* + * On all dual CRTC GPUs this bit controls the CRTC of the primary DAC. + * Therefore it is set in the DAC DMPS function. + * This is different for GPU's with a single CRTC but a primary and a + * TV DAC: here it controls the single CRTC no matter where it is + * routed. Therefore we set it here. + */ + if (rdev->flags & RADEON_SINGLE_CRTC) + crtc_ext_cntl = RADEON_CRTC_CRT_ON; + switch (mode) { case DRM_MODE_DPMS_ON: radeon_crtc->enabled = true; @@ -317,7 +328,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) else { WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN | RADEON_CRTC_DISP_REQ_EN_B)); - WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask); + WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl)); } drm_vblank_post_modeset(dev, radeon_crtc->crtc_id); radeon_crtc_load_lut(crtc); @@ -331,7 +342,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) else { WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN | RADEON_CRTC_DISP_REQ_EN_B)); - WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask); + WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl)); } radeon_crtc->enabled = false; /* adjust pm to dpms changes AFTER disabling crtcs */ diff --git a/drivers/video/drm/radeon/radeon_legacy_encoders.c b/drivers/video/drm/radeon/radeon_legacy_encoders.c index 6e4035e67b..cb6a4b9bfe 100644 --- a/drivers/video/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/video/drm/radeon/radeon_legacy_encoders.c @@ -537,6 +537,8 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode break; } + /* handled in radeon_crtc_dpms() */ + if (!(rdev->flags & RADEON_SINGLE_CRTC)) WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); WREG32(RADEON_DAC_CNTL, dac_cntl); WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); @@ -662,6 +664,8 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc if (ASIC_IS_R300(rdev)) tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); + else if (ASIC_IS_RV100(rdev)) + tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT); else tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); @@ -671,6 +675,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; WREG32(RADEON_DAC_CNTL, tmp); + tmp = dac_macro_cntl; tmp &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | RADEON_DAC_PDWN_B); @@ -1092,7 +1097,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode) } else { if (is_tv) WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); - else + /* handled in radeon_crtc_dpms() */ + else if (!(rdev->flags & RADEON_SINGLE_CRTC)) WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); } @@ -1416,13 +1422,101 @@ static bool radeon_legacy_tv_detect(struct drm_encoder *encoder, return found; } +static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder, + struct drm_connector *connector) +{ + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; + uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl; + uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c; + uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f; + uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp; + uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid; + bool found = false; + int i; + + /* save the regs we need */ + gpio_monid = RREG32(RADEON_GPIO_MONID); + fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); + disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); + crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A); + disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B); + disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C); + disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D); + disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E); + disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F); + crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP); + crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP); + crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID); + crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID); + + tmp = RREG32(RADEON_GPIO_MONID); + tmp &= ~RADEON_GPIO_A_0; + WREG32(RADEON_GPIO_MONID, tmp); + + WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON | + RADEON_FP2_PANEL_FORMAT | + R200_FP2_SOURCE_SEL_TRANS_UNIT | + RADEON_FP2_DVO_EN | + R200_FP2_DVO_RATE_SEL_SDR)); + + WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX | + RADEON_DISP_TRANS_MATRIX_GRAPHICS)); + + WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN | + RADEON_CRTC2_DISP_REQ_EN_B)); + + WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); + + WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); + WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); + WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); + WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); + + for (i = 0; i < 200; i++) { + tmp = RREG32(RADEON_GPIO_MONID); + if (tmp & RADEON_GPIO_Y_0) + found = true; + + if (found) + break; + + msleep(1); + } + + /* restore the regs we used */ + WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e); + WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f); + WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp); + WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp); + WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid); + WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid); + WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); + WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); + WREG32(RADEON_GPIO_MONID, gpio_monid); + + return found; +} + static enum drm_connector_status radeon_legacy_tv_dac_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_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp; + uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl; + uint32_t gpiopad_a = 0, pixclks_cntl, tmp; + uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0; 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; @@ -1459,12 +1553,27 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder return connector_status_disconnected; } + /* R200 uses an external DAC for secondary DAC */ + if (rdev->family == CHIP_R200) { + if (radeon_legacy_ext_dac_detect(encoder, connector)) + found = connector_status_connected; + return found; + } + /* save the regs we need */ pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); - gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0; - disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0; - disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG); + + if (rdev->flags & RADEON_SINGLE_CRTC) { + crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); + } else { + if (ASIC_IS_R300(rdev)) { + gpiopad_a = RREG32(RADEON_GPIOPAD_A); + disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); + } else { + disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); + } crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + } tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL); dac_cntl2 = RREG32(RADEON_DAC_CNTL2); @@ -1473,16 +1582,17 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder | RADEON_PIX2CLK_DAC_ALWAYS_ONb); WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); - if (ASIC_IS_R300(rdev)) - WREG32_P(RADEON_GPIOPAD_A, 1, ~1); - + if (rdev->flags & RADEON_SINGLE_CRTC) { + tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; + WREG32(RADEON_CRTC_EXT_CNTL, tmp); + } else { tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; tmp |= RADEON_CRTC2_CRT2_ON | (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); - WREG32(RADEON_CRTC2_GEN_CNTL, tmp); if (ASIC_IS_R300(rdev)) { + WREG32_P(RADEON_GPIOPAD_A, 1, ~1); tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); @@ -1490,6 +1600,7 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; WREG32(RADEON_DISP_HW_DEBUG, tmp); } + } tmp = RADEON_TV_DAC_NBLANK | RADEON_TV_DAC_NHOLD | @@ -1530,14 +1641,19 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder WREG32(RADEON_DAC_CNTL2, dac_cntl2); WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl); WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); - WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); + if (rdev->flags & RADEON_SINGLE_CRTC) { + WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); + } else { + WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); if (ASIC_IS_R300(rdev)) { WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); } else { WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); } + } + WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl); return found; diff --git a/drivers/video/drm/radeon/radeon_sa.c b/drivers/video/drm/radeon/radeon_sa.c index f18adbe20f..f885236461 100644 --- a/drivers/video/drm/radeon/radeon_sa.c +++ b/drivers/video/drm/radeon/radeon_sa.c @@ -64,7 +64,7 @@ int radeon_sa_bo_manager_init(struct radeon_device *rdev, } r = radeon_bo_create(rdev, size, RADEON_GPU_PAGE_SIZE, true, - RADEON_GEM_DOMAIN_CPU, NULL, &sa_manager->bo); + domain, NULL, &sa_manager->bo); if (r) { dev_err(rdev->dev, "(%d) failed to allocate bo for manager\n", r); return r; diff --git a/drivers/video/drm/radeon/rdisplay.c b/drivers/video/drm/radeon/rdisplay.c index b98aee5d4e..eb1f3abd01 100644 --- a/drivers/video/drm/radeon/rdisplay.c +++ b/drivers/video/drm/radeon/rdisplay.c @@ -5,6 +5,7 @@ #include "radeon_drm.h" #include "radeon.h" #include "radeon_object.h" +#include "bitmap.h" #include "display.h" #include "r100d.h" @@ -256,6 +257,8 @@ bool init_display(struct radeon_device *rdev, videomode_t *usermode) }; safe_sti(ifl); + init_bitmaps(); + LEAVE(); return retval; diff --git a/drivers/video/drm/radeon/rdisplay_kms.c b/drivers/video/drm/radeon/rdisplay_kms.c index 199e384f20..e350cdd89f 100644 --- a/drivers/video/drm/radeon/rdisplay_kms.c +++ b/drivers/video/drm/radeon/rdisplay_kms.c @@ -5,8 +5,10 @@ #include "radeon_drm.h" #include "radeon.h" #include "radeon_object.h" -#include "display.h" #include "drm_fb_helper.h" +#include "hmm.h" +#include "bitmap.h" +#include "display.h" struct radeon_fbdev { struct drm_fb_helper helper; @@ -528,6 +530,8 @@ bool init_display_kms(struct radeon_device *rdev, videomode_t *usermode) }; safe_sti(ifl); + init_bitmaps(); + LEAVE(); return retval; @@ -673,3 +677,212 @@ int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, } +typedef struct +{ + int left; + int top; + int right; + int bottom; +}rect_t; + +extern struct hmm bm_mm; +struct drm_device *main_drm_device; + +void FASTCALL GetWindowRect(rect_t *rc)__asm__("GetWindowRect"); + +#define CURRENT_TASK (0x80003000) + +static u32_t get_display_map() +{ + u32_t addr; + + addr = (u32_t)rdisplay; + addr+= sizeof(display_t); /* shoot me */ + return *(u32_t*)addr; +} + +#include "clip.inc" +#include "r100d.h" + +# define PACKET3_BITBLT 0x92 + + +int srv_blit_bitmap(u32 hbitmap, int dst_x, int dst_y, + int src_x, int src_y, u32 w, u32 h) +{ + struct context *context; + + bitmap_t *bitmap; + rect_t winrc; + clip_t dst_clip; + clip_t src_clip; + u32_t width; + u32_t height; + + u32_t br13, cmd, slot_mask, *b; + u32_t offset; + u8 slot; + int n=0; + int ret; + + if(unlikely(hbitmap==0)) + return -1; + + bitmap = (bitmap_t*)hmm_get_data(&bm_mm, hbitmap); + + if(unlikely(bitmap==NULL)) + return -1; + + context = get_context(main_drm_device); + if(unlikely(context == NULL)) + return -1; + + GetWindowRect(&winrc); + { + static warn_count; + + if(warn_count < 1) + { + printf("left %d top %d right %d bottom %d\n", + winrc.left, winrc.top, winrc.right, winrc.bottom); + printf("bitmap width %d height %d\n", w, h); + warn_count++; + }; + }; + + + dst_clip.xmin = 0; + dst_clip.ymin = 0; + dst_clip.xmax = winrc.right-winrc.left; + dst_clip.ymax = winrc.bottom -winrc.top; + + src_clip.xmin = 0; + src_clip.ymin = 0; + src_clip.xmax = bitmap->width - 1; + src_clip.ymax = bitmap->height - 1; + + width = w; + height = h; + + if( blit_clip(&dst_clip, &dst_x, &dst_y, + &src_clip, &src_x, &src_y, + &width, &height) ) + return 0; + + dst_x+= winrc.left; + dst_y+= winrc.top; + + slot = *((u8*)CURRENT_TASK); + + slot_mask = (u32_t)slot<<24; + + { +#if 1 +#else + u8* src_offset; + u8* dst_offset; + u32 ifl; + + src_offset = (u8*)(src_y*bitmap->pitch + src_x*4); + src_offset += (u32)bitmap->uaddr; + + dst_offset = (u8*)(dst_y*rdisplay->width + dst_x); + dst_offset+= get_display_map(); + + u32_t tmp_h = height; + + ifl = safe_cli(); + while( tmp_h--) + { + u32_t tmp_w = width; + + u8* tmp_src = src_offset; + u8* tmp_dst = dst_offset; + + src_offset+= bitmap->pitch; + dst_offset+= rdisplay->width; + + while( tmp_w--) + { + *(tmp_src+3) = (*tmp_dst==slot)?0xFF:0x00; + tmp_src+=4; + tmp_dst++; + }; + }; + safe_sti(ifl); +#endif + } + + { + static warn_count; + + if(warn_count < 1) + { + printf("blit width %d height %d\n", + width, height); + warn_count++; + }; + }; + + +// if((context->cmd_buffer & 0xFC0)==0xFC0) +// context->cmd_buffer&= 0xFFFFF000; + +// b = (u32_t*)ALIGN(context->cmd_buffer,64); + +// offset = context->cmd_offset + ((u32_t)b & 0xFFF); + + +// context->cmd_buffer+= n*4; + + struct radeon_device *rdev = main_drm_device->dev_private; + struct radeon_ib *ib = &context->ib; + + ib->ptr[0] = PACKET3(PACKET3_BITBLT, 8); + ib->ptr[1] = RADEON_GMC_SRC_PITCH_OFFSET_CNTL | + RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_SRC_CLIPPING | + RADEON_GMC_DST_CLIPPING | + RADEON_GMC_BRUSH_NONE | + (RADEON_COLOR_FORMAT_ARGB8888 << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP3_S | + RADEON_DP_SRC_SOURCE_MEMORY | + RADEON_GMC_CLR_CMP_CNTL_DIS | + RADEON_GMC_WR_MSK_DIS; + + ib->ptr[2] = ((bitmap->pitch/64) << 22) | (bitmap->gaddr >> 10); + ib->ptr[3] = ((rdisplay->pitch/64) << 22) | (rdev->mc.vram_start >> 10); + ib->ptr[4] = (0x1fff) | (0x1fff << 16); + ib->ptr[5] = 0; + ib->ptr[6] = (0x1fff) | (0x1fff << 16); + + ib->ptr[7] = (src_x << 16) | src_y; + ib->ptr[8] = (dst_x << 16) | dst_y; + ib->ptr[9] = (width << 16) | height; + + ib->ptr[10] = PACKET2(0); + ib->ptr[11] = PACKET2(0); + ib->ptr[12] = PACKET2(0); + ib->ptr[13] = PACKET2(0); + ib->ptr[14] = PACKET2(0); + ib->ptr[15] = PACKET2(0); + + ib->length_dw = 16; + + ret = radeon_ib_schedule(rdev, ib, NULL); + if (ret) { + DRM_ERROR("radeon: failed to schedule ib (%d).\n", ret); + goto fail; + } + + ret = radeon_fence_wait(ib->fence, false); + if (ret) { + DRM_ERROR("radeon: fence wait failed (%d).\n", ret); + goto fail; + } + +fail: + return ret; +}; + diff --git a/drivers/video/drm/radeon/rs400.c b/drivers/video/drm/radeon/rs400.c index f1fe7050e2..509f03116b 100644 --- a/drivers/video/drm/radeon/rs400.c +++ b/drivers/video/drm/radeon/rs400.c @@ -410,6 +410,12 @@ static int rs400_startup(struct radeon_device *rdev) if (r) return r; + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + /* Enable IRQ */ r100_irq_set(rdev); rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); diff --git a/drivers/video/drm/radeon/rv515.c b/drivers/video/drm/radeon/rv515.c index df21e04009..7f67d554cc 100644 --- a/drivers/video/drm/radeon/rv515.c +++ b/drivers/video/drm/radeon/rv515.c @@ -379,6 +379,12 @@ static int rv515_startup(struct radeon_device *rdev) if (r) return r; + r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); + if (r) { + dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); + return r; + } + /* Enable IRQ */ rs600_irq_set(rdev); rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); diff --git a/drivers/video/drm/radeon/si.c b/drivers/video/drm/radeon/si.c index e544da9453..49ef880649 100644 --- a/drivers/video/drm/radeon/si.c +++ b/drivers/video/drm/radeon/si.c @@ -2007,7 +2007,7 @@ static int si_cp_resume(struct radeon_device *rdev) ring->wptr = 0; WREG32(CP_RB0_WPTR, ring->wptr); - /* set the wb address wether it's enabled or not */ + /* set the wb address whether it's enabled or not */ WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC); WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF); @@ -2040,7 +2040,7 @@ static int si_cp_resume(struct radeon_device *rdev) ring->wptr = 0; WREG32(CP_RB1_WPTR, ring->wptr); - /* set the wb address wether it's enabled or not */ + /* set the wb address whether it's enabled or not */ WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC); WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF); @@ -2066,7 +2066,7 @@ static int si_cp_resume(struct radeon_device *rdev) ring->wptr = 0; WREG32(CP_RB2_WPTR, ring->wptr); - /* set the wb address wether it's enabled or not */ + /* set the wb address whether it's enabled or not */ WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC); WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF); @@ -3841,11 +3841,11 @@ static int si_startup(struct radeon_device *rdev) if (r) return r; -// r = radeon_ib_pool_init(rdev); -// if (r) { -// dev_err(rdev->dev, "IB initialization failed (%d).\n", r); -// return r; -// } + r = radeon_ib_pool_init(rdev); + if (r) { + dev_err(rdev->dev, "IB initialization failed (%d).\n", r); + return r; + } // r = radeon_vm_manager_init(rdev); // if (r) { @@ -3857,6 +3857,8 @@ static int si_startup(struct radeon_device *rdev) } + + /* Plan is to move initialization in that function and use * helper function so that radeon_device_init pretty much * do nothing more than calling asic specific function. This