diff --git a/[refs] b/[refs] index 16abd0738bc1..7c662a951d87 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a3b1097c037ae992510fe8f1e933072280ef19b0 +refs/heads/master: bc752862170c135d6c09fb22d79eeb451023568e diff --git a/trunk/Documentation/DocBook/drm.tmpl b/trunk/Documentation/DocBook/drm.tmpl index a6428ddfcfc2..b26de523ab70 100644 --- a/trunk/Documentation/DocBook/drm.tmpl +++ b/trunk/Documentation/DocBook/drm.tmpl @@ -1160,12 +1160,6 @@ int max_width, max_height; without waiting for rendering or page flip to complete and must block any new rendering to the frame buffer until the page flip completes. - - If a page flip can be successfully scheduled the driver must set the - drm_crtc-<fb field to the new framebuffer pointed to - by fb. This is important so that the reference counting - on framebuffers stays balanced. - If a page flip is already pending, the page_flip operation must return @@ -2149,7 +2143,6 @@ void intel_crt_init(struct drm_device *dev) fbdev Helper Functions Reference !Pdrivers/gpu/drm/drm_fb_helper.c fbdev helpers !Edrivers/gpu/drm/drm_fb_helper.c -!Iinclude/drm/drm_fb_helper.h Display Port Helper Functions Reference diff --git a/trunk/Documentation/devicetree/bindings/drm/tilcdc/panel.txt b/trunk/Documentation/devicetree/bindings/drm/tilcdc/panel.txt deleted file mode 100644 index 9301c330d1a6..000000000000 --- a/trunk/Documentation/devicetree/bindings/drm/tilcdc/panel.txt +++ /dev/null @@ -1,59 +0,0 @@ -Device-Tree bindings for tilcdc DRM generic panel output driver - -Required properties: - - compatible: value should be "ti,tilcdc,panel". - - panel-info: configuration info to configure LCDC correctly for the panel - - ac-bias: AC Bias Pin Frequency - - ac-bias-intrpt: AC Bias Pin Transitions per Interrupt - - dma-burst-sz: DMA burst size - - bpp: Bits per pixel - - fdd: FIFO DMA Request Delay - - sync-edge: Horizontal and Vertical Sync Edge: 0=rising 1=falling - - sync-ctrl: Horizontal and Vertical Sync: Control: 0=ignore - - raster-order: Raster Data Order Select: 1=Most-to-least 0=Least-to-most - - fifo-th: DMA FIFO threshold - - display-timings: typical videomode of lcd panel. Multiple video modes - can be listed if the panel supports multiple timings, but the 'native-mode' - should be the preferred/default resolution. Refer to - Documentation/devicetree/bindings/video/display-timing.txt for display - timing binding details. - -Recommended properties: - - pinctrl-names, pinctrl-0: the pincontrol settings to configure - muxing properly for pins that connect to TFP410 device - -Example: - - /* Settings for CDTech_S035Q01 / LCD3 cape: */ - lcd3 { - compatible = "ti,tilcdc,panel"; - pinctrl-names = "default"; - pinctrl-0 = <&bone_lcd3_cape_lcd_pins>; - panel-info { - ac-bias = <255>; - ac-bias-intrpt = <0>; - dma-burst-sz = <16>; - bpp = <16>; - fdd = <0x80>; - sync-edge = <0>; - sync-ctrl = <1>; - raster-order = <0>; - fifo-th = <0>; - }; - display-timings { - native-mode = <&timing0>; - timing0: 320x240 { - hactive = <320>; - vactive = <240>; - hback-porch = <21>; - hfront-porch = <58>; - hsync-len = <47>; - vback-porch = <11>; - vfront-porch = <23>; - vsync-len = <2>; - clock-frequency = <8000000>; - hsync-active = <0>; - vsync-active = <0>; - }; - }; - }; diff --git a/trunk/Documentation/devicetree/bindings/drm/tilcdc/slave.txt b/trunk/Documentation/devicetree/bindings/drm/tilcdc/slave.txt deleted file mode 100644 index 3d2c52460dca..000000000000 --- a/trunk/Documentation/devicetree/bindings/drm/tilcdc/slave.txt +++ /dev/null @@ -1,18 +0,0 @@ -Device-Tree bindings for tilcdc DRM encoder slave output driver - -Required properties: - - compatible: value should be "ti,tilcdc,slave". - - i2c: the phandle for the i2c device the encoder slave is connected to - -Recommended properties: - - pinctrl-names, pinctrl-0: the pincontrol settings to configure - muxing properly for pins that connect to TFP410 device - -Example: - - hdmi { - compatible = "ti,tilcdc,slave"; - i2c = <&i2c0>; - pinctrl-names = "default"; - pinctrl-0 = <&nxp_hdmi_bonelt_pins>; - }; diff --git a/trunk/Documentation/devicetree/bindings/drm/tilcdc/tfp410.txt b/trunk/Documentation/devicetree/bindings/drm/tilcdc/tfp410.txt deleted file mode 100644 index a58ae7756fc6..000000000000 --- a/trunk/Documentation/devicetree/bindings/drm/tilcdc/tfp410.txt +++ /dev/null @@ -1,21 +0,0 @@ -Device-Tree bindings for tilcdc DRM TFP410 output driver - -Required properties: - - compatible: value should be "ti,tilcdc,tfp410". - - i2c: the phandle for the i2c device to use for DDC - -Recommended properties: - - pinctrl-names, pinctrl-0: the pincontrol settings to configure - muxing properly for pins that connect to TFP410 device - - powerdn-gpio: the powerdown GPIO, pulled low to power down the - TFP410 device (for DPMS_OFF) - -Example: - - dvicape { - compatible = "ti,tilcdc,tfp410"; - i2c = <&i2c2>; - pinctrl-names = "default"; - pinctrl-0 = <&bone_dvi_cape_dvi_00A1_pins>; - powerdn-gpio = <&gpio2 31 0>; - }; diff --git a/trunk/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt b/trunk/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt deleted file mode 100644 index e5f130159ae1..000000000000 --- a/trunk/Documentation/devicetree/bindings/drm/tilcdc/tilcdc.txt +++ /dev/null @@ -1,21 +0,0 @@ -Device-Tree bindings for tilcdc DRM driver - -Required properties: - - compatible: value should be "ti,am33xx-tilcdc". - - interrupts: the interrupt number - - reg: base address and size of the LCDC device - -Recommended properties: - - interrupt-parent: the phandle for the interrupt controller that - services interrupts for this device. - - ti,hwmods: Name of the hwmod associated to the LCDC - -Example: - - fb: fb@4830e000 { - compatible = "ti,am33xx-tilcdc"; - reg = <0x4830e000 0x1000>; - interrupt-parent = <&intc>; - interrupts = <36>; - ti,hwmods = "lcdc"; - }; diff --git a/trunk/Documentation/thermal/nouveau_thermal b/trunk/Documentation/thermal/nouveau_thermal deleted file mode 100644 index efceb7828f54..000000000000 --- a/trunk/Documentation/thermal/nouveau_thermal +++ /dev/null @@ -1,81 +0,0 @@ -Kernel driver nouveau -=================== - -Supported chips: -* NV43+ - -Authors: Martin Peres (mupuf) - -Description ---------- - -This driver allows to read the GPU core temperature, drive the GPU fan and -set temperature alarms. - -Currently, due to the absence of in-kernel API to access HWMON drivers, Nouveau -cannot access any of the i2c external monitoring chips it may find. If you -have one of those, temperature and/or fan management through Nouveau's HWMON -interface is likely not to work. This document may then not cover your situation -entirely. - -Temperature management --------------------- - -Temperature is exposed under as a read-only HWMON attribute temp1_input. - -In order to protect the GPU from overheating, Nouveau supports 4 configurable -temperature thresholds: - - * Fan_boost: Fan speed is set to 100% when reaching this temperature; - * Downclock: The GPU will be downclocked to reduce its power dissipation; - * Critical: The GPU is put on hold to further lower power dissipation; - * Shutdown: Shut the computer down to protect your GPU. - -WARNING: Some of these thresholds may not be used by Nouveau depending -on your chipset. - -The default value for these thresholds comes from the GPU's vbios. These -thresholds can be configured thanks to the following HWMON attributes: - - * Fan_boost: temp1_auto_point1_temp and temp1_auto_point1_temp_hyst; - * Downclock: temp1_max and temp1_max_hyst; - * Critical: temp1_crit and temp1_crit_hyst; - * Shutdown: temp1_emergency and temp1_emergency_hyst. - -NOTE: Remember that the values are stored as milli degrees Celcius. Don't forget -to multiply! - -Fan management ------------- - -Not all cards have a drivable fan. If you do, then the following HWMON -attributes should be available: - - * pwm1_enable: Current fan management mode (NONE, MANUAL or AUTO); - * pwm1: Current PWM value (power percentage); - * pwm1_min: The minimum PWM speed allowed; - * pwm1_max: The maximum PWM speed allowed (bypassed when hitting Fan_boost); - -You may also have the following attribute: - - * fan1_input: Speed in RPM of your fan. - -Your fan can be driven in different modes: - - * 0: The fan is left untouched; - * 1: The fan can be driven in manual (use pwm1 to change the speed); - * 2; The fan is driven automatically depending on the temperature. - -NOTE: Be sure to use the manual mode if you want to drive the fan speed manually - -NOTE2: Not all fan management modes may be supported on all chipsets. We are -working on it. - -Bug reports ---------- - -Thermal management on Nouveau is new and may not work on all cards. If you have -inquiries, please ping mupuf on IRC (#nouveau, freenode). - -Bug reports should be filled on Freedesktop's bug tracker. Please follow -http://nouveau.freedesktop.org/wiki/Bugs diff --git a/trunk/drivers/gpu/Makefile b/trunk/drivers/gpu/Makefile index 30879df3daea..cc9277885dd0 100644 --- a/trunk/drivers/gpu/Makefile +++ b/trunk/drivers/gpu/Makefile @@ -1 +1 @@ -obj-y += drm/ vga/ +obj-y += drm/ vga/ stub/ diff --git a/trunk/drivers/gpu/drm/Kconfig b/trunk/drivers/gpu/drm/Kconfig index f8dae851130c..ed9e3af17b31 100644 --- a/trunk/drivers/gpu/drm/Kconfig +++ b/trunk/drivers/gpu/drm/Kconfig @@ -215,7 +215,3 @@ source "drivers/gpu/drm/cirrus/Kconfig" source "drivers/gpu/drm/shmobile/Kconfig" source "drivers/gpu/drm/tegra/Kconfig" - -source "drivers/gpu/drm/omapdrm/Kconfig" - -source "drivers/gpu/drm/tilcdc/Kconfig" diff --git a/trunk/drivers/gpu/drm/Makefile b/trunk/drivers/gpu/drm/Makefile index 0d59b24f8d23..6f58c81cfcbc 100644 --- a/trunk/drivers/gpu/drm/Makefile +++ b/trunk/drivers/gpu/drm/Makefile @@ -50,6 +50,4 @@ obj-$(CONFIG_DRM_UDL) += udl/ obj-$(CONFIG_DRM_AST) += ast/ obj-$(CONFIG_DRM_SHMOBILE) +=shmobile/ obj-$(CONFIG_DRM_TEGRA) += tegra/ -obj-$(CONFIG_DRM_OMAP) += omapdrm/ -obj-$(CONFIG_DRM_TILCDC) += tilcdc/ obj-y += i2c/ diff --git a/trunk/drivers/gpu/drm/ast/ast_fb.c b/trunk/drivers/gpu/drm/ast/ast_fb.c index 34931fe7d2c5..3e6584b940dc 100644 --- a/trunk/drivers/gpu/drm/ast/ast_fb.c +++ b/trunk/drivers/gpu/drm/ast/ast_fb.c @@ -40,7 +40,6 @@ #include #include #include -#include #include "ast_drv.h" static void ast_dirty_update(struct ast_fbdev *afbdev, @@ -146,10 +145,9 @@ static int astfb_create_object(struct ast_fbdev *afbdev, return ret; } -static int astfb_create(struct drm_fb_helper *helper, +static int astfb_create(struct ast_fbdev *afbdev, struct drm_fb_helper_surface_size *sizes) { - struct ast_fbdev *afbdev = (struct ast_fbdev *)helper; struct drm_device *dev = afbdev->helper.dev; struct drm_mode_fb_cmd2 mode_cmd; struct drm_framebuffer *fb; @@ -250,10 +248,26 @@ static void ast_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, *blue = ast_crtc->lut_b[regno] << 8; } +static int ast_find_or_create_single(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + struct ast_fbdev *afbdev = (struct ast_fbdev *)helper; + int new_fb = 0; + int ret; + + if (!helper->fb) { + ret = astfb_create(afbdev, sizes); + if (ret) + return ret; + new_fb = 1; + } + return new_fb; +} + static struct drm_fb_helper_funcs ast_fb_helper_funcs = { .gamma_set = ast_fb_gamma_set, .gamma_get = ast_fb_gamma_get, - .fb_probe = astfb_create, + .fb_probe = ast_find_or_create_single, }; static void ast_fbdev_destroy(struct drm_device *dev, @@ -300,10 +314,6 @@ int ast_fbdev_init(struct drm_device *dev) } drm_fb_helper_single_add_all_connectors(&afbdev->helper); - - /* disable all the possible outputs/crtcs before entering KMS mode */ - drm_helper_disable_unused_functions(dev); - drm_fb_helper_initial_config(&afbdev->helper, 32); return 0; } diff --git a/trunk/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/trunk/drivers/gpu/drm/cirrus/cirrus_fbdev.c index e25afccaf85b..3daea0f638c3 100644 --- a/trunk/drivers/gpu/drm/cirrus/cirrus_fbdev.c +++ b/trunk/drivers/gpu/drm/cirrus/cirrus_fbdev.c @@ -11,7 +11,6 @@ #include #include #include -#include #include @@ -121,10 +120,9 @@ static int cirrusfb_create_object(struct cirrus_fbdev *afbdev, return ret; } -static int cirrusfb_create(struct drm_fb_helper *helper, +static int cirrusfb_create(struct cirrus_fbdev *gfbdev, struct drm_fb_helper_surface_size *sizes) { - struct cirrus_fbdev *gfbdev = (struct cirrus_fbdev *)helper; struct drm_device *dev = gfbdev->helper.dev; struct cirrus_device *cdev = gfbdev->helper.dev->dev_private; struct fb_info *info; @@ -221,6 +219,23 @@ static int cirrusfb_create(struct drm_fb_helper *helper, return ret; } +static int cirrus_fb_find_or_create_single(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size + *sizes) +{ + struct cirrus_fbdev *gfbdev = (struct cirrus_fbdev *)helper; + int new_fb = 0; + int ret; + + if (!helper->fb) { + ret = cirrusfb_create(gfbdev, sizes); + if (ret) + return ret; + new_fb = 1; + } + return new_fb; +} + static int cirrus_fbdev_destroy(struct drm_device *dev, struct cirrus_fbdev *gfbdev) { @@ -252,7 +267,7 @@ static int cirrus_fbdev_destroy(struct drm_device *dev, static struct drm_fb_helper_funcs cirrus_fb_helper_funcs = { .gamma_set = cirrus_crtc_fb_gamma_set, .gamma_get = cirrus_crtc_fb_gamma_get, - .fb_probe = cirrusfb_create, + .fb_probe = cirrus_fb_find_or_create_single, }; int cirrus_fbdev_init(struct cirrus_device *cdev) @@ -276,9 +291,6 @@ int cirrus_fbdev_init(struct cirrus_device *cdev) return ret; } drm_fb_helper_single_add_all_connectors(&gfbdev->helper); - - /* disable all the possible outputs/crtcs before entering KMS mode */ - drm_helper_disable_unused_functions(cdev->dev); drm_fb_helper_initial_config(&gfbdev->helper, bpp_sel); return 0; diff --git a/trunk/drivers/gpu/drm/drm_crtc.c b/trunk/drivers/gpu/drm/drm_crtc.c index 3bdf2a650d9c..826a5ca3595f 100644 --- a/trunk/drivers/gpu/drm/drm_crtc.c +++ b/trunk/drivers/gpu/drm/drm_crtc.c @@ -68,22 +68,8 @@ void drm_modeset_unlock_all(struct drm_device *dev) mutex_unlock(&dev->mode_config.mutex); } -EXPORT_SYMBOL(drm_modeset_unlock_all); - -/** - * drm_warn_on_modeset_not_all_locked - check that all modeset locks are locked - * @dev: device - */ -void drm_warn_on_modeset_not_all_locked(struct drm_device *dev) -{ - struct drm_crtc *crtc; - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) - WARN_ON(!mutex_is_locked(&crtc->mutex)); - - WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); -} -EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked); +EXPORT_SYMBOL(drm_modeset_unlock_all); /* Avoid boilerplate. I'm tired of typing. */ #define DRM_ENUM_NAME_FN(fnname, list) \ @@ -1996,9 +1982,9 @@ int drm_mode_setplane(struct drm_device *dev, void *data, plane_req->src_w, plane_req->src_h); if (!ret) { old_fb = plane->fb; + fb = NULL; plane->crtc = crtc; plane->fb = fb; - fb = NULL; } drm_modeset_unlock_all(dev); @@ -3792,13 +3778,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, /* Keep the old fb, don't unref it. */ old_fb = NULL; } else { - /* - * Warn if the driver hasn't properly updated the crtc->fb - * field to reflect that the new framebuffer is now used. - * Failing to do so will screw with the reference counting - * on framebuffers. - */ - WARN_ON(crtc->fb != fb); /* Unref only the old framebuffer. */ fb = NULL; } diff --git a/trunk/drivers/gpu/drm/drm_edid.c b/trunk/drivers/gpu/drm/drm_edid.c index 67aa0dd68250..51324256a657 100644 --- a/trunk/drivers/gpu/drm/drm_edid.c +++ b/trunk/drivers/gpu/drm/drm_edid.c @@ -354,14 +354,10 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter) break; } } - - if (i == 4 && print_bad_edid) { + if (i == 4) dev_warn(connector->dev->dev, "%s: Ignoring invalid EDID block %d.\n", drm_get_connector_name(connector), j); - - connector->bad_edid_counter++; - } } if (valid_extensions != block[0x7e]) { @@ -2054,8 +2050,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) num_modes += add_cvt_modes(connector, edid); num_modes += add_standard_modes(connector, edid); num_modes += add_established_modes(connector, edid); - if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF) - num_modes += add_inferred_modes(connector, edid); + num_modes += add_inferred_modes(connector, edid); num_modes += add_cea_modes(connector, edid); if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) diff --git a/trunk/drivers/gpu/drm/drm_encoder_slave.c b/trunk/drivers/gpu/drm/drm_encoder_slave.c index 48c52f7df4e6..63e733408b6d 100644 --- a/trunk/drivers/gpu/drm/drm_encoder_slave.c +++ b/trunk/drivers/gpu/drm/drm_encoder_slave.c @@ -123,66 +123,3 @@ void drm_i2c_encoder_destroy(struct drm_encoder *drm_encoder) module_put(module); } EXPORT_SYMBOL(drm_i2c_encoder_destroy); - -/* - * Wrapper fxns which can be plugged in to drm_encoder_helper_funcs: - */ - -static inline struct drm_encoder_slave_funcs * -get_slave_funcs(struct drm_encoder *enc) -{ - return to_encoder_slave(enc)->slave_funcs; -} - -void drm_i2c_encoder_dpms(struct drm_encoder *encoder, int mode) -{ - get_slave_funcs(encoder)->dpms(encoder, mode); -} -EXPORT_SYMBOL(drm_i2c_encoder_dpms); - -bool drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return get_slave_funcs(encoder)->mode_fixup(encoder, mode, adjusted_mode); -} -EXPORT_SYMBOL(drm_i2c_encoder_mode_fixup); - -void drm_i2c_encoder_prepare(struct drm_encoder *encoder) -{ - drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); -} -EXPORT_SYMBOL(drm_i2c_encoder_prepare); - -void drm_i2c_encoder_commit(struct drm_encoder *encoder) -{ - drm_i2c_encoder_dpms(encoder, DRM_MODE_DPMS_ON); -} -EXPORT_SYMBOL(drm_i2c_encoder_commit); - -void drm_i2c_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - get_slave_funcs(encoder)->mode_set(encoder, mode, adjusted_mode); -} -EXPORT_SYMBOL(drm_i2c_encoder_mode_set); - -enum drm_connector_status drm_i2c_encoder_detect(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - return get_slave_funcs(encoder)->detect(encoder, connector); -} -EXPORT_SYMBOL(drm_i2c_encoder_detect); - -void drm_i2c_encoder_save(struct drm_encoder *encoder) -{ - get_slave_funcs(encoder)->save(encoder); -} -EXPORT_SYMBOL(drm_i2c_encoder_save); - -void drm_i2c_encoder_restore(struct drm_encoder *encoder) -{ - get_slave_funcs(encoder)->restore(encoder); -} -EXPORT_SYMBOL(drm_i2c_encoder_restore); diff --git a/trunk/drivers/gpu/drm/drm_fb_cma_helper.c b/trunk/drivers/gpu/drm/drm_fb_cma_helper.c index 0b5af7d0edb1..3742bc96421e 100644 --- a/trunk/drivers/gpu/drm/drm_fb_cma_helper.c +++ b/trunk/drivers/gpu/drm/drm_fb_cma_helper.c @@ -180,59 +180,6 @@ struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb, } EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj); -#ifdef CONFIG_DEBUG_FS -/** - * drm_fb_cma_describe() - Helper to dump information about a single - * CMA framebuffer object - */ -void drm_fb_cma_describe(struct drm_framebuffer *fb, struct seq_file *m) -{ - struct drm_fb_cma *fb_cma = to_fb_cma(fb); - int i, n = drm_format_num_planes(fb->pixel_format); - - seq_printf(m, "fb: %dx%d@%4.4s\n", fb->width, fb->height, - (char *)&fb->pixel_format); - - for (i = 0; i < n; i++) { - seq_printf(m, " %d: offset=%d pitch=%d, obj: ", - i, fb->offsets[i], fb->pitches[i]); - drm_gem_cma_describe(fb_cma->obj[i], m); - } -} -EXPORT_SYMBOL_GPL(drm_fb_cma_describe); - -/** - * drm_fb_cma_debugfs_show() - Helper to list CMA framebuffer objects - * in debugfs. - */ -int drm_fb_cma_debugfs_show(struct seq_file *m, void *arg) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - struct drm_framebuffer *fb; - int ret; - - ret = mutex_lock_interruptible(&dev->mode_config.mutex); - if (ret) - return ret; - - ret = mutex_lock_interruptible(&dev->struct_mutex); - if (ret) { - mutex_unlock(&dev->mode_config.mutex); - return ret; - } - - list_for_each_entry(fb, &dev->mode_config.fb_list, head) - drm_fb_cma_describe(fb, m); - - mutex_unlock(&dev->struct_mutex); - mutex_unlock(&dev->mode_config.mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(drm_fb_cma_debugfs_show); -#endif - static struct fb_ops drm_fbdev_cma_ops = { .owner = THIS_MODULE, .fb_fillrect = sys_fillrect, @@ -328,8 +275,23 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper, return ret; } +static int drm_fbdev_cma_probe(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + int ret = 0; + + if (!helper->fb) { + ret = drm_fbdev_cma_create(helper, sizes); + if (ret < 0) + return ret; + ret = 1; + } + + return ret; +} + static struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = { - .fb_probe = drm_fbdev_cma_create, + .fb_probe = drm_fbdev_cma_probe, }; /** @@ -371,9 +333,6 @@ struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev, } - /* disable all the possible outputs/crtcs before entering KMS mode */ - drm_helper_disable_unused_functions(dev); - ret = drm_fb_helper_initial_config(helper, preferred_bpp); if (ret < 0) { dev_err(dev->dev, "Failed to set inital hw configuration.\n"); @@ -430,13 +389,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_fini); */ void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma) { - if (fbdev_cma) { - struct drm_device *dev = fbdev_cma->fb_helper.dev; - - drm_modeset_lock_all(dev); + if (fbdev_cma) drm_fb_helper_restore_fbdev_mode(&fbdev_cma->fb_helper); - drm_modeset_unlock_all(dev); - } } EXPORT_SYMBOL_GPL(drm_fbdev_cma_restore_mode); diff --git a/trunk/drivers/gpu/drm/drm_fb_helper.c b/trunk/drivers/gpu/drm/drm_fb_helper.c index 59d6b9bf204b..0c6e25e979dd 100644 --- a/trunk/drivers/gpu/drm/drm_fb_helper.c +++ b/trunk/drivers/gpu/drm/drm_fb_helper.c @@ -52,36 +52,9 @@ static LIST_HEAD(kernel_fb_helper_list); * mode setting driver. They can be used mostly independantely from the crtc * helper functions used by many drivers to implement the kernel mode setting * interfaces. - * - * Initialization is done as a three-step process with drm_fb_helper_init(), - * drm_fb_helper_single_add_all_connectors() and drm_fb_helper_initial_config(). - * Drivers with fancier requirements than the default beheviour can override the - * second step with their own code. Teardown is done with drm_fb_helper_fini(). - * - * At runtime drivers should restore the fbdev console by calling - * drm_fb_helper_restore_fbdev_mode() from their ->lastclose callback. They - * should also notify the fb helper code from updates to the output - * configuration by calling drm_fb_helper_hotplug_event(). For easier - * integration with the output polling code in drm_crtc_helper.c the modeset - * code proves a ->output_poll_changed callback. - * - * All other functions exported by the fb helper library can be used to - * implement the fbdev driver interface by the driver. */ -/** - * drm_fb_helper_single_add_all_connectors() - add all connectors to fbdev - * emulation helper - * @fb_helper: fbdev initialized with drm_fb_helper_init - * - * This functions adds all the available connectors for use with the given - * fb_helper. This is a separate step to allow drivers to freely assign - * connectors to the fbdev, e.g. if some are reserved for special purposes or - * not adequate to be used for the fbcon. - * - * Since this is part of the initial setup before the fbdev is published, no - * locking is required. - */ +/* simple single crtc case helper function */ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper) { struct drm_device *dev = fb_helper->dev; @@ -190,10 +163,6 @@ static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc) crtc->funcs->gamma_set(crtc, r_base, g_base, b_base, 0, crtc->gamma_size); } -/** - * drm_fb_helper_debug_enter - implementation for ->fb_debug_enter - * @info: fbdev registered by the helper - */ int drm_fb_helper_debug_enter(struct fb_info *info) { struct drm_fb_helper *helper = info->par; @@ -239,10 +208,6 @@ static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc) return NULL; } -/** - * drm_fb_helper_debug_leave - implementation for ->fb_debug_leave - * @info: fbdev registered by the helper - */ int drm_fb_helper_debug_leave(struct fb_info *info) { struct drm_fb_helper *helper = info->par; @@ -274,21 +239,10 @@ int drm_fb_helper_debug_leave(struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_debug_leave); -/** - * drm_fb_helper_restore_fbdev_mode - restore fbdev configuration - * @fb_helper: fbcon to restore - * - * This should be called from driver's drm ->lastclose callback - * when implementing an fbcon on top of kms using this helper. This ensures that - * the user isn't greeted with a black screen when e.g. X dies. - */ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) { bool error = false; int i, ret; - - drm_warn_on_modeset_not_all_locked(fb_helper->dev); - for (i = 0; i < fb_helper->crtc_count; i++) { struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set; ret = drm_mode_set_config_internal(mode_set); @@ -299,10 +253,6 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper) } EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode); -/* - * restore fbcon display for all kms driver's using this helper, used for sysrq - * and panic handling. - */ static bool drm_fb_helper_force_kernel_mode(void) { bool ret, error = false; @@ -322,7 +272,7 @@ static bool drm_fb_helper_force_kernel_mode(void) return error; } -static int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed, +int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed, void *panic_str) { /* @@ -335,11 +285,26 @@ static int drm_fb_helper_panic(struct notifier_block *n, unsigned long ununsed, pr_err("panic occurred, switching back to text console\n"); return drm_fb_helper_force_kernel_mode(); } +EXPORT_SYMBOL(drm_fb_helper_panic); static struct notifier_block paniced = { .notifier_call = drm_fb_helper_panic, }; +/** + * drm_fb_helper_restore - restore the framebuffer console (kernel) config + * + * Restore's the kernel's fbcon mode, used for lastclose & panic paths. + */ +void drm_fb_helper_restore(void) +{ + bool ret; + ret = drm_fb_helper_force_kernel_mode(); + if (ret == true) + DRM_ERROR("Failed to restore crtc configuration\n"); +} +EXPORT_SYMBOL(drm_fb_helper_restore); + static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper) { struct drm_device *dev = fb_helper->dev; @@ -361,10 +326,7 @@ static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper) #ifdef CONFIG_MAGIC_SYSRQ static void drm_fb_helper_restore_work_fn(struct work_struct *ignored) { - bool ret; - ret = drm_fb_helper_force_kernel_mode(); - if (ret == true) - DRM_ERROR("Failed to restore crtc configuration\n"); + drm_fb_helper_restore(); } static DECLARE_WORK(drm_fb_helper_restore_work, drm_fb_helper_restore_work_fn); @@ -390,14 +352,6 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) struct drm_connector *connector; int i, j; - /* - * fbdev->blank can be called from irq context in case of a panic. - * Since we already have our own special panic handler which will - * restore the fbdev console mode completely, just bail out early. - */ - if (oops_in_progress) - return; - /* * For each CRTC in this fb, turn the connectors on/off. */ @@ -424,11 +378,6 @@ static void drm_fb_helper_dpms(struct fb_info *info, int dpms_mode) drm_modeset_unlock_all(dev); } -/** - * drm_fb_helper_blank - implementation for ->fb_blank - * @blank: desired blanking state - * @info: fbdev registered by the helper - */ int drm_fb_helper_blank(int blank, struct fb_info *info) { switch (blank) { @@ -472,24 +421,6 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper) kfree(helper->crtc_info); } -/** - * drm_fb_helper_init - initialize a drm_fb_helper structure - * @dev: drm device - * @fb_helper: driver-allocated fbdev helper structure to initialize - * @crtc_count: maximum number of crtcs to support in this fbdev emulation - * @max_conn_count: max connector count - * - * This allocates the structures for the fbdev helper with the given limits. - * Note that this won't yet touch the hardware (through the driver interfaces) - * nor register the fbdev. This is only done in drm_fb_helper_initial_config() - * to allow driver writes more control over the exact init sequence. - * - * Drivers must set fb_helper->funcs before calling - * drm_fb_helper_initial_config(). - * - * RETURNS: - * Zero if everything went ok, nonzero otherwise. - */ int drm_fb_helper_init(struct drm_device *dev, struct drm_fb_helper *fb_helper, int crtc_count, int max_conn_count) @@ -618,11 +549,6 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green, return 0; } -/** - * drm_fb_helper_setcmap - implementation for ->fb_setcmap - * @cmap: cmap to set - * @info: fbdev registered by the helper - */ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) { struct drm_fb_helper *fb_helper = info->par; @@ -662,11 +588,6 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_setcmap); -/** - * drm_fb_helper_check_var - implementation for ->fb_check_var - * @var: screeninfo to check - * @info: fbdev registered by the helper - */ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, struct fb_info *info) { @@ -759,19 +680,13 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var, } EXPORT_SYMBOL(drm_fb_helper_check_var); -/** - * drm_fb_helper_set_par - implementation for ->fb_set_par - * @info: fbdev registered by the helper - * - * This will let fbcon do the mode init and is called at initialization time by - * the fbdev core when registering the driver, and later on through the hotplug - * callback. - */ +/* this will let fbcon do the mode init */ int drm_fb_helper_set_par(struct fb_info *info) { struct drm_fb_helper *fb_helper = info->par; struct drm_device *dev = fb_helper->dev; struct fb_var_screeninfo *var = &info->var; + struct drm_crtc *crtc; int ret; int i; @@ -782,6 +697,7 @@ int drm_fb_helper_set_par(struct fb_info *info) drm_modeset_lock_all(dev); for (i = 0; i < fb_helper->crtc_count; i++) { + crtc = fb_helper->crtc_info[i].mode_set.crtc; ret = drm_mode_set_config_internal(&fb_helper->crtc_info[i].mode_set); if (ret) { drm_modeset_unlock_all(dev); @@ -798,11 +714,6 @@ int drm_fb_helper_set_par(struct fb_info *info) } EXPORT_SYMBOL(drm_fb_helper_set_par); -/** - * drm_fb_helper_pan_display - implementation for ->fb_pan_display - * @var: updated screen information - * @info: fbdev registered by the helper - */ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { @@ -840,15 +751,10 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var, } EXPORT_SYMBOL(drm_fb_helper_pan_display); -/* - * Allocates the backing storage and sets up the fbdev info structure through - * the ->fb_probe callback and then registers the fbdev and sets up the panic - * notifier. - */ -static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, - int preferred_bpp) +int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, + int preferred_bpp) { - int ret = 0; + int new_fb = 0; int crtc_count = 0; int i; struct fb_info *info; @@ -926,30 +832,27 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, } /* push down into drivers */ - ret = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes); - if (ret < 0) - return ret; + new_fb = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes); + if (new_fb < 0) + return new_fb; info = fb_helper->fbdev; - /* - * Set the fb pointer - usually drm_setup_crtcs does this for hotplug - * events, but at init time drm_setup_crtcs needs to be called before - * the fb is allocated (since we need to figure out the desired size of - * the fb before we can allocate it ...). Hence we need to fix things up - * here again. - */ + /* set the fb pointer */ for (i = 0; i < fb_helper->crtc_count; i++) - if (fb_helper->crtc_info[i].mode_set.num_connectors) - fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb; + fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb; + if (new_fb) { + info->var.pixclock = 0; + if (register_framebuffer(info) < 0) + return -EINVAL; - info->var.pixclock = 0; - if (register_framebuffer(info) < 0) - return -EINVAL; + dev_info(fb_helper->dev->dev, "fb%d: %s frame buffer device\n", + info->node, info->fix.id); - dev_info(fb_helper->dev->dev, "fb%d: %s frame buffer device\n", - info->node, info->fix.id); + } else { + drm_fb_helper_set_par(info); + } /* Switch back to kernel console on panic */ /* multi card linked list maybe */ @@ -959,25 +862,13 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper, &paniced); register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op); } - - list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list); + if (new_fb) + list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list); return 0; } +EXPORT_SYMBOL(drm_fb_helper_single_fb_probe); -/** - * drm_fb_helper_fill_fix - initializes fixed fbdev information - * @info: fbdev registered by the helper - * @pitch: desired pitch - * @depth: desired depth - * - * Helper to fill in the fixed fbdev information useful for a non-accelerated - * fbdev emulations. Drivers which support acceleration methods which impose - * additional constraints need to set up their own limits. - * - * Drivers should call this (or their equivalent setup code) from their - * ->fb_probe callback. - */ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, uint32_t depth) { @@ -998,20 +889,6 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch, } EXPORT_SYMBOL(drm_fb_helper_fill_fix); -/** - * drm_fb_helper_fill_var - initalizes variable fbdev information - * @info: fbdev instance to set up - * @fb_helper: fb helper instance to use as template - * @fb_width: desired fb width - * @fb_height: desired fb height - * - * Sets up the variable fbdev metainformation from the given fb helper instance - * and the drm framebuffer allocated in fb_helper->fb. - * - * Drivers should call this (or their equivalent setup code) from their - * ->fb_probe callback after having allocated the fbdev backing - * storage framebuffer. - */ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper, uint32_t fb_width, uint32_t fb_height) { @@ -1435,7 +1312,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) for (i = 0; i < fb_helper->crtc_count; i++) { modeset = &fb_helper->crtc_info[i].mode_set; modeset->num_connectors = 0; - modeset->fb = NULL; } for (i = 0; i < fb_helper->connector_count; i++) { @@ -1452,21 +1328,9 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) modeset->mode = drm_mode_duplicate(dev, fb_crtc->desired_mode); modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector; - modeset->fb = fb_helper->fb; } } - /* Clear out any old modes if there are no more connected outputs. */ - for (i = 0; i < fb_helper->crtc_count; i++) { - modeset = &fb_helper->crtc_info[i].mode_set; - if (modeset->num_connectors == 0) { - BUG_ON(modeset->fb); - BUG_ON(modeset->num_connectors); - if (modeset->mode) - drm_mode_destroy(dev, modeset->mode); - modeset->mode = NULL; - } - } out: kfree(crtcs); kfree(modes); @@ -1474,23 +1338,18 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper) } /** - * drm_fb_helper_initial_config - setup a sane initial connector configuration + * drm_helper_initial_config - setup a sane initial connector configuration * @fb_helper: fb_helper device struct * @bpp_sel: bpp value to use for the framebuffer configuration * + * LOCKING: + * Called at init time by the driver to set up the @fb_helper initial + * configuration, must take the mode config lock. + * * Scans the CRTCs and connectors and tries to put together an initial setup. * At the moment, this is a cloned configuration across all heads with * a new framebuffer object as the backing store. * - * Note that this also registers the fbdev and so allows userspace to call into - * the driver through the fbdev interfaces. - * - * This function will call down into the ->fb_probe callback to let - * the driver allocate and initialize the fbdev info structure and the drm - * framebuffer used to back the fbdev. drm_fb_helper_fill_var() and - * drm_fb_helper_fill_fix() are provided as helpers to setup simple default - * values for the fbdev info structure. - * * RETURNS: * Zero if everything went ok, nonzero otherwise. */ @@ -1499,6 +1358,9 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel) struct drm_device *dev = fb_helper->dev; int count = 0; + /* disable all the possible outputs/crtcs before entering KMS mode */ + drm_helper_disable_unused_functions(fb_helper->dev); + drm_fb_helper_parse_command_line(fb_helper); count = drm_fb_helper_probe_connector_modes(fb_helper, @@ -1521,17 +1383,12 @@ EXPORT_SYMBOL(drm_fb_helper_initial_config); * probing all the outputs attached to the fb * @fb_helper: the drm_fb_helper * + * LOCKING: + * Called at runtime, must take mode config lock. + * * Scan the connectors attached to the fb_helper and try to put together a * setup after *notification of a change in output configuration. * - * Called at runtime, takes the mode config locks to be able to check/change the - * modeset configuration. Must be run from process context (which usually means - * either the output polling work or a work item launched from the driver's - * hotplug interrupt). - * - * Note that the driver must ensure that this is only called _after_ the fb has - * been fully set up, i.e. after the call to drm_fb_helper_initial_config. - * * RETURNS: * 0 on success and a non-zero error code otherwise. */ @@ -1561,9 +1418,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper) drm_setup_crtcs(fb_helper); drm_modeset_unlock_all(dev); - drm_fb_helper_set_par(fb_helper->fbdev); - - return 0; + return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel); } EXPORT_SYMBOL(drm_fb_helper_hotplug_event); diff --git a/trunk/drivers/gpu/drm/drm_gem_cma_helper.c b/trunk/drivers/gpu/drm/drm_gem_cma_helper.c index 0a7e011509bd..1aa8fee1e865 100644 --- a/trunk/drivers/gpu/drm/drm_gem_cma_helper.c +++ b/trunk/drivers/gpu/drm/drm_gem_cma_helper.c @@ -249,24 +249,3 @@ int drm_gem_cma_dumb_destroy(struct drm_file *file_priv, return drm_gem_handle_delete(file_priv, handle); } EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_destroy); - -#ifdef CONFIG_DEBUG_FS -void drm_gem_cma_describe(struct drm_gem_cma_object *cma_obj, struct seq_file *m) -{ - struct drm_gem_object *obj = &cma_obj->base; - struct drm_device *dev = obj->dev; - uint64_t off = 0; - - WARN_ON(!mutex_is_locked(&dev->struct_mutex)); - - if (obj->map_list.map) - off = (uint64_t)obj->map_list.hash.key; - - seq_printf(m, "%2d (%2d) %08llx %08Zx %p %d", - obj->name, obj->refcount.refcount.counter, - off, cma_obj->paddr, cma_obj->vaddr, obj->size); - - seq_printf(m, "\n"); -} -EXPORT_SYMBOL_GPL(drm_gem_cma_describe); -#endif diff --git a/trunk/drivers/gpu/drm/drm_irq.c b/trunk/drivers/gpu/drm/drm_irq.c index a6a8643a6a77..38e79927b2d7 100644 --- a/trunk/drivers/gpu/drm/drm_irq.c +++ b/trunk/drivers/gpu/drm/drm_irq.c @@ -867,7 +867,6 @@ void drm_send_vblank_event(struct drm_device *dev, int crtc, now = get_drm_timestamp(); } - e->pipe = crtc; send_vblank_event(dev, e, seq, &now); } EXPORT_SYMBOL(drm_send_vblank_event); diff --git a/trunk/drivers/gpu/drm/drm_pci.c b/trunk/drivers/gpu/drm/drm_pci.c index bd719e936e13..86102a08f65c 100644 --- a/trunk/drivers/gpu/drm/drm_pci.c +++ b/trunk/drivers/gpu/drm/drm_pci.c @@ -439,6 +439,33 @@ int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) return 0; } +#else + +int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) +{ + return -1; +} + +#endif + +EXPORT_SYMBOL(drm_pci_init); + +/*@}*/ +void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver) +{ + struct drm_device *dev, *tmp; + DRM_DEBUG("\n"); + + if (driver->driver_features & DRIVER_MODESET) { + pci_unregister_driver(pdriver); + } else { + list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item) + drm_put_dev(dev); + } + DRM_INFO("Module unloaded\n"); +} +EXPORT_SYMBOL(drm_pci_exit); + int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask) { struct pci_dev *root; @@ -476,30 +503,3 @@ int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask) return 0; } EXPORT_SYMBOL(drm_pcie_get_speed_cap_mask); - -#else - -int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) -{ - return -1; -} - -#endif - -EXPORT_SYMBOL(drm_pci_init); - -/*@}*/ -void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver) -{ - struct drm_device *dev, *tmp; - DRM_DEBUG("\n"); - - if (driver->driver_features & DRIVER_MODESET) { - pci_unregister_driver(pdriver); - } else { - list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item) - drm_put_dev(dev); - } - DRM_INFO("Module unloaded\n"); -} -EXPORT_SYMBOL(drm_pci_exit); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c index 0e04f4ea441f..294c0513f587 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -99,10 +99,6 @@ static int exynos_drm_fb_create_handle(struct drm_framebuffer *fb, DRM_DEBUG_KMS("%s\n", __FILE__); - /* This fb should have only one gem object. */ - if (WARN_ON(exynos_fb->buf_cnt != 1)) - return -EINVAL; - return drm_gem_handle_create(file_priv, &exynos_fb->exynos_gem_obj[0]->base, handle); } @@ -221,25 +217,23 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd) { struct drm_gem_object *obj; - struct exynos_drm_gem_obj *exynos_gem_obj; struct exynos_drm_fb *exynos_fb; int i, ret; DRM_DEBUG_KMS("%s\n", __FILE__); + obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); + if (!obj) { + DRM_ERROR("failed to lookup gem object\n"); + return ERR_PTR(-ENOENT); + } + exynos_fb = kzalloc(sizeof(*exynos_fb), GFP_KERNEL); if (!exynos_fb) { DRM_ERROR("failed to allocate exynos drm framebuffer\n"); return ERR_PTR(-ENOMEM); } - obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); - if (!obj) { - DRM_ERROR("failed to lookup gem object\n"); - ret = -ENOENT; - goto err_free; - } - drm_helper_mode_fill_fb_struct(&exynos_fb->fb, mode_cmd); exynos_fb->exynos_gem_obj[0] = to_exynos_gem_obj(obj); exynos_fb->buf_cnt = exynos_drm_format_num_buffers(mode_cmd); @@ -247,44 +241,43 @@ exynos_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, DRM_DEBUG_KMS("buf_cnt = %d\n", exynos_fb->buf_cnt); for (i = 1; i < exynos_fb->buf_cnt; i++) { + struct exynos_drm_gem_obj *exynos_gem_obj; + int ret; + obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[i]); if (!obj) { DRM_ERROR("failed to lookup gem object\n"); - ret = -ENOENT; - exynos_fb->buf_cnt = i; - goto err_unreference; + kfree(exynos_fb); + return ERR_PTR(-ENOENT); } exynos_gem_obj = to_exynos_gem_obj(obj); - exynos_fb->exynos_gem_obj[i] = exynos_gem_obj; ret = check_fb_gem_memory_type(dev, exynos_gem_obj); if (ret < 0) { DRM_ERROR("cannot use this gem memory type for fb.\n"); - goto err_unreference; + kfree(exynos_fb); + return ERR_PTR(ret); } + + exynos_fb->exynos_gem_obj[i] = to_exynos_gem_obj(obj); } ret = drm_framebuffer_init(dev, &exynos_fb->fb, &exynos_drm_fb_funcs); if (ret) { - DRM_ERROR("failed to init framebuffer.\n"); - goto err_unreference; - } + for (i = 0; i < exynos_fb->buf_cnt; i++) { + struct exynos_drm_gem_obj *gem_obj; - return &exynos_fb->fb; - -err_unreference: - for (i = 0; i < exynos_fb->buf_cnt; i++) { - struct drm_gem_object *obj; + gem_obj = exynos_fb->exynos_gem_obj[i]; + drm_gem_object_unreference_unlocked(&gem_obj->base); + } - obj = &exynos_fb->exynos_gem_obj[i]->base; - if (obj) - drm_gem_object_unreference_unlocked(obj); + kfree(exynos_fb); + return ERR_PTR(ret); } -err_free: - kfree(exynos_fb); - return ERR_PTR(ret); + + return &exynos_fb->fb; } struct exynos_drm_gem_buf *exynos_drm_fb_buffer(struct drm_framebuffer *fb, diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 68f0045f86b8..90d335cfb8c0 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -226,8 +226,36 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper, return ret; } +static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + int ret = 0; + + DRM_DEBUG_KMS("%s\n", __FILE__); + + /* + * with !helper->fb, it means that this funcion is called first time + * and after that, the helper->fb would be used as clone mode. + */ + if (!helper->fb) { + ret = exynos_drm_fbdev_create(helper, sizes); + if (ret < 0) { + DRM_ERROR("failed to create fbdev.\n"); + return ret; + } + + /* + * fb_helper expects a value more than 1 if succeed + * because register_framebuffer() should be called. + */ + ret = 1; + } + + return ret; +} + static struct drm_fb_helper_funcs exynos_drm_fb_helper_funcs = { - .fb_probe = exynos_drm_fbdev_create, + .fb_probe = exynos_drm_fbdev_probe, }; int exynos_drm_fbdev_init(struct drm_device *dev) @@ -267,9 +295,6 @@ int exynos_drm_fbdev_init(struct drm_device *dev) } - /* disable all the possible outputs/crtcs before entering KMS mode */ - drm_helper_disable_unused_functions(dev); - ret = drm_fb_helper_initial_config(helper, PREFERRED_BPP); if (ret < 0) { DRM_ERROR("failed to set up hw configuration.\n"); @@ -351,7 +376,5 @@ void exynos_drm_fbdev_restore_mode(struct drm_device *dev) if (!private || !private->fb_helper) return; - drm_modeset_lock_all(dev); drm_fb_helper_restore_fbdev_mode(private->fb_helper); - drm_modeset_unlock_all(dev); } diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 0fcfbe4660bb..9a4c08e7453c 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -430,7 +429,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, g2d_userptr->pages = pages; - sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); + sgt = kzalloc(sizeof *sgt, GFP_KERNEL); if (!sgt) { DRM_ERROR("failed to allocate sg table.\n"); ret = -ENOMEM; @@ -1241,14 +1240,6 @@ static int g2d_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume); -#ifdef CONFIG_OF -static const struct of_device_id exynos_g2d_match[] = { - { .compatible = "samsung,exynos5250-g2d" }, - {}, -}; -MODULE_DEVICE_TABLE(of, exynos_g2d_match); -#endif - struct platform_driver g2d_driver = { .probe = g2d_probe, .remove = g2d_remove, @@ -1256,6 +1247,5 @@ struct platform_driver g2d_driver = { .name = "s5p-g2d", .owner = THIS_MODULE, .pm = &g2d_pm_ops, - .of_match_table = of_match_ptr(exynos_g2d_match), }, }; diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c index 67e17ce112b6..473180776528 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -329,11 +329,17 @@ static struct drm_file *exynos_drm_find_drm_file(struct drm_device *drm_dev, { struct drm_file *file_priv; + mutex_lock(&drm_dev->struct_mutex); + /* find current process's drm_file from filelist. */ - list_for_each_entry(file_priv, &drm_dev->filelist, lhead) - if (file_priv->filp == filp) + list_for_each_entry(file_priv, &drm_dev->filelist, lhead) { + if (file_priv->filp == filp) { + mutex_unlock(&drm_dev->struct_mutex); return file_priv; + } + } + mutex_unlock(&drm_dev->struct_mutex); WARN_ON(1); return ERR_PTR(-EFAULT); @@ -394,7 +400,9 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp, */ drm_gem_object_reference(obj); + mutex_lock(&drm_dev->struct_mutex); drm_vm_open_locked(drm_dev, vma); + mutex_unlock(&drm_dev->struct_mutex); return 0; } @@ -423,16 +431,6 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, return -EINVAL; } - /* - * We have to use gem object and its fops for specific mmaper, - * but vm_mmap() can deliver only filp. So we have to change - * filp->f_op and filp->private_data temporarily, then restore - * again. So it is important to keep lock until restoration the - * settings to prevent others from misuse of filp->f_op or - * filp->private_data. - */ - mutex_lock(&dev->struct_mutex); - /* * Set specific mmper's fops. And it will be restored by * exynos_drm_gem_mmap_buffer to dev->driver->fops. @@ -450,20 +448,13 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data, addr = vm_mmap(file_priv->filp, 0, args->size, PROT_READ | PROT_WRITE, MAP_SHARED, 0); - drm_gem_object_unreference(obj); + drm_gem_object_unreference_unlocked(obj); if (IS_ERR((void *)addr)) { - /* check filp->f_op, filp->private_data are restored */ - if (file_priv->filp->f_op == &exynos_drm_gem_fops) { - file_priv->filp->f_op = fops_get(dev->driver->fops); - file_priv->filp->private_data = file_priv; - } - mutex_unlock(&dev->struct_mutex); + file_priv->filp->private_data = file_priv; return PTR_ERR((void *)addr); } - mutex_unlock(&dev->struct_mutex); - args->mapped = addr; DRM_DEBUG_KMS("mapped = 0x%lx\n", (unsigned long)args->mapped); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 7c27df03c9ff..28644539b305 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.c @@ -124,21 +124,9 @@ static struct edid *drm_hdmi_get_edid(struct device *dev, static int drm_hdmi_check_timing(struct device *dev, void *timing) { struct drm_hdmi_context *ctx = to_context(dev); - int ret = 0; DRM_DEBUG_KMS("%s\n", __FILE__); - /* - * Both, mixer and hdmi should be able to handle the requested mode. - * If any of the two fails, return mode as BAD. - */ - - if (mixer_ops && mixer_ops->check_timing) - ret = mixer_ops->check_timing(ctx->mixer_ctx->ctx, timing); - - if (ret) - return ret; - if (hdmi_ops && hdmi_ops->check_timing) return hdmi_ops->check_timing(ctx->hdmi_ctx->ctx, timing); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.h index b7faa3662307..d80516fc9ed7 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.h +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_hdmi.h @@ -32,7 +32,7 @@ struct exynos_hdmi_ops { bool (*is_connected)(void *ctx); struct edid *(*get_edid)(void *ctx, struct drm_connector *connector); - int (*check_timing)(void *ctx, struct fb_videomode *timing); + int (*check_timing)(void *ctx, void *timing); int (*power_on)(void *ctx, int mode); /* manager */ @@ -58,9 +58,6 @@ struct exynos_mixer_ops { void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay); void (*win_commit)(void *ctx, int zpos); void (*win_disable)(void *ctx, int zpos); - - /* display */ - int (*check_timing)(void *ctx, struct fb_videomode *timing); }; void exynos_hdmi_drv_attach(struct exynos_drm_hdmi_context *ctx); diff --git a/trunk/drivers/gpu/drm/exynos/exynos_drm_iommu.h b/trunk/drivers/gpu/drm/exynos/exynos_drm_iommu.h index 598e60f57d4b..53b7deea8ab7 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_drm_iommu.h +++ b/trunk/drivers/gpu/drm/exynos/exynos_drm_iommu.h @@ -14,7 +14,7 @@ #define EXYNOS_DEV_ADDR_START 0x20000000 #define EXYNOS_DEV_ADDR_SIZE 0x40000000 -#define EXYNOS_DEV_ADDR_ORDER 0x0 +#define EXYNOS_DEV_ADDR_ORDER 0x4 #ifdef CONFIG_DRM_EXYNOS_IOMMU diff --git a/trunk/drivers/gpu/drm/exynos/exynos_hdmi.c b/trunk/drivers/gpu/drm/exynos/exynos_hdmi.c index 6d63f9090f94..fbab3c468603 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -87,73 +87,6 @@ struct hdmi_resources { int regul_count; }; -struct hdmi_tg_regs { - u8 cmd[1]; - u8 h_fsz[2]; - u8 hact_st[2]; - u8 hact_sz[2]; - u8 v_fsz[2]; - u8 vsync[2]; - u8 vsync2[2]; - u8 vact_st[2]; - u8 vact_sz[2]; - u8 field_chg[2]; - u8 vact_st2[2]; - u8 vact_st3[2]; - u8 vact_st4[2]; - u8 vsync_top_hdmi[2]; - u8 vsync_bot_hdmi[2]; - u8 field_top_hdmi[2]; - u8 field_bot_hdmi[2]; - u8 tg_3d[1]; -}; - -struct hdmi_core_regs { - u8 h_blank[2]; - u8 v2_blank[2]; - u8 v1_blank[2]; - u8 v_line[2]; - u8 h_line[2]; - u8 hsync_pol[1]; - u8 vsync_pol[1]; - u8 int_pro_mode[1]; - u8 v_blank_f0[2]; - u8 v_blank_f1[2]; - u8 h_sync_start[2]; - u8 h_sync_end[2]; - u8 v_sync_line_bef_2[2]; - u8 v_sync_line_bef_1[2]; - u8 v_sync_line_aft_2[2]; - u8 v_sync_line_aft_1[2]; - u8 v_sync_line_aft_pxl_2[2]; - u8 v_sync_line_aft_pxl_1[2]; - u8 v_blank_f2[2]; /* for 3D mode */ - u8 v_blank_f3[2]; /* for 3D mode */ - u8 v_blank_f4[2]; /* for 3D mode */ - u8 v_blank_f5[2]; /* for 3D mode */ - u8 v_sync_line_aft_3[2]; - u8 v_sync_line_aft_4[2]; - u8 v_sync_line_aft_5[2]; - u8 v_sync_line_aft_6[2]; - u8 v_sync_line_aft_pxl_3[2]; - u8 v_sync_line_aft_pxl_4[2]; - u8 v_sync_line_aft_pxl_5[2]; - u8 v_sync_line_aft_pxl_6[2]; - u8 vact_space_1[2]; - u8 vact_space_2[2]; - u8 vact_space_3[2]; - u8 vact_space_4[2]; - u8 vact_space_5[2]; - u8 vact_space_6[2]; -}; - -struct hdmi_v14_conf { - int pixel_clock; - struct hdmi_core_regs core; - struct hdmi_tg_regs tg; - int cea_video_id; -}; - struct hdmi_context { struct device *dev; struct drm_device *drm_dev; @@ -171,7 +104,6 @@ struct hdmi_context { /* current hdmiphy conf index */ int cur_conf; - struct hdmi_v14_conf mode_conf; struct hdmi_resources res; @@ -460,132 +392,586 @@ static const struct hdmi_v13_conf hdmi_v13_confs[] = { }; /* HDMI Version 1.4 */ -struct hdmiphy_config { - int pixel_clock; - u8 conf[32]; +static const u8 hdmiphy_conf27_027[32] = { + 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08, + 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80, + 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, + 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, }; -/* list of all required phy config settings */ -static const struct hdmiphy_config hdmiphy_v14_configs[] = { - { - .pixel_clock = 25200000, - .conf = { - 0x01, 0x51, 0x2A, 0x75, 0x40, 0x01, 0x00, 0x08, - 0x82, 0x80, 0xfc, 0xd8, 0x45, 0xa0, 0xac, 0x80, - 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0xf4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80, - }, +static const u8 hdmiphy_conf74_176[32] = { + 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x5b, 0xef, 0x08, + 0x81, 0xa0, 0xb9, 0xd8, 0x45, 0xa0, 0xac, 0x80, + 0x5a, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, + 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, +}; + +static const u8 hdmiphy_conf74_25[32] = { + 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08, + 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, + 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, + 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, +}; + +static const u8 hdmiphy_conf148_5[32] = { + 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08, + 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, + 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, + 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00, +}; + +struct hdmi_tg_regs { + u8 cmd; + u8 h_fsz_l; + u8 h_fsz_h; + u8 hact_st_l; + u8 hact_st_h; + u8 hact_sz_l; + u8 hact_sz_h; + u8 v_fsz_l; + u8 v_fsz_h; + u8 vsync_l; + u8 vsync_h; + u8 vsync2_l; + u8 vsync2_h; + u8 vact_st_l; + u8 vact_st_h; + u8 vact_sz_l; + u8 vact_sz_h; + u8 field_chg_l; + u8 field_chg_h; + u8 vact_st2_l; + u8 vact_st2_h; + u8 vact_st3_l; + u8 vact_st3_h; + u8 vact_st4_l; + u8 vact_st4_h; + u8 vsync_top_hdmi_l; + u8 vsync_top_hdmi_h; + u8 vsync_bot_hdmi_l; + u8 vsync_bot_hdmi_h; + u8 field_top_hdmi_l; + u8 field_top_hdmi_h; + u8 field_bot_hdmi_l; + u8 field_bot_hdmi_h; + u8 tg_3d; +}; + +struct hdmi_core_regs { + u8 h_blank[2]; + u8 v2_blank[2]; + u8 v1_blank[2]; + u8 v_line[2]; + u8 h_line[2]; + u8 hsync_pol[1]; + u8 vsync_pol[1]; + u8 int_pro_mode[1]; + u8 v_blank_f0[2]; + u8 v_blank_f1[2]; + u8 h_sync_start[2]; + u8 h_sync_end[2]; + u8 v_sync_line_bef_2[2]; + u8 v_sync_line_bef_1[2]; + u8 v_sync_line_aft_2[2]; + u8 v_sync_line_aft_1[2]; + u8 v_sync_line_aft_pxl_2[2]; + u8 v_sync_line_aft_pxl_1[2]; + u8 v_blank_f2[2]; /* for 3D mode */ + u8 v_blank_f3[2]; /* for 3D mode */ + u8 v_blank_f4[2]; /* for 3D mode */ + u8 v_blank_f5[2]; /* for 3D mode */ + u8 v_sync_line_aft_3[2]; + u8 v_sync_line_aft_4[2]; + u8 v_sync_line_aft_5[2]; + u8 v_sync_line_aft_6[2]; + u8 v_sync_line_aft_pxl_3[2]; + u8 v_sync_line_aft_pxl_4[2]; + u8 v_sync_line_aft_pxl_5[2]; + u8 v_sync_line_aft_pxl_6[2]; + u8 vact_space_1[2]; + u8 vact_space_2[2]; + u8 vact_space_3[2]; + u8 vact_space_4[2]; + u8 vact_space_5[2]; + u8 vact_space_6[2]; +}; + +struct hdmi_preset_conf { + struct hdmi_core_regs core; + struct hdmi_tg_regs tg; +}; + +struct hdmi_conf { + int width; + int height; + int vrefresh; + bool interlace; + int cea_video_id; + const u8 *hdmiphy_data; + const struct hdmi_preset_conf *conf; +}; + +static const struct hdmi_preset_conf hdmi_conf_480p60 = { + .core = { + .h_blank = {0x8a, 0x00}, + .v2_blank = {0x0d, 0x02}, + .v1_blank = {0x2d, 0x00}, + .v_line = {0x0d, 0x02}, + .h_line = {0x5a, 0x03}, + .hsync_pol = {0x01}, + .vsync_pol = {0x01}, + .int_pro_mode = {0x00}, + .v_blank_f0 = {0xff, 0xff}, + .v_blank_f1 = {0xff, 0xff}, + .h_sync_start = {0x0e, 0x00}, + .h_sync_end = {0x4c, 0x00}, + .v_sync_line_bef_2 = {0x0f, 0x00}, + .v_sync_line_bef_1 = {0x09, 0x00}, + .v_sync_line_aft_2 = {0xff, 0xff}, + .v_sync_line_aft_1 = {0xff, 0xff}, + .v_sync_line_aft_pxl_2 = {0xff, 0xff}, + .v_sync_line_aft_pxl_1 = {0xff, 0xff}, + .v_blank_f2 = {0xff, 0xff}, + .v_blank_f3 = {0xff, 0xff}, + .v_blank_f4 = {0xff, 0xff}, + .v_blank_f5 = {0xff, 0xff}, + .v_sync_line_aft_3 = {0xff, 0xff}, + .v_sync_line_aft_4 = {0xff, 0xff}, + .v_sync_line_aft_5 = {0xff, 0xff}, + .v_sync_line_aft_6 = {0xff, 0xff}, + .v_sync_line_aft_pxl_3 = {0xff, 0xff}, + .v_sync_line_aft_pxl_4 = {0xff, 0xff}, + .v_sync_line_aft_pxl_5 = {0xff, 0xff}, + .v_sync_line_aft_pxl_6 = {0xff, 0xff}, + .vact_space_1 = {0xff, 0xff}, + .vact_space_2 = {0xff, 0xff}, + .vact_space_3 = {0xff, 0xff}, + .vact_space_4 = {0xff, 0xff}, + .vact_space_5 = {0xff, 0xff}, + .vact_space_6 = {0xff, 0xff}, + /* other don't care */ }, - { - .pixel_clock = 27000000, - .conf = { - 0x01, 0xd1, 0x22, 0x51, 0x40, 0x08, 0xfc, 0x20, - 0x98, 0xa0, 0xcb, 0xd8, 0x45, 0xa0, 0xac, 0x80, - 0x06, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0xe4, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80, - }, + .tg = { + 0x00, /* cmd */ + 0x5a, 0x03, /* h_fsz */ + 0x8a, 0x00, 0xd0, 0x02, /* hact */ + 0x0d, 0x02, /* v_fsz */ + 0x01, 0x00, 0x33, 0x02, /* vsync */ + 0x2d, 0x00, 0xe0, 0x01, /* vact */ + 0x33, 0x02, /* field_chg */ + 0x48, 0x02, /* vact_st2 */ + 0x00, 0x00, /* vact_st3 */ + 0x00, 0x00, /* vact_st4 */ + 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ + 0x01, 0x00, 0x33, 0x02, /* field top/bot */ + 0x00, /* 3d FP */ }, - { - .pixel_clock = 27027000, - .conf = { - 0x01, 0xd1, 0x2d, 0x72, 0x40, 0x64, 0x12, 0x08, - 0x43, 0xa0, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80, - 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0xe3, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, - }, +}; + +static const struct hdmi_preset_conf hdmi_conf_720p50 = { + .core = { + .h_blank = {0xbc, 0x02}, + .v2_blank = {0xee, 0x02}, + .v1_blank = {0x1e, 0x00}, + .v_line = {0xee, 0x02}, + .h_line = {0xbc, 0x07}, + .hsync_pol = {0x00}, + .vsync_pol = {0x00}, + .int_pro_mode = {0x00}, + .v_blank_f0 = {0xff, 0xff}, + .v_blank_f1 = {0xff, 0xff}, + .h_sync_start = {0xb6, 0x01}, + .h_sync_end = {0xde, 0x01}, + .v_sync_line_bef_2 = {0x0a, 0x00}, + .v_sync_line_bef_1 = {0x05, 0x00}, + .v_sync_line_aft_2 = {0xff, 0xff}, + .v_sync_line_aft_1 = {0xff, 0xff}, + .v_sync_line_aft_pxl_2 = {0xff, 0xff}, + .v_sync_line_aft_pxl_1 = {0xff, 0xff}, + .v_blank_f2 = {0xff, 0xff}, + .v_blank_f3 = {0xff, 0xff}, + .v_blank_f4 = {0xff, 0xff}, + .v_blank_f5 = {0xff, 0xff}, + .v_sync_line_aft_3 = {0xff, 0xff}, + .v_sync_line_aft_4 = {0xff, 0xff}, + .v_sync_line_aft_5 = {0xff, 0xff}, + .v_sync_line_aft_6 = {0xff, 0xff}, + .v_sync_line_aft_pxl_3 = {0xff, 0xff}, + .v_sync_line_aft_pxl_4 = {0xff, 0xff}, + .v_sync_line_aft_pxl_5 = {0xff, 0xff}, + .v_sync_line_aft_pxl_6 = {0xff, 0xff}, + .vact_space_1 = {0xff, 0xff}, + .vact_space_2 = {0xff, 0xff}, + .vact_space_3 = {0xff, 0xff}, + .vact_space_4 = {0xff, 0xff}, + .vact_space_5 = {0xff, 0xff}, + .vact_space_6 = {0xff, 0xff}, + /* other don't care */ }, - { - .pixel_clock = 36000000, - .conf = { - 0x01, 0x51, 0x2d, 0x55, 0x40, 0x01, 0x00, 0x08, - 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80, - 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0xab, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80, - }, + .tg = { + 0x00, /* cmd */ + 0xbc, 0x07, /* h_fsz */ + 0xbc, 0x02, 0x00, 0x05, /* hact */ + 0xee, 0x02, /* v_fsz */ + 0x01, 0x00, 0x33, 0x02, /* vsync */ + 0x1e, 0x00, 0xd0, 0x02, /* vact */ + 0x33, 0x02, /* field_chg */ + 0x48, 0x02, /* vact_st2 */ + 0x00, 0x00, /* vact_st3 */ + 0x00, 0x00, /* vact_st4 */ + 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ + 0x01, 0x00, 0x33, 0x02, /* field top/bot */ + 0x00, /* 3d FP */ }, - { - .pixel_clock = 40000000, - .conf = { - 0x01, 0x51, 0x32, 0x55, 0x40, 0x01, 0x00, 0x08, - 0x82, 0x80, 0x2c, 0xd9, 0x45, 0xa0, 0xac, 0x80, - 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0x9a, 0x24, 0x00, 0x00, 0x00, 0x01, 0x80, - }, +}; + +static const struct hdmi_preset_conf hdmi_conf_720p60 = { + .core = { + .h_blank = {0x72, 0x01}, + .v2_blank = {0xee, 0x02}, + .v1_blank = {0x1e, 0x00}, + .v_line = {0xee, 0x02}, + .h_line = {0x72, 0x06}, + .hsync_pol = {0x00}, + .vsync_pol = {0x00}, + .int_pro_mode = {0x00}, + .v_blank_f0 = {0xff, 0xff}, + .v_blank_f1 = {0xff, 0xff}, + .h_sync_start = {0x6c, 0x00}, + .h_sync_end = {0x94, 0x00}, + .v_sync_line_bef_2 = {0x0a, 0x00}, + .v_sync_line_bef_1 = {0x05, 0x00}, + .v_sync_line_aft_2 = {0xff, 0xff}, + .v_sync_line_aft_1 = {0xff, 0xff}, + .v_sync_line_aft_pxl_2 = {0xff, 0xff}, + .v_sync_line_aft_pxl_1 = {0xff, 0xff}, + .v_blank_f2 = {0xff, 0xff}, + .v_blank_f3 = {0xff, 0xff}, + .v_blank_f4 = {0xff, 0xff}, + .v_blank_f5 = {0xff, 0xff}, + .v_sync_line_aft_3 = {0xff, 0xff}, + .v_sync_line_aft_4 = {0xff, 0xff}, + .v_sync_line_aft_5 = {0xff, 0xff}, + .v_sync_line_aft_6 = {0xff, 0xff}, + .v_sync_line_aft_pxl_3 = {0xff, 0xff}, + .v_sync_line_aft_pxl_4 = {0xff, 0xff}, + .v_sync_line_aft_pxl_5 = {0xff, 0xff}, + .v_sync_line_aft_pxl_6 = {0xff, 0xff}, + .vact_space_1 = {0xff, 0xff}, + .vact_space_2 = {0xff, 0xff}, + .vact_space_3 = {0xff, 0xff}, + .vact_space_4 = {0xff, 0xff}, + .vact_space_5 = {0xff, 0xff}, + .vact_space_6 = {0xff, 0xff}, + /* other don't care */ }, - { - .pixel_clock = 65000000, - .conf = { - 0x01, 0xd1, 0x36, 0x34, 0x40, 0x1e, 0x0a, 0x08, - 0x82, 0xa0, 0x45, 0xd9, 0x45, 0xa0, 0xac, 0x80, - 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0xbd, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80, - }, + .tg = { + 0x00, /* cmd */ + 0x72, 0x06, /* h_fsz */ + 0x72, 0x01, 0x00, 0x05, /* hact */ + 0xee, 0x02, /* v_fsz */ + 0x01, 0x00, 0x33, 0x02, /* vsync */ + 0x1e, 0x00, 0xd0, 0x02, /* vact */ + 0x33, 0x02, /* field_chg */ + 0x48, 0x02, /* vact_st2 */ + 0x00, 0x00, /* vact_st3 */ + 0x00, 0x00, /* vact_st4 */ + 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ + 0x01, 0x00, 0x33, 0x02, /* field top/bot */ + 0x00, /* 3d FP */ }, - { - .pixel_clock = 74176000, - .conf = { - 0x01, 0xd1, 0x3e, 0x35, 0x40, 0x5b, 0xde, 0x08, - 0x82, 0xa0, 0x73, 0xd9, 0x45, 0xa0, 0xac, 0x80, - 0x56, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0xa6, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80, - }, +}; + +static const struct hdmi_preset_conf hdmi_conf_1080i50 = { + .core = { + .h_blank = {0xd0, 0x02}, + .v2_blank = {0x32, 0x02}, + .v1_blank = {0x16, 0x00}, + .v_line = {0x65, 0x04}, + .h_line = {0x50, 0x0a}, + .hsync_pol = {0x00}, + .vsync_pol = {0x00}, + .int_pro_mode = {0x01}, + .v_blank_f0 = {0x49, 0x02}, + .v_blank_f1 = {0x65, 0x04}, + .h_sync_start = {0x0e, 0x02}, + .h_sync_end = {0x3a, 0x02}, + .v_sync_line_bef_2 = {0x07, 0x00}, + .v_sync_line_bef_1 = {0x02, 0x00}, + .v_sync_line_aft_2 = {0x39, 0x02}, + .v_sync_line_aft_1 = {0x34, 0x02}, + .v_sync_line_aft_pxl_2 = {0x38, 0x07}, + .v_sync_line_aft_pxl_1 = {0x38, 0x07}, + .v_blank_f2 = {0xff, 0xff}, + .v_blank_f3 = {0xff, 0xff}, + .v_blank_f4 = {0xff, 0xff}, + .v_blank_f5 = {0xff, 0xff}, + .v_sync_line_aft_3 = {0xff, 0xff}, + .v_sync_line_aft_4 = {0xff, 0xff}, + .v_sync_line_aft_5 = {0xff, 0xff}, + .v_sync_line_aft_6 = {0xff, 0xff}, + .v_sync_line_aft_pxl_3 = {0xff, 0xff}, + .v_sync_line_aft_pxl_4 = {0xff, 0xff}, + .v_sync_line_aft_pxl_5 = {0xff, 0xff}, + .v_sync_line_aft_pxl_6 = {0xff, 0xff}, + .vact_space_1 = {0xff, 0xff}, + .vact_space_2 = {0xff, 0xff}, + .vact_space_3 = {0xff, 0xff}, + .vact_space_4 = {0xff, 0xff}, + .vact_space_5 = {0xff, 0xff}, + .vact_space_6 = {0xff, 0xff}, + /* other don't care */ }, - { - .pixel_clock = 74250000, - .conf = { - 0x01, 0xd1, 0x1f, 0x10, 0x40, 0x40, 0xf8, 0x08, - 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, - 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0xa5, 0x24, 0x01, 0x00, 0x00, 0x01, 0x00, - }, + .tg = { + 0x00, /* cmd */ + 0x50, 0x0a, /* h_fsz */ + 0xd0, 0x02, 0x80, 0x07, /* hact */ + 0x65, 0x04, /* v_fsz */ + 0x01, 0x00, 0x33, 0x02, /* vsync */ + 0x16, 0x00, 0x1c, 0x02, /* vact */ + 0x33, 0x02, /* field_chg */ + 0x49, 0x02, /* vact_st2 */ + 0x00, 0x00, /* vact_st3 */ + 0x00, 0x00, /* vact_st4 */ + 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ + 0x01, 0x00, 0x33, 0x02, /* field top/bot */ + 0x00, /* 3d FP */ }, - { - .pixel_clock = 83500000, - .conf = { - 0x01, 0xd1, 0x23, 0x11, 0x40, 0x0c, 0xfb, 0x08, - 0x85, 0xa0, 0xd1, 0xd8, 0x45, 0xa0, 0xac, 0x80, - 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0x93, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80, - }, +}; + +static const struct hdmi_preset_conf hdmi_conf_1080i60 = { + .core = { + .h_blank = {0x18, 0x01}, + .v2_blank = {0x32, 0x02}, + .v1_blank = {0x16, 0x00}, + .v_line = {0x65, 0x04}, + .h_line = {0x98, 0x08}, + .hsync_pol = {0x00}, + .vsync_pol = {0x00}, + .int_pro_mode = {0x01}, + .v_blank_f0 = {0x49, 0x02}, + .v_blank_f1 = {0x65, 0x04}, + .h_sync_start = {0x56, 0x00}, + .h_sync_end = {0x82, 0x00}, + .v_sync_line_bef_2 = {0x07, 0x00}, + .v_sync_line_bef_1 = {0x02, 0x00}, + .v_sync_line_aft_2 = {0x39, 0x02}, + .v_sync_line_aft_1 = {0x34, 0x02}, + .v_sync_line_aft_pxl_2 = {0xa4, 0x04}, + .v_sync_line_aft_pxl_1 = {0xa4, 0x04}, + .v_blank_f2 = {0xff, 0xff}, + .v_blank_f3 = {0xff, 0xff}, + .v_blank_f4 = {0xff, 0xff}, + .v_blank_f5 = {0xff, 0xff}, + .v_sync_line_aft_3 = {0xff, 0xff}, + .v_sync_line_aft_4 = {0xff, 0xff}, + .v_sync_line_aft_5 = {0xff, 0xff}, + .v_sync_line_aft_6 = {0xff, 0xff}, + .v_sync_line_aft_pxl_3 = {0xff, 0xff}, + .v_sync_line_aft_pxl_4 = {0xff, 0xff}, + .v_sync_line_aft_pxl_5 = {0xff, 0xff}, + .v_sync_line_aft_pxl_6 = {0xff, 0xff}, + .vact_space_1 = {0xff, 0xff}, + .vact_space_2 = {0xff, 0xff}, + .vact_space_3 = {0xff, 0xff}, + .vact_space_4 = {0xff, 0xff}, + .vact_space_5 = {0xff, 0xff}, + .vact_space_6 = {0xff, 0xff}, + /* other don't care */ }, - { - .pixel_clock = 106500000, - .conf = { - 0x01, 0xd1, 0x2c, 0x12, 0x40, 0x0c, 0x09, 0x08, - 0x84, 0xa0, 0x0a, 0xd9, 0x45, 0xa0, 0xac, 0x80, - 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0x73, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80, - }, + .tg = { + 0x00, /* cmd */ + 0x98, 0x08, /* h_fsz */ + 0x18, 0x01, 0x80, 0x07, /* hact */ + 0x65, 0x04, /* v_fsz */ + 0x01, 0x00, 0x33, 0x02, /* vsync */ + 0x16, 0x00, 0x1c, 0x02, /* vact */ + 0x33, 0x02, /* field_chg */ + 0x49, 0x02, /* vact_st2 */ + 0x00, 0x00, /* vact_st3 */ + 0x00, 0x00, /* vact_st4 */ + 0x01, 0x00, 0x33, 0x02, /* vsync top/bot */ + 0x01, 0x00, 0x33, 0x02, /* field top/bot */ + 0x00, /* 3d FP */ }, - { - .pixel_clock = 108000000, - .conf = { - 0x01, 0x51, 0x2d, 0x15, 0x40, 0x01, 0x00, 0x08, - 0x82, 0x80, 0x0e, 0xd9, 0x45, 0xa0, 0xac, 0x80, - 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0xc7, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80, - }, +}; + +static const struct hdmi_preset_conf hdmi_conf_1080p30 = { + .core = { + .h_blank = {0x18, 0x01}, + .v2_blank = {0x65, 0x04}, + .v1_blank = {0x2d, 0x00}, + .v_line = {0x65, 0x04}, + .h_line = {0x98, 0x08}, + .hsync_pol = {0x00}, + .vsync_pol = {0x00}, + .int_pro_mode = {0x00}, + .v_blank_f0 = {0xff, 0xff}, + .v_blank_f1 = {0xff, 0xff}, + .h_sync_start = {0x56, 0x00}, + .h_sync_end = {0x82, 0x00}, + .v_sync_line_bef_2 = {0x09, 0x00}, + .v_sync_line_bef_1 = {0x04, 0x00}, + .v_sync_line_aft_2 = {0xff, 0xff}, + .v_sync_line_aft_1 = {0xff, 0xff}, + .v_sync_line_aft_pxl_2 = {0xff, 0xff}, + .v_sync_line_aft_pxl_1 = {0xff, 0xff}, + .v_blank_f2 = {0xff, 0xff}, + .v_blank_f3 = {0xff, 0xff}, + .v_blank_f4 = {0xff, 0xff}, + .v_blank_f5 = {0xff, 0xff}, + .v_sync_line_aft_3 = {0xff, 0xff}, + .v_sync_line_aft_4 = {0xff, 0xff}, + .v_sync_line_aft_5 = {0xff, 0xff}, + .v_sync_line_aft_6 = {0xff, 0xff}, + .v_sync_line_aft_pxl_3 = {0xff, 0xff}, + .v_sync_line_aft_pxl_4 = {0xff, 0xff}, + .v_sync_line_aft_pxl_5 = {0xff, 0xff}, + .v_sync_line_aft_pxl_6 = {0xff, 0xff}, + .vact_space_1 = {0xff, 0xff}, + .vact_space_2 = {0xff, 0xff}, + .vact_space_3 = {0xff, 0xff}, + .vact_space_4 = {0xff, 0xff}, + .vact_space_5 = {0xff, 0xff}, + .vact_space_6 = {0xff, 0xff}, + /* other don't care */ }, - { - .pixel_clock = 146250000, - .conf = { - 0x01, 0xd1, 0x3d, 0x15, 0x40, 0x18, 0xfd, 0x08, - 0x83, 0xa0, 0x6e, 0xd9, 0x45, 0xa0, 0xac, 0x80, - 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0x50, 0x25, 0x03, 0x00, 0x00, 0x01, 0x80, - }, + .tg = { + 0x00, /* cmd */ + 0x98, 0x08, /* h_fsz */ + 0x18, 0x01, 0x80, 0x07, /* hact */ + 0x65, 0x04, /* v_fsz */ + 0x01, 0x00, 0x33, 0x02, /* vsync */ + 0x2d, 0x00, 0x38, 0x04, /* vact */ + 0x33, 0x02, /* field_chg */ + 0x48, 0x02, /* vact_st2 */ + 0x00, 0x00, /* vact_st3 */ + 0x00, 0x00, /* vact_st4 */ + 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ + 0x01, 0x00, 0x33, 0x02, /* field top/bot */ + 0x00, /* 3d FP */ }, - { - .pixel_clock = 148500000, - .conf = { - 0x01, 0xd1, 0x1f, 0x00, 0x40, 0x40, 0xf8, 0x08, - 0x81, 0xa0, 0xba, 0xd8, 0x45, 0xa0, 0xac, 0x80, - 0x3c, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, - 0x54, 0x4b, 0x25, 0x03, 0x00, 0x00, 0x01, 0x00, - }, +}; + +static const struct hdmi_preset_conf hdmi_conf_1080p50 = { + .core = { + .h_blank = {0xd0, 0x02}, + .v2_blank = {0x65, 0x04}, + .v1_blank = {0x2d, 0x00}, + .v_line = {0x65, 0x04}, + .h_line = {0x50, 0x0a}, + .hsync_pol = {0x00}, + .vsync_pol = {0x00}, + .int_pro_mode = {0x00}, + .v_blank_f0 = {0xff, 0xff}, + .v_blank_f1 = {0xff, 0xff}, + .h_sync_start = {0x0e, 0x02}, + .h_sync_end = {0x3a, 0x02}, + .v_sync_line_bef_2 = {0x09, 0x00}, + .v_sync_line_bef_1 = {0x04, 0x00}, + .v_sync_line_aft_2 = {0xff, 0xff}, + .v_sync_line_aft_1 = {0xff, 0xff}, + .v_sync_line_aft_pxl_2 = {0xff, 0xff}, + .v_sync_line_aft_pxl_1 = {0xff, 0xff}, + .v_blank_f2 = {0xff, 0xff}, + .v_blank_f3 = {0xff, 0xff}, + .v_blank_f4 = {0xff, 0xff}, + .v_blank_f5 = {0xff, 0xff}, + .v_sync_line_aft_3 = {0xff, 0xff}, + .v_sync_line_aft_4 = {0xff, 0xff}, + .v_sync_line_aft_5 = {0xff, 0xff}, + .v_sync_line_aft_6 = {0xff, 0xff}, + .v_sync_line_aft_pxl_3 = {0xff, 0xff}, + .v_sync_line_aft_pxl_4 = {0xff, 0xff}, + .v_sync_line_aft_pxl_5 = {0xff, 0xff}, + .v_sync_line_aft_pxl_6 = {0xff, 0xff}, + .vact_space_1 = {0xff, 0xff}, + .vact_space_2 = {0xff, 0xff}, + .vact_space_3 = {0xff, 0xff}, + .vact_space_4 = {0xff, 0xff}, + .vact_space_5 = {0xff, 0xff}, + .vact_space_6 = {0xff, 0xff}, + /* other don't care */ + }, + .tg = { + 0x00, /* cmd */ + 0x50, 0x0a, /* h_fsz */ + 0xd0, 0x02, 0x80, 0x07, /* hact */ + 0x65, 0x04, /* v_fsz */ + 0x01, 0x00, 0x33, 0x02, /* vsync */ + 0x2d, 0x00, 0x38, 0x04, /* vact */ + 0x33, 0x02, /* field_chg */ + 0x48, 0x02, /* vact_st2 */ + 0x00, 0x00, /* vact_st3 */ + 0x00, 0x00, /* vact_st4 */ + 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ + 0x01, 0x00, 0x33, 0x02, /* field top/bot */ + 0x00, /* 3d FP */ }, }; +static const struct hdmi_preset_conf hdmi_conf_1080p60 = { + .core = { + .h_blank = {0x18, 0x01}, + .v2_blank = {0x65, 0x04}, + .v1_blank = {0x2d, 0x00}, + .v_line = {0x65, 0x04}, + .h_line = {0x98, 0x08}, + .hsync_pol = {0x00}, + .vsync_pol = {0x00}, + .int_pro_mode = {0x00}, + .v_blank_f0 = {0xff, 0xff}, + .v_blank_f1 = {0xff, 0xff}, + .h_sync_start = {0x56, 0x00}, + .h_sync_end = {0x82, 0x00}, + .v_sync_line_bef_2 = {0x09, 0x00}, + .v_sync_line_bef_1 = {0x04, 0x00}, + .v_sync_line_aft_2 = {0xff, 0xff}, + .v_sync_line_aft_1 = {0xff, 0xff}, + .v_sync_line_aft_pxl_2 = {0xff, 0xff}, + .v_sync_line_aft_pxl_1 = {0xff, 0xff}, + .v_blank_f2 = {0xff, 0xff}, + .v_blank_f3 = {0xff, 0xff}, + .v_blank_f4 = {0xff, 0xff}, + .v_blank_f5 = {0xff, 0xff}, + .v_sync_line_aft_3 = {0xff, 0xff}, + .v_sync_line_aft_4 = {0xff, 0xff}, + .v_sync_line_aft_5 = {0xff, 0xff}, + .v_sync_line_aft_6 = {0xff, 0xff}, + .v_sync_line_aft_pxl_3 = {0xff, 0xff}, + .v_sync_line_aft_pxl_4 = {0xff, 0xff}, + .v_sync_line_aft_pxl_5 = {0xff, 0xff}, + .v_sync_line_aft_pxl_6 = {0xff, 0xff}, + /* other don't care */ + }, + .tg = { + 0x00, /* cmd */ + 0x98, 0x08, /* h_fsz */ + 0x18, 0x01, 0x80, 0x07, /* hact */ + 0x65, 0x04, /* v_fsz */ + 0x01, 0x00, 0x33, 0x02, /* vsync */ + 0x2d, 0x00, 0x38, 0x04, /* vact */ + 0x33, 0x02, /* field_chg */ + 0x48, 0x02, /* vact_st2 */ + 0x00, 0x00, /* vact_st3 */ + 0x00, 0x00, /* vact_st4 */ + 0x01, 0x00, 0x01, 0x00, /* vsync top/bot */ + 0x01, 0x00, 0x33, 0x02, /* field top/bot */ + 0x00, /* 3d FP */ + }, +}; + +static const struct hdmi_conf hdmi_confs[] = { + { 720, 480, 60, false, 3, hdmiphy_conf27_027, &hdmi_conf_480p60 }, + { 1280, 720, 50, false, 19, hdmiphy_conf74_25, &hdmi_conf_720p50 }, + { 1280, 720, 60, false, 4, hdmiphy_conf74_25, &hdmi_conf_720p60 }, + { 1920, 1080, 50, true, 20, hdmiphy_conf74_25, &hdmi_conf_1080i50 }, + { 1920, 1080, 60, true, 5, hdmiphy_conf74_25, &hdmi_conf_1080i60 }, + { 1920, 1080, 30, false, 34, hdmiphy_conf74_176, &hdmi_conf_1080p30 }, + { 1920, 1080, 50, false, 31, hdmiphy_conf148_5, &hdmi_conf_1080p50 }, + { 1920, 1080, 60, false, 16, hdmiphy_conf148_5, &hdmi_conf_1080p60 }, +}; + struct hdmi_infoframe { enum HDMI_PACKET_TYPE type; u8 ver; @@ -889,6 +1275,31 @@ static int hdmi_v13_conf_index(struct drm_display_mode *mode) return -EINVAL; } +static int hdmi_v14_conf_index(struct drm_display_mode *mode) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(hdmi_confs); ++i) + if (hdmi_confs[i].width == mode->hdisplay && + hdmi_confs[i].height == mode->vdisplay && + hdmi_confs[i].vrefresh == mode->vrefresh && + hdmi_confs[i].interlace == + ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? + true : false)) + return i; + + return -EINVAL; +} + +static int hdmi_conf_index(struct hdmi_context *hdata, + struct drm_display_mode *mode) +{ + if (hdata->type == HDMI_TYPE13) + return hdmi_v13_conf_index(mode); + + return hdmi_v14_conf_index(mode); +} + static u8 hdmi_chksum(struct hdmi_context *hdata, u32 start, u8 len, u32 hdr_sum) { @@ -946,7 +1357,7 @@ static void hdmi_reg_infoframe(struct hdmi_context *hdata, if (hdata->type == HDMI_TYPE13) vic = hdmi_v13_confs[hdata->cur_conf].cea_video_id; else - vic = hdata->mode_conf.cea_video_id; + vic = hdmi_confs[hdata->cur_conf].cea_video_id; hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(4), vic); @@ -1023,51 +1434,44 @@ static int hdmi_v13_check_timing(struct fb_videomode *check_timing) return -EINVAL; } -static int hdmi_v14_find_phy_conf(int pixel_clock) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(hdmiphy_v14_configs); i++) { - if (hdmiphy_v14_configs[i].pixel_clock == pixel_clock) - return i; - } - - DRM_DEBUG_KMS("Could not find phy config for %d\n", pixel_clock); - return -EINVAL; -} - static int hdmi_v14_check_timing(struct fb_videomode *check_timing) { int i; - DRM_DEBUG_KMS("mode: xres=%d, yres=%d, refresh=%d, clock=%d, intl=%d\n", + DRM_DEBUG_KMS("valid mode : xres=%d, yres=%d, refresh=%d, intl=%d\n", check_timing->xres, check_timing->yres, - check_timing->refresh, check_timing->pixclock, - (check_timing->vmode & FB_VMODE_INTERLACED) ? - true : false); + check_timing->refresh, (check_timing->vmode & + FB_VMODE_INTERLACED) ? true : false); - for (i = 0; i < ARRAY_SIZE(hdmiphy_v14_configs); i++) - if (hdmiphy_v14_configs[i].pixel_clock == - check_timing->pixclock) - return 0; + for (i = 0; i < ARRAY_SIZE(hdmi_confs); i++) + if (hdmi_confs[i].width == check_timing->xres && + hdmi_confs[i].height == check_timing->yres && + hdmi_confs[i].vrefresh == check_timing->refresh && + hdmi_confs[i].interlace == + ((check_timing->vmode & FB_VMODE_INTERLACED) ? + true : false)) + return 0; + + /* TODO */ return -EINVAL; } -static int hdmi_check_timing(void *ctx, struct fb_videomode *timing) +static int hdmi_check_timing(void *ctx, void *timing) { struct hdmi_context *hdata = ctx; + struct fb_videomode *check_timing = timing; DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", timing->xres, - timing->yres, timing->refresh, - timing->vmode); + DRM_DEBUG_KMS("[%d]x[%d] [%d]Hz [%x]\n", check_timing->xres, + check_timing->yres, check_timing->refresh, + check_timing->vmode); if (hdata->type == HDMI_TYPE13) - return hdmi_v13_check_timing(timing); + return hdmi_v13_check_timing(check_timing); else - return hdmi_v14_check_timing(timing); + return hdmi_v14_check_timing(check_timing); } static void hdmi_set_acr(u32 freq, u8 *acr) @@ -1391,8 +1795,9 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata) static void hdmi_v14_timing_apply(struct hdmi_context *hdata) { - struct hdmi_core_regs *core = &hdata->mode_conf.core; - struct hdmi_tg_regs *tg = &hdata->mode_conf.tg; + const struct hdmi_preset_conf *conf = hdmi_confs[hdata->cur_conf].conf; + const struct hdmi_core_regs *core = &conf->core; + const struct hdmi_tg_regs *tg = &conf->tg; int tries; /* setting core registers */ @@ -1495,39 +1900,39 @@ static void hdmi_v14_timing_apply(struct hdmi_context *hdata) hdmi_reg_writeb(hdata, HDMI_VACT_SPACE_6_1, core->vact_space_6[1]); /* Timing generator registers */ - hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz[0]); - hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz[1]); - hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st[0]); - hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st[1]); - hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz[0]); - hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz[1]); - hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz[0]); - hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz[1]); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync[0]); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync[1]); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2[0]); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2[1]); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st[0]); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st[1]); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz[0]); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz[1]); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg[0]); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg[1]); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2[0]); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2[1]); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3[0]); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3[1]); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4[0]); - hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4[1]); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi[0]); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi[1]); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi[0]); - hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi[1]); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi[0]); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi[1]); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi[0]); - hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi[1]); - hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d[0]); + hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_L, tg->h_fsz_l); + hdmi_reg_writeb(hdata, HDMI_TG_H_FSZ_H, tg->h_fsz_h); + hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_L, tg->hact_st_l); + hdmi_reg_writeb(hdata, HDMI_TG_HACT_ST_H, tg->hact_st_h); + hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_L, tg->hact_sz_l); + hdmi_reg_writeb(hdata, HDMI_TG_HACT_SZ_H, tg->hact_sz_h); + hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_L, tg->v_fsz_l); + hdmi_reg_writeb(hdata, HDMI_TG_V_FSZ_H, tg->v_fsz_h); + hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_L, tg->vsync_l); + hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_H, tg->vsync_h); + hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_L, tg->vsync2_l); + hdmi_reg_writeb(hdata, HDMI_TG_VSYNC2_H, tg->vsync2_h); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_L, tg->vact_st_l); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST_H, tg->vact_st_h); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_L, tg->vact_sz_l); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_SZ_H, tg->vact_sz_h); + hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_L, tg->field_chg_l); + hdmi_reg_writeb(hdata, HDMI_TG_FIELD_CHG_H, tg->field_chg_h); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_L, tg->vact_st2_l); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST2_H, tg->vact_st2_h); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_L, tg->vact_st3_l); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST3_H, tg->vact_st3_h); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_L, tg->vact_st4_l); + hdmi_reg_writeb(hdata, HDMI_TG_VACT_ST4_H, tg->vact_st4_h); + hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_L, tg->vsync_top_hdmi_l); + hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_TOP_HDMI_H, tg->vsync_top_hdmi_h); + hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_L, tg->vsync_bot_hdmi_l); + hdmi_reg_writeb(hdata, HDMI_TG_VSYNC_BOT_HDMI_H, tg->vsync_bot_hdmi_h); + hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_L, tg->field_top_hdmi_l); + hdmi_reg_writeb(hdata, HDMI_TG_FIELD_TOP_HDMI_H, tg->field_top_hdmi_h); + hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_L, tg->field_bot_hdmi_l); + hdmi_reg_writeb(hdata, HDMI_TG_FIELD_BOT_HDMI_H, tg->field_bot_hdmi_h); + hdmi_reg_writeb(hdata, HDMI_TG_3D, tg->tg_3d); /* waiting for HDMIPHY's PLL to get to steady state */ for (tries = 100; tries; --tries) { @@ -1624,17 +2029,10 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata) } /* pixel clock */ - if (hdata->type == HDMI_TYPE13) { + if (hdata->type == HDMI_TYPE13) hdmiphy_data = hdmi_v13_confs[hdata->cur_conf].hdmiphy_data; - } else { - i = hdmi_v14_find_phy_conf(hdata->mode_conf.pixel_clock); - if (i < 0) { - DRM_ERROR("failed to find hdmiphy conf\n"); - return; - } - - hdmiphy_data = hdmiphy_v14_configs[i].conf; - } + else + hdmiphy_data = hdmi_confs[hdata->cur_conf].hdmiphy_data; memcpy(buffer, hdmiphy_data, 32); ret = i2c_master_send(hdata->hdmiphy_port, buffer, 32); @@ -1702,7 +2100,7 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, if (hdata->type == HDMI_TYPE13) index = hdmi_v13_conf_index(adjusted_mode); else - index = hdmi_v14_find_phy_conf(adjusted_mode->clock * 1000); + index = hdmi_v14_conf_index(adjusted_mode); /* just return if user desired mode exists. */ if (index >= 0) @@ -1716,7 +2114,7 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, if (hdata->type == HDMI_TYPE13) index = hdmi_v13_conf_index(m); else - index = hdmi_v14_find_phy_conf(m->clock * 1000); + index = hdmi_v14_conf_index(m); if (index >= 0) { struct drm_mode_object base; @@ -1725,9 +2123,6 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, DRM_INFO("desired mode doesn't exist so\n"); DRM_INFO("use the most suitable mode among modes.\n"); - DRM_DEBUG_KMS("Adjusted Mode: [%d]x[%d] [%d]Hz\n", - m->hdisplay, m->vdisplay, m->vrefresh); - /* preserve display mode header while copying. */ head = adjusted_mode->head; base = adjusted_mode->base; @@ -1739,122 +2134,6 @@ static void hdmi_mode_fixup(void *ctx, struct drm_connector *connector, } } -static void hdmi_set_reg(u8 *reg_pair, int num_bytes, u32 value) -{ - int i; - BUG_ON(num_bytes > 4); - for (i = 0; i < num_bytes; i++) - reg_pair[i] = (value >> (8 * i)) & 0xff; -} - -static void hdmi_v14_mode_set(struct hdmi_context *hdata, - struct drm_display_mode *m) -{ - struct hdmi_core_regs *core = &hdata->mode_conf.core; - struct hdmi_tg_regs *tg = &hdata->mode_conf.tg; - - hdata->mode_conf.cea_video_id = drm_match_cea_mode(m); - - hdata->mode_conf.pixel_clock = m->clock * 1000; - hdmi_set_reg(core->h_blank, 2, m->htotal - m->hdisplay); - hdmi_set_reg(core->v_line, 2, m->vtotal); - hdmi_set_reg(core->h_line, 2, m->htotal); - hdmi_set_reg(core->hsync_pol, 1, - (m->flags & DRM_MODE_FLAG_NHSYNC) ? 1 : 0); - hdmi_set_reg(core->vsync_pol, 1, - (m->flags & DRM_MODE_FLAG_NVSYNC) ? 1 : 0); - hdmi_set_reg(core->int_pro_mode, 1, - (m->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0); - - /* - * Quirk requirement for exynos 5 HDMI IP design, - * 2 pixels less than the actual calculation for hsync_start - * and end. - */ - - /* Following values & calculations differ for different type of modes */ - if (m->flags & DRM_MODE_FLAG_INTERLACE) { - /* Interlaced Mode */ - hdmi_set_reg(core->v_sync_line_bef_2, 2, - (m->vsync_end - m->vdisplay) / 2); - hdmi_set_reg(core->v_sync_line_bef_1, 2, - (m->vsync_start - m->vdisplay) / 2); - hdmi_set_reg(core->v2_blank, 2, m->vtotal / 2); - hdmi_set_reg(core->v1_blank, 2, (m->vtotal - m->vdisplay) / 2); - hdmi_set_reg(core->v_blank_f0, 2, (m->vtotal + - ((m->vsync_end - m->vsync_start) * 4) + 5) / 2); - hdmi_set_reg(core->v_blank_f1, 2, m->vtotal); - hdmi_set_reg(core->v_sync_line_aft_2, 2, (m->vtotal / 2) + 7); - hdmi_set_reg(core->v_sync_line_aft_1, 2, (m->vtotal / 2) + 2); - hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2, - (m->htotal / 2) + (m->hsync_start - m->hdisplay)); - hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2, - (m->htotal / 2) + (m->hsync_start - m->hdisplay)); - hdmi_set_reg(tg->vact_st, 2, (m->vtotal - m->vdisplay) / 2); - hdmi_set_reg(tg->vact_sz, 2, m->vdisplay / 2); - hdmi_set_reg(tg->vact_st2, 2, 0x249);/* Reset value + 1*/ - hdmi_set_reg(tg->vact_st3, 2, 0x0); - hdmi_set_reg(tg->vact_st4, 2, 0x0); - } else { - /* Progressive Mode */ - hdmi_set_reg(core->v_sync_line_bef_2, 2, - m->vsync_end - m->vdisplay); - hdmi_set_reg(core->v_sync_line_bef_1, 2, - m->vsync_start - m->vdisplay); - hdmi_set_reg(core->v2_blank, 2, m->vtotal); - hdmi_set_reg(core->v1_blank, 2, m->vtotal - m->vdisplay); - hdmi_set_reg(core->v_blank_f0, 2, 0xffff); - hdmi_set_reg(core->v_blank_f1, 2, 0xffff); - hdmi_set_reg(core->v_sync_line_aft_2, 2, 0xffff); - hdmi_set_reg(core->v_sync_line_aft_1, 2, 0xffff); - hdmi_set_reg(core->v_sync_line_aft_pxl_2, 2, 0xffff); - hdmi_set_reg(core->v_sync_line_aft_pxl_1, 2, 0xffff); - hdmi_set_reg(tg->vact_st, 2, m->vtotal - m->vdisplay); - hdmi_set_reg(tg->vact_sz, 2, m->vdisplay); - hdmi_set_reg(tg->vact_st2, 2, 0x248); /* Reset value */ - hdmi_set_reg(tg->vact_st3, 2, 0x47b); /* Reset value */ - hdmi_set_reg(tg->vact_st4, 2, 0x6ae); /* Reset value */ - } - - /* Following values & calculations are same irrespective of mode type */ - hdmi_set_reg(core->h_sync_start, 2, m->hsync_start - m->hdisplay - 2); - hdmi_set_reg(core->h_sync_end, 2, m->hsync_end - m->hdisplay - 2); - hdmi_set_reg(core->vact_space_1, 2, 0xffff); - hdmi_set_reg(core->vact_space_2, 2, 0xffff); - hdmi_set_reg(core->vact_space_3, 2, 0xffff); - hdmi_set_reg(core->vact_space_4, 2, 0xffff); - hdmi_set_reg(core->vact_space_5, 2, 0xffff); - hdmi_set_reg(core->vact_space_6, 2, 0xffff); - hdmi_set_reg(core->v_blank_f2, 2, 0xffff); - hdmi_set_reg(core->v_blank_f3, 2, 0xffff); - hdmi_set_reg(core->v_blank_f4, 2, 0xffff); - hdmi_set_reg(core->v_blank_f5, 2, 0xffff); - hdmi_set_reg(core->v_sync_line_aft_3, 2, 0xffff); - hdmi_set_reg(core->v_sync_line_aft_4, 2, 0xffff); - hdmi_set_reg(core->v_sync_line_aft_5, 2, 0xffff); - hdmi_set_reg(core->v_sync_line_aft_6, 2, 0xffff); - hdmi_set_reg(core->v_sync_line_aft_pxl_3, 2, 0xffff); - hdmi_set_reg(core->v_sync_line_aft_pxl_4, 2, 0xffff); - hdmi_set_reg(core->v_sync_line_aft_pxl_5, 2, 0xffff); - hdmi_set_reg(core->v_sync_line_aft_pxl_6, 2, 0xffff); - - /* Timing generator registers */ - hdmi_set_reg(tg->cmd, 1, 0x0); - hdmi_set_reg(tg->h_fsz, 2, m->htotal); - hdmi_set_reg(tg->hact_st, 2, m->htotal - m->hdisplay); - hdmi_set_reg(tg->hact_sz, 2, m->hdisplay); - hdmi_set_reg(tg->v_fsz, 2, m->vtotal); - hdmi_set_reg(tg->vsync, 2, 0x1); - hdmi_set_reg(tg->vsync2, 2, 0x233); /* Reset value */ - hdmi_set_reg(tg->field_chg, 2, 0x233); /* Reset value */ - hdmi_set_reg(tg->vsync_top_hdmi, 2, 0x1); /* Reset value */ - hdmi_set_reg(tg->vsync_bot_hdmi, 2, 0x233); /* Reset value */ - hdmi_set_reg(tg->field_top_hdmi, 2, 0x1); /* Reset value */ - hdmi_set_reg(tg->field_bot_hdmi, 2, 0x233); /* Reset value */ - hdmi_set_reg(tg->tg_3d, 1, 0x0); - -} - static void hdmi_mode_set(void *ctx, void *mode) { struct hdmi_context *hdata = ctx; @@ -1862,15 +2141,11 @@ static void hdmi_mode_set(void *ctx, void *mode) DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); - if (hdata->type == HDMI_TYPE13) { - conf_idx = hdmi_v13_conf_index(mode); - if (conf_idx >= 0) - hdata->cur_conf = conf_idx; - else - DRM_DEBUG_KMS("not supported mode\n"); - } else { - hdmi_v14_mode_set(hdata, mode); - } + conf_idx = hdmi_conf_index(hdata, mode); + if (conf_idx >= 0) + hdata->cur_conf = conf_idx; + else + DRM_DEBUG_KMS("not supported mode\n"); } static void hdmi_get_max_resol(void *ctx, unsigned int *width, diff --git a/trunk/drivers/gpu/drm/exynos/exynos_mixer.c b/trunk/drivers/gpu/drm/exynos/exynos_mixer.c index e919aba29b3d..c414584bfbae 100644 --- a/trunk/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/trunk/drivers/gpu/drm/exynos/exynos_mixer.c @@ -284,13 +284,13 @@ static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height) MXR_CFG_SCAN_PROGRASSIVE); /* choosing between porper HD and SD mode */ - if (height <= 480) + if (height == 480) val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD; - else if (height <= 576) + else if (height == 576) val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD; - else if (height <= 720) + else if (height == 720) val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD; - else if (height <= 1080) + else if (height == 1080) val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD; else val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD; @@ -818,29 +818,6 @@ static void mixer_win_disable(void *ctx, int win) mixer_ctx->win_data[win].enabled = false; } -int mixer_check_timing(void *ctx, struct fb_videomode *timing) -{ - struct mixer_context *mixer_ctx = ctx; - u32 w, h; - - w = timing->xres; - h = timing->yres; - - DRM_DEBUG_KMS("%s : xres=%d, yres=%d, refresh=%d, intl=%d\n", - __func__, timing->xres, timing->yres, - timing->refresh, (timing->vmode & - FB_VMODE_INTERLACED) ? true : false); - - if (mixer_ctx->mxr_ver == MXR_VER_0_0_0_16) - return 0; - - if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) || - (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) || - (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080)) - return 0; - - return -EINVAL; -} static void mixer_wait_for_vblank(void *ctx) { struct mixer_context *mixer_ctx = ctx; @@ -978,9 +955,6 @@ static struct exynos_mixer_ops mixer_ops = { .win_mode_set = mixer_win_mode_set, .win_commit = mixer_win_commit, .win_disable = mixer_win_disable, - - /* display */ - .check_timing = mixer_check_timing, }; static irqreturn_t mixer_irq_handler(int irq, void *arg) diff --git a/trunk/drivers/gpu/drm/gma500/framebuffer.c b/trunk/drivers/gpu/drm/gma500/framebuffer.c index 2590cac84257..c1ef37e2efdf 100644 --- a/trunk/drivers/gpu/drm/gma500/framebuffer.c +++ b/trunk/drivers/gpu/drm/gma500/framebuffer.c @@ -545,7 +545,9 @@ static int psbfb_probe(struct drm_fb_helper *helper, struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper; struct drm_device *dev = psb_fbdev->psb_fb_helper.dev; struct drm_psb_private *dev_priv = dev->dev_private; + int new_fb = 0; int bytespp; + int ret; bytespp = sizes->surface_bpp / 8; if (bytespp == 3) /* no 24bit packed */ @@ -560,7 +562,13 @@ static int psbfb_probe(struct drm_fb_helper *helper, sizes->surface_depth = 16; } - return psbfb_create(psb_fbdev, sizes); + if (!helper->fb) { + ret = psbfb_create(psb_fbdev, sizes); + if (ret) + return ret; + new_fb = 1; + } + return new_fb; } static struct drm_fb_helper_funcs psb_fb_helper_funcs = { @@ -608,10 +616,6 @@ int psb_fbdev_init(struct drm_device *dev) INTELFB_CONN_LIMIT); drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper); - - /* disable all the possible outputs/crtcs before entering KMS mode */ - drm_helper_disable_unused_functions(dev); - drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32); return 0; } diff --git a/trunk/drivers/gpu/drm/gma500/psb_intel_display.c b/trunk/drivers/gpu/drm/gma500/psb_intel_display.c index 9edb1902a096..8033526bb53b 100644 --- a/trunk/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/trunk/drivers/gpu/drm/gma500/psb_intel_display.c @@ -85,14 +85,14 @@ struct psb_intel_limit_t { #define I9XX_DOT_MAX 400000 #define I9XX_VCO_MIN 1400000 #define I9XX_VCO_MAX 2800000 -#define I9XX_N_MIN 1 -#define I9XX_N_MAX 6 +#define I9XX_N_MIN 3 +#define I9XX_N_MAX 8 #define I9XX_M_MIN 70 #define I9XX_M_MAX 120 -#define I9XX_M1_MIN 8 -#define I9XX_M1_MAX 18 -#define I9XX_M2_MIN 3 -#define I9XX_M2_MAX 7 +#define I9XX_M1_MIN 10 +#define I9XX_M1_MAX 20 +#define I9XX_M2_MIN 5 +#define I9XX_M2_MAX 9 #define I9XX_P_SDVO_DAC_MIN 5 #define I9XX_P_SDVO_DAC_MAX 80 #define I9XX_P_LVDS_MIN 7 diff --git a/trunk/drivers/gpu/drm/i2c/Kconfig b/trunk/drivers/gpu/drm/i2c/Kconfig index 4d341db462a2..16118363509a 100644 --- a/trunk/drivers/gpu/drm/i2c/Kconfig +++ b/trunk/drivers/gpu/drm/i2c/Kconfig @@ -19,10 +19,4 @@ config DRM_I2C_SIL164 when used in pairs) TMDS transmitters, used in some nVidia video cards. -config DRM_I2C_NXP_TDA998X - tristate "NXP Semiconductors TDA998X HDMI encoder" - default m if DRM_TILCDC - help - Support for NXP Semiconductors TDA998X HDMI encoders. - endmenu diff --git a/trunk/drivers/gpu/drm/i2c/Makefile b/trunk/drivers/gpu/drm/i2c/Makefile index 43aa33baebed..92862563e7ee 100644 --- a/trunk/drivers/gpu/drm/i2c/Makefile +++ b/trunk/drivers/gpu/drm/i2c/Makefile @@ -5,6 +5,3 @@ obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o sil164-y := sil164_drv.o obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o - -tda998x-y := tda998x_drv.o -obj-$(CONFIG_DRM_I2C_NXP_TDA998X) += tda998x.o diff --git a/trunk/drivers/gpu/drm/i2c/tda998x_drv.c b/trunk/drivers/gpu/drm/i2c/tda998x_drv.c deleted file mode 100644 index e68b58a1aaf9..000000000000 --- a/trunk/drivers/gpu/drm/i2c/tda998x_drv.c +++ /dev/null @@ -1,906 +0,0 @@ -/* - * Copyright (C) 2012 Texas Instruments - * Author: Rob Clark - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - - - -#include - -#include -#include -#include -#include - - -#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) - -struct tda998x_priv { - struct i2c_client *cec; - uint16_t rev; - uint8_t current_page; - int dpms; -}; - -#define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv) - -/* The TDA9988 series of devices use a paged register scheme.. to simplify - * things we encode the page # in upper bits of the register #. To read/ - * write a given register, we need to make sure CURPAGE register is set - * appropriately. Which implies reads/writes are not atomic. Fun! - */ - -#define REG(page, addr) (((page) << 8) | (addr)) -#define REG2ADDR(reg) ((reg) & 0xff) -#define REG2PAGE(reg) (((reg) >> 8) & 0xff) - -#define REG_CURPAGE 0xff /* write */ - - -/* Page 00h: General Control */ -#define REG_VERSION_LSB REG(0x00, 0x00) /* read */ -#define REG_MAIN_CNTRL0 REG(0x00, 0x01) /* read/write */ -# define MAIN_CNTRL0_SR (1 << 0) -# define MAIN_CNTRL0_DECS (1 << 1) -# define MAIN_CNTRL0_DEHS (1 << 2) -# define MAIN_CNTRL0_CECS (1 << 3) -# define MAIN_CNTRL0_CEHS (1 << 4) -# define MAIN_CNTRL0_SCALER (1 << 7) -#define REG_VERSION_MSB REG(0x00, 0x02) /* read */ -#define REG_SOFTRESET REG(0x00, 0x0a) /* write */ -# define SOFTRESET_AUDIO (1 << 0) -# define SOFTRESET_I2C_MASTER (1 << 1) -#define REG_DDC_DISABLE REG(0x00, 0x0b) /* read/write */ -#define REG_CCLK_ON REG(0x00, 0x0c) /* read/write */ -#define REG_I2C_MASTER REG(0x00, 0x0d) /* read/write */ -# define I2C_MASTER_DIS_MM (1 << 0) -# define I2C_MASTER_DIS_FILT (1 << 1) -# define I2C_MASTER_APP_STRT_LAT (1 << 2) -#define REG_INT_FLAGS_0 REG(0x00, 0x0f) /* read/write */ -#define REG_INT_FLAGS_1 REG(0x00, 0x10) /* read/write */ -#define REG_INT_FLAGS_2 REG(0x00, 0x11) /* read/write */ -# define INT_FLAGS_2_EDID_BLK_RD (1 << 1) -#define REG_ENA_VP_0 REG(0x00, 0x18) /* read/write */ -#define REG_ENA_VP_1 REG(0x00, 0x19) /* read/write */ -#define REG_ENA_VP_2 REG(0x00, 0x1a) /* read/write */ -#define REG_ENA_AP REG(0x00, 0x1e) /* read/write */ -#define REG_VIP_CNTRL_0 REG(0x00, 0x20) /* write */ -# define VIP_CNTRL_0_MIRR_A (1 << 7) -# define VIP_CNTRL_0_SWAP_A(x) (((x) & 7) << 4) -# define VIP_CNTRL_0_MIRR_B (1 << 3) -# define VIP_CNTRL_0_SWAP_B(x) (((x) & 7) << 0) -#define REG_VIP_CNTRL_1 REG(0x00, 0x21) /* write */ -# define VIP_CNTRL_1_MIRR_C (1 << 7) -# define VIP_CNTRL_1_SWAP_C(x) (((x) & 7) << 4) -# define VIP_CNTRL_1_MIRR_D (1 << 3) -# define VIP_CNTRL_1_SWAP_D(x) (((x) & 7) << 0) -#define REG_VIP_CNTRL_2 REG(0x00, 0x22) /* write */ -# define VIP_CNTRL_2_MIRR_E (1 << 7) -# define VIP_CNTRL_2_SWAP_E(x) (((x) & 7) << 4) -# define VIP_CNTRL_2_MIRR_F (1 << 3) -# define VIP_CNTRL_2_SWAP_F(x) (((x) & 7) << 0) -#define REG_VIP_CNTRL_3 REG(0x00, 0x23) /* write */ -# define VIP_CNTRL_3_X_TGL (1 << 0) -# define VIP_CNTRL_3_H_TGL (1 << 1) -# define VIP_CNTRL_3_V_TGL (1 << 2) -# define VIP_CNTRL_3_EMB (1 << 3) -# define VIP_CNTRL_3_SYNC_DE (1 << 4) -# define VIP_CNTRL_3_SYNC_HS (1 << 5) -# define VIP_CNTRL_3_DE_INT (1 << 6) -# define VIP_CNTRL_3_EDGE (1 << 7) -#define REG_VIP_CNTRL_4 REG(0x00, 0x24) /* write */ -# define VIP_CNTRL_4_BLC(x) (((x) & 3) << 0) -# define VIP_CNTRL_4_BLANKIT(x) (((x) & 3) << 2) -# define VIP_CNTRL_4_CCIR656 (1 << 4) -# define VIP_CNTRL_4_656_ALT (1 << 5) -# define VIP_CNTRL_4_TST_656 (1 << 6) -# define VIP_CNTRL_4_TST_PAT (1 << 7) -#define REG_VIP_CNTRL_5 REG(0x00, 0x25) /* write */ -# define VIP_CNTRL_5_CKCASE (1 << 0) -# define VIP_CNTRL_5_SP_CNT(x) (((x) & 3) << 1) -#define REG_MAT_CONTRL REG(0x00, 0x80) /* write */ -# define MAT_CONTRL_MAT_SC(x) (((x) & 3) << 0) -# define MAT_CONTRL_MAT_BP (1 << 2) -#define REG_VIDFORMAT REG(0x00, 0xa0) /* write */ -#define REG_REFPIX_MSB REG(0x00, 0xa1) /* write */ -#define REG_REFPIX_LSB REG(0x00, 0xa2) /* write */ -#define REG_REFLINE_MSB REG(0x00, 0xa3) /* write */ -#define REG_REFLINE_LSB REG(0x00, 0xa4) /* write */ -#define REG_NPIX_MSB REG(0x00, 0xa5) /* write */ -#define REG_NPIX_LSB REG(0x00, 0xa6) /* write */ -#define REG_NLINE_MSB REG(0x00, 0xa7) /* write */ -#define REG_NLINE_LSB REG(0x00, 0xa8) /* write */ -#define REG_VS_LINE_STRT_1_MSB REG(0x00, 0xa9) /* write */ -#define REG_VS_LINE_STRT_1_LSB REG(0x00, 0xaa) /* write */ -#define REG_VS_PIX_STRT_1_MSB REG(0x00, 0xab) /* write */ -#define REG_VS_PIX_STRT_1_LSB REG(0x00, 0xac) /* write */ -#define REG_VS_LINE_END_1_MSB REG(0x00, 0xad) /* write */ -#define REG_VS_LINE_END_1_LSB REG(0x00, 0xae) /* write */ -#define REG_VS_PIX_END_1_MSB REG(0x00, 0xaf) /* write */ -#define REG_VS_PIX_END_1_LSB REG(0x00, 0xb0) /* write */ -#define REG_VS_PIX_STRT_2_MSB REG(0x00, 0xb3) /* write */ -#define REG_VS_PIX_STRT_2_LSB REG(0x00, 0xb4) /* write */ -#define REG_VS_PIX_END_2_MSB REG(0x00, 0xb7) /* write */ -#define REG_VS_PIX_END_2_LSB REG(0x00, 0xb8) /* write */ -#define REG_HS_PIX_START_MSB REG(0x00, 0xb9) /* write */ -#define REG_HS_PIX_START_LSB REG(0x00, 0xba) /* write */ -#define REG_HS_PIX_STOP_MSB REG(0x00, 0xbb) /* write */ -#define REG_HS_PIX_STOP_LSB REG(0x00, 0xbc) /* write */ -#define REG_VWIN_START_1_MSB REG(0x00, 0xbd) /* write */ -#define REG_VWIN_START_1_LSB REG(0x00, 0xbe) /* write */ -#define REG_VWIN_END_1_MSB REG(0x00, 0xbf) /* write */ -#define REG_VWIN_END_1_LSB REG(0x00, 0xc0) /* write */ -#define REG_DE_START_MSB REG(0x00, 0xc5) /* write */ -#define REG_DE_START_LSB REG(0x00, 0xc6) /* write */ -#define REG_DE_STOP_MSB REG(0x00, 0xc7) /* write */ -#define REG_DE_STOP_LSB REG(0x00, 0xc8) /* write */ -#define REG_TBG_CNTRL_0 REG(0x00, 0xca) /* write */ -# define TBG_CNTRL_0_FRAME_DIS (1 << 5) -# define TBG_CNTRL_0_SYNC_MTHD (1 << 6) -# define TBG_CNTRL_0_SYNC_ONCE (1 << 7) -#define REG_TBG_CNTRL_1 REG(0x00, 0xcb) /* write */ -# define TBG_CNTRL_1_VH_TGL_0 (1 << 0) -# define TBG_CNTRL_1_VH_TGL_1 (1 << 1) -# define TBG_CNTRL_1_VH_TGL_2 (1 << 2) -# define TBG_CNTRL_1_VHX_EXT_DE (1 << 3) -# define TBG_CNTRL_1_VHX_EXT_HS (1 << 4) -# define TBG_CNTRL_1_VHX_EXT_VS (1 << 5) -# define TBG_CNTRL_1_DWIN_DIS (1 << 6) -#define REG_ENABLE_SPACE REG(0x00, 0xd6) /* write */ -#define REG_HVF_CNTRL_0 REG(0x00, 0xe4) /* write */ -# define HVF_CNTRL_0_SM (1 << 7) -# define HVF_CNTRL_0_RWB (1 << 6) -# define HVF_CNTRL_0_PREFIL(x) (((x) & 3) << 2) -# define HVF_CNTRL_0_INTPOL(x) (((x) & 3) << 0) -#define REG_HVF_CNTRL_1 REG(0x00, 0xe5) /* write */ -# define HVF_CNTRL_1_FOR (1 << 0) -# define HVF_CNTRL_1_YUVBLK (1 << 1) -# define HVF_CNTRL_1_VQR(x) (((x) & 3) << 2) -# define HVF_CNTRL_1_PAD(x) (((x) & 3) << 4) -# define HVF_CNTRL_1_SEMI_PLANAR (1 << 6) -#define REG_RPT_CNTRL REG(0x00, 0xf0) /* write */ - - -/* Page 02h: PLL settings */ -#define REG_PLL_SERIAL_1 REG(0x02, 0x00) /* read/write */ -# define PLL_SERIAL_1_SRL_FDN (1 << 0) -# define PLL_SERIAL_1_SRL_IZ(x) (((x) & 3) << 1) -# define PLL_SERIAL_1_SRL_MAN_IZ (1 << 6) -#define REG_PLL_SERIAL_2 REG(0x02, 0x01) /* read/write */ -# define PLL_SERIAL_2_SRL_NOSC(x) (((x) & 3) << 0) -# define PLL_SERIAL_2_SRL_PR(x) (((x) & 0xf) << 4) -#define REG_PLL_SERIAL_3 REG(0x02, 0x02) /* read/write */ -# define PLL_SERIAL_3_SRL_CCIR (1 << 0) -# define PLL_SERIAL_3_SRL_DE (1 << 2) -# define PLL_SERIAL_3_SRL_PXIN_SEL (1 << 4) -#define REG_SERIALIZER REG(0x02, 0x03) /* read/write */ -#define REG_BUFFER_OUT REG(0x02, 0x04) /* read/write */ -#define REG_PLL_SCG1 REG(0x02, 0x05) /* read/write */ -#define REG_PLL_SCG2 REG(0x02, 0x06) /* read/write */ -#define REG_PLL_SCGN1 REG(0x02, 0x07) /* read/write */ -#define REG_PLL_SCGN2 REG(0x02, 0x08) /* read/write */ -#define REG_PLL_SCGR1 REG(0x02, 0x09) /* read/write */ -#define REG_PLL_SCGR2 REG(0x02, 0x0a) /* read/write */ -#define REG_AUDIO_DIV REG(0x02, 0x0e) /* read/write */ -#define REG_SEL_CLK REG(0x02, 0x11) /* read/write */ -# define SEL_CLK_SEL_CLK1 (1 << 0) -# define SEL_CLK_SEL_VRF_CLK(x) (((x) & 3) << 1) -# define SEL_CLK_ENA_SC_CLK (1 << 3) -#define REG_ANA_GENERAL REG(0x02, 0x12) /* read/write */ - - -/* Page 09h: EDID Control */ -#define REG_EDID_DATA_0 REG(0x09, 0x00) /* read */ -/* next 127 successive registers are the EDID block */ -#define REG_EDID_CTRL REG(0x09, 0xfa) /* read/write */ -#define REG_DDC_ADDR REG(0x09, 0xfb) /* read/write */ -#define REG_DDC_OFFS REG(0x09, 0xfc) /* read/write */ -#define REG_DDC_SEGM_ADDR REG(0x09, 0xfd) /* read/write */ -#define REG_DDC_SEGM REG(0x09, 0xfe) /* read/write */ - - -/* Page 10h: information frames and packets */ - - -/* Page 11h: audio settings and content info packets */ -#define REG_AIP_CNTRL_0 REG(0x11, 0x00) /* read/write */ -# define AIP_CNTRL_0_RST_FIFO (1 << 0) -# define AIP_CNTRL_0_SWAP (1 << 1) -# define AIP_CNTRL_0_LAYOUT (1 << 2) -# define AIP_CNTRL_0_ACR_MAN (1 << 5) -# define AIP_CNTRL_0_RST_CTS (1 << 6) -#define REG_ENC_CNTRL REG(0x11, 0x0d) /* read/write */ -# define ENC_CNTRL_RST_ENC (1 << 0) -# define ENC_CNTRL_RST_SEL (1 << 1) -# define ENC_CNTRL_CTL_CODE(x) (((x) & 3) << 2) - - -/* Page 12h: HDCP and OTP */ -#define REG_TX3 REG(0x12, 0x9a) /* read/write */ -#define REG_TX33 REG(0x12, 0xb8) /* read/write */ -# define TX33_HDMI (1 << 1) - - -/* Page 13h: Gamut related metadata packets */ - - - -/* CEC registers: (not paged) - */ -#define REG_CEC_FRO_IM_CLK_CTRL 0xfb /* read/write */ -# define CEC_FRO_IM_CLK_CTRL_GHOST_DIS (1 << 7) -# define CEC_FRO_IM_CLK_CTRL_ENA_OTP (1 << 6) -# define CEC_FRO_IM_CLK_CTRL_IMCLK_SEL (1 << 1) -# define CEC_FRO_IM_CLK_CTRL_FRO_DIV (1 << 0) -#define REG_CEC_RXSHPDLEV 0xfe /* read */ -# define CEC_RXSHPDLEV_RXSENS (1 << 0) -# define CEC_RXSHPDLEV_HPD (1 << 1) - -#define REG_CEC_ENAMODS 0xff /* read/write */ -# define CEC_ENAMODS_DIS_FRO (1 << 6) -# define CEC_ENAMODS_DIS_CCLK (1 << 5) -# define CEC_ENAMODS_EN_RXSENS (1 << 2) -# define CEC_ENAMODS_EN_HDMI (1 << 1) -# define CEC_ENAMODS_EN_CEC (1 << 0) - - -/* Device versions: */ -#define TDA9989N2 0x0101 -#define TDA19989 0x0201 -#define TDA19989N2 0x0202 -#define TDA19988 0x0301 - -static void -cec_write(struct drm_encoder *encoder, uint16_t addr, uint8_t val) -{ - struct i2c_client *client = to_tda998x_priv(encoder)->cec; - uint8_t buf[] = {addr, val}; - int ret; - - ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); - if (ret < 0) - dev_err(&client->dev, "Error %d writing to cec:0x%x\n", ret, addr); -} - -static uint8_t -cec_read(struct drm_encoder *encoder, uint8_t addr) -{ - struct i2c_client *client = to_tda998x_priv(encoder)->cec; - uint8_t val; - int ret; - - ret = i2c_master_send(client, &addr, sizeof(addr)); - if (ret < 0) - goto fail; - - ret = i2c_master_recv(client, &val, sizeof(val)); - if (ret < 0) - goto fail; - - return val; - -fail: - dev_err(&client->dev, "Error %d reading from cec:0x%x\n", ret, addr); - return 0; -} - -static void -set_page(struct drm_encoder *encoder, uint16_t reg) -{ - struct tda998x_priv *priv = to_tda998x_priv(encoder); - - if (REG2PAGE(reg) != priv->current_page) { - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); - uint8_t buf[] = { - REG_CURPAGE, REG2PAGE(reg) - }; - int ret = i2c_master_send(client, buf, sizeof(buf)); - if (ret < 0) - dev_err(&client->dev, "Error %d writing to REG_CURPAGE\n", ret); - - priv->current_page = REG2PAGE(reg); - } -} - -static int -reg_read_range(struct drm_encoder *encoder, uint16_t reg, char *buf, int cnt) -{ - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); - uint8_t addr = REG2ADDR(reg); - int ret; - - set_page(encoder, reg); - - ret = i2c_master_send(client, &addr, sizeof(addr)); - if (ret < 0) - goto fail; - - ret = i2c_master_recv(client, buf, cnt); - if (ret < 0) - goto fail; - - return ret; - -fail: - dev_err(&client->dev, "Error %d reading from 0x%x\n", ret, reg); - return ret; -} - -static uint8_t -reg_read(struct drm_encoder *encoder, uint16_t reg) -{ - uint8_t val = 0; - reg_read_range(encoder, reg, &val, sizeof(val)); - return val; -} - -static void -reg_write(struct drm_encoder *encoder, uint16_t reg, uint8_t val) -{ - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); - uint8_t buf[] = {REG2ADDR(reg), val}; - int ret; - - set_page(encoder, reg); - - ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); - if (ret < 0) - dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg); -} - -static void -reg_write16(struct drm_encoder *encoder, uint16_t reg, uint16_t val) -{ - struct i2c_client *client = drm_i2c_encoder_get_client(encoder); - uint8_t buf[] = {REG2ADDR(reg), val >> 8, val}; - int ret; - - set_page(encoder, reg); - - ret = i2c_master_send(client, buf, ARRAY_SIZE(buf)); - if (ret < 0) - dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg); -} - -static void -reg_set(struct drm_encoder *encoder, uint16_t reg, uint8_t val) -{ - reg_write(encoder, reg, reg_read(encoder, reg) | val); -} - -static void -reg_clear(struct drm_encoder *encoder, uint16_t reg, uint8_t val) -{ - reg_write(encoder, reg, reg_read(encoder, reg) & ~val); -} - -static void -tda998x_reset(struct drm_encoder *encoder) -{ - /* reset audio and i2c master: */ - reg_set(encoder, REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER); - msleep(50); - reg_clear(encoder, REG_SOFTRESET, SOFTRESET_AUDIO | SOFTRESET_I2C_MASTER); - msleep(50); - - /* reset transmitter: */ - reg_set(encoder, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR); - reg_clear(encoder, REG_MAIN_CNTRL0, MAIN_CNTRL0_SR); - - /* PLL registers common configuration */ - reg_write(encoder, REG_PLL_SERIAL_1, 0x00); - reg_write(encoder, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(1)); - reg_write(encoder, REG_PLL_SERIAL_3, 0x00); - reg_write(encoder, REG_SERIALIZER, 0x00); - reg_write(encoder, REG_BUFFER_OUT, 0x00); - reg_write(encoder, REG_PLL_SCG1, 0x00); - reg_write(encoder, REG_AUDIO_DIV, 0x03); - reg_write(encoder, REG_SEL_CLK, SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK); - reg_write(encoder, REG_PLL_SCGN1, 0xfa); - reg_write(encoder, REG_PLL_SCGN2, 0x00); - reg_write(encoder, REG_PLL_SCGR1, 0x5b); - reg_write(encoder, REG_PLL_SCGR2, 0x00); - reg_write(encoder, REG_PLL_SCG2, 0x10); -} - -/* DRM encoder functions */ - -static void -tda998x_encoder_set_config(struct drm_encoder *encoder, void *params) -{ -} - -static void -tda998x_encoder_dpms(struct drm_encoder *encoder, int mode) -{ - struct tda998x_priv *priv = to_tda998x_priv(encoder); - - /* we only care about on or off: */ - if (mode != DRM_MODE_DPMS_ON) - mode = DRM_MODE_DPMS_OFF; - - if (mode == priv->dpms) - return; - - switch (mode) { - case DRM_MODE_DPMS_ON: - /* enable audio and video ports */ - reg_write(encoder, REG_ENA_AP, 0xff); - reg_write(encoder, REG_ENA_VP_0, 0xff); - reg_write(encoder, REG_ENA_VP_1, 0xff); - reg_write(encoder, REG_ENA_VP_2, 0xff); - /* set muxing after enabling ports: */ - reg_write(encoder, REG_VIP_CNTRL_0, - VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3)); - reg_write(encoder, REG_VIP_CNTRL_1, - VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1)); - reg_write(encoder, REG_VIP_CNTRL_2, - VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5)); - break; - case DRM_MODE_DPMS_OFF: - /* disable audio and video ports */ - reg_write(encoder, REG_ENA_AP, 0x00); - reg_write(encoder, REG_ENA_VP_0, 0x00); - reg_write(encoder, REG_ENA_VP_1, 0x00); - reg_write(encoder, REG_ENA_VP_2, 0x00); - break; - } - - priv->dpms = mode; -} - -static void -tda998x_encoder_save(struct drm_encoder *encoder) -{ - DBG(""); -} - -static void -tda998x_encoder_restore(struct drm_encoder *encoder) -{ - DBG(""); -} - -static bool -tda998x_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - -static int -tda998x_encoder_mode_valid(struct drm_encoder *encoder, - struct drm_display_mode *mode) -{ - return MODE_OK; -} - -static void -tda998x_encoder_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct tda998x_priv *priv = to_tda998x_priv(encoder); - uint16_t hs_start, hs_end, line_start, line_end; - uint16_t vwin_start, vwin_end, de_start, de_end; - uint16_t ref_pix, ref_line, pix_start2; - uint8_t reg, div, rep; - - hs_start = mode->hsync_start - mode->hdisplay; - hs_end = mode->hsync_end - mode->hdisplay; - line_start = 1; - line_end = 1 + mode->vsync_end - mode->vsync_start; - vwin_start = mode->vtotal - mode->vsync_start; - vwin_end = vwin_start + mode->vdisplay; - de_start = mode->htotal - mode->hdisplay; - de_end = mode->htotal; - - pix_start2 = 0; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - pix_start2 = (mode->htotal / 2) + hs_start; - - /* TODO how is this value calculated? It is 2 for all common - * formats in the tables in out of tree nxp driver (assuming - * I've properly deciphered their byzantine table system) - */ - ref_line = 2; - - /* this might changes for other color formats from the CRTC: */ - ref_pix = 3 + hs_start; - - div = 148500 / mode->clock; - - DBG("clock=%d, div=%u", mode->clock, div); - DBG("hs_start=%u, hs_end=%u, line_start=%u, line_end=%u", - hs_start, hs_end, line_start, line_end); - DBG("vwin_start=%u, vwin_end=%u, de_start=%u, de_end=%u", - vwin_start, vwin_end, de_start, de_end); - DBG("ref_line=%u, ref_pix=%u, pix_start2=%u", - ref_line, ref_pix, pix_start2); - - /* mute the audio FIFO: */ - reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO); - - /* set HDMI HDCP mode off: */ - reg_set(encoder, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS); - reg_clear(encoder, REG_TX33, TX33_HDMI); - - reg_write(encoder, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(0)); - /* no pre-filter or interpolator: */ - reg_write(encoder, REG_HVF_CNTRL_0, HVF_CNTRL_0_PREFIL(0) | - HVF_CNTRL_0_INTPOL(0)); - reg_write(encoder, REG_VIP_CNTRL_5, VIP_CNTRL_5_SP_CNT(0)); - reg_write(encoder, REG_VIP_CNTRL_4, VIP_CNTRL_4_BLANKIT(0) | - VIP_CNTRL_4_BLC(0)); - reg_clear(encoder, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_CCIR); - - reg_clear(encoder, REG_PLL_SERIAL_1, PLL_SERIAL_1_SRL_MAN_IZ); - reg_clear(encoder, REG_PLL_SERIAL_3, PLL_SERIAL_3_SRL_DE); - reg_write(encoder, REG_SERIALIZER, 0); - reg_write(encoder, REG_HVF_CNTRL_1, HVF_CNTRL_1_VQR(0)); - - /* TODO enable pixel repeat for pixel rates less than 25Msamp/s */ - rep = 0; - reg_write(encoder, REG_RPT_CNTRL, 0); - reg_write(encoder, REG_SEL_CLK, SEL_CLK_SEL_VRF_CLK(0) | - SEL_CLK_SEL_CLK1 | SEL_CLK_ENA_SC_CLK); - - reg_write(encoder, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) | - PLL_SERIAL_2_SRL_PR(rep)); - - reg_write16(encoder, REG_VS_PIX_STRT_2_MSB, pix_start2); - reg_write16(encoder, REG_VS_PIX_END_2_MSB, pix_start2); - - /* set color matrix bypass flag: */ - reg_set(encoder, REG_MAT_CONTRL, MAT_CONTRL_MAT_BP); - - /* set BIAS tmds value: */ - reg_write(encoder, REG_ANA_GENERAL, 0x09); - - reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_MTHD); - - reg_write(encoder, REG_VIP_CNTRL_3, 0); - reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_SYNC_HS); - if (mode->flags & DRM_MODE_FLAG_NVSYNC) - reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_V_TGL); - - if (mode->flags & DRM_MODE_FLAG_NHSYNC) - reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_H_TGL); - - reg_write(encoder, REG_VIDFORMAT, 0x00); - reg_write16(encoder, REG_NPIX_MSB, mode->hdisplay - 1); - reg_write16(encoder, REG_NLINE_MSB, mode->vdisplay - 1); - reg_write16(encoder, REG_VS_LINE_STRT_1_MSB, line_start); - reg_write16(encoder, REG_VS_LINE_END_1_MSB, line_end); - reg_write16(encoder, REG_VS_PIX_STRT_1_MSB, hs_start); - reg_write16(encoder, REG_VS_PIX_END_1_MSB, hs_start); - reg_write16(encoder, REG_HS_PIX_START_MSB, hs_start); - reg_write16(encoder, REG_HS_PIX_STOP_MSB, hs_end); - reg_write16(encoder, REG_VWIN_START_1_MSB, vwin_start); - reg_write16(encoder, REG_VWIN_END_1_MSB, vwin_end); - reg_write16(encoder, REG_DE_START_MSB, de_start); - reg_write16(encoder, REG_DE_STOP_MSB, de_end); - - if (priv->rev == TDA19988) { - /* let incoming pixels fill the active space (if any) */ - reg_write(encoder, REG_ENABLE_SPACE, 0x01); - } - - reg_write16(encoder, REG_REFPIX_MSB, ref_pix); - reg_write16(encoder, REG_REFLINE_MSB, ref_line); - - reg = TBG_CNTRL_1_VHX_EXT_DE | - TBG_CNTRL_1_VHX_EXT_HS | - TBG_CNTRL_1_VHX_EXT_VS | - TBG_CNTRL_1_DWIN_DIS | /* HDCP off */ - TBG_CNTRL_1_VH_TGL_2; - if (mode->flags & (DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC)) - reg |= TBG_CNTRL_1_VH_TGL_0; - reg_set(encoder, REG_TBG_CNTRL_1, reg); - - /* must be last register set: */ - reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE); -} - -static enum drm_connector_status -tda998x_encoder_detect(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - uint8_t val = cec_read(encoder, REG_CEC_RXSHPDLEV); - return (val & CEC_RXSHPDLEV_HPD) ? connector_status_connected : - connector_status_disconnected; -} - -static int -read_edid_block(struct drm_encoder *encoder, uint8_t *buf, int blk) -{ - uint8_t offset, segptr; - int ret, i; - - /* enable EDID read irq: */ - reg_set(encoder, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD); - - offset = (blk & 1) ? 128 : 0; - segptr = blk / 2; - - reg_write(encoder, REG_DDC_ADDR, 0xa0); - reg_write(encoder, REG_DDC_OFFS, offset); - reg_write(encoder, REG_DDC_SEGM_ADDR, 0x60); - reg_write(encoder, REG_DDC_SEGM, segptr); - - /* enable reading EDID: */ - reg_write(encoder, REG_EDID_CTRL, 0x1); - - /* flag must be cleared by sw: */ - reg_write(encoder, REG_EDID_CTRL, 0x0); - - /* wait for block read to complete: */ - for (i = 100; i > 0; i--) { - uint8_t val = reg_read(encoder, REG_INT_FLAGS_2); - if (val & INT_FLAGS_2_EDID_BLK_RD) - break; - msleep(1); - } - - if (i == 0) - return -ETIMEDOUT; - - ret = reg_read_range(encoder, REG_EDID_DATA_0, buf, EDID_LENGTH); - if (ret != EDID_LENGTH) { - dev_err(encoder->dev->dev, "failed to read edid block %d: %d", - blk, ret); - return ret; - } - - reg_clear(encoder, REG_INT_FLAGS_2, INT_FLAGS_2_EDID_BLK_RD); - - return 0; -} - -static uint8_t * -do_get_edid(struct drm_encoder *encoder) -{ - int j = 0, valid_extensions = 0; - uint8_t *block, *new; - bool print_bad_edid = drm_debug & DRM_UT_KMS; - - if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) - return NULL; - - /* base block fetch */ - if (read_edid_block(encoder, block, 0)) - goto fail; - - if (!drm_edid_block_valid(block, 0, print_bad_edid)) - goto fail; - - /* if there's no extensions, we're done */ - if (block[0x7e] == 0) - return block; - - new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL); - if (!new) - goto fail; - block = new; - - for (j = 1; j <= block[0x7e]; j++) { - uint8_t *ext_block = block + (valid_extensions + 1) * EDID_LENGTH; - if (read_edid_block(encoder, ext_block, j)) - goto fail; - - if (!drm_edid_block_valid(ext_block, j, print_bad_edid)) - goto fail; - - valid_extensions++; - } - - if (valid_extensions != block[0x7e]) { - block[EDID_LENGTH-1] += block[0x7e] - valid_extensions; - block[0x7e] = valid_extensions; - new = krealloc(block, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL); - if (!new) - goto fail; - block = new; - } - - return block; - -fail: - dev_warn(encoder->dev->dev, "failed to read EDID\n"); - kfree(block); - return NULL; -} - -static int -tda998x_encoder_get_modes(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - struct edid *edid = (struct edid *)do_get_edid(encoder); - int n = 0; - - if (edid) { - drm_mode_connector_update_edid_property(connector, edid); - n = drm_add_edid_modes(connector, edid); - kfree(edid); - } - - return n; -} - -static int -tda998x_encoder_create_resources(struct drm_encoder *encoder, - struct drm_connector *connector) -{ - DBG(""); - return 0; -} - -static int -tda998x_encoder_set_property(struct drm_encoder *encoder, - struct drm_connector *connector, - struct drm_property *property, - uint64_t val) -{ - DBG(""); - return 0; -} - -static void -tda998x_encoder_destroy(struct drm_encoder *encoder) -{ - struct tda998x_priv *priv = to_tda998x_priv(encoder); - drm_i2c_encoder_destroy(encoder); - kfree(priv); -} - -static struct drm_encoder_slave_funcs tda998x_encoder_funcs = { - .set_config = tda998x_encoder_set_config, - .destroy = tda998x_encoder_destroy, - .dpms = tda998x_encoder_dpms, - .save = tda998x_encoder_save, - .restore = tda998x_encoder_restore, - .mode_fixup = tda998x_encoder_mode_fixup, - .mode_valid = tda998x_encoder_mode_valid, - .mode_set = tda998x_encoder_mode_set, - .detect = tda998x_encoder_detect, - .get_modes = tda998x_encoder_get_modes, - .create_resources = tda998x_encoder_create_resources, - .set_property = tda998x_encoder_set_property, -}; - -/* I2C driver functions */ - -static int -tda998x_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - return 0; -} - -static int -tda998x_remove(struct i2c_client *client) -{ - return 0; -} - -static int -tda998x_encoder_init(struct i2c_client *client, - struct drm_device *dev, - struct drm_encoder_slave *encoder_slave) -{ - struct drm_encoder *encoder = &encoder_slave->base; - struct tda998x_priv *priv; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->current_page = 0; - priv->cec = i2c_new_dummy(client->adapter, 0x34); - priv->dpms = DRM_MODE_DPMS_OFF; - - encoder_slave->slave_priv = priv; - encoder_slave->slave_funcs = &tda998x_encoder_funcs; - - /* wake up the device: */ - cec_write(encoder, REG_CEC_ENAMODS, - CEC_ENAMODS_EN_RXSENS | CEC_ENAMODS_EN_HDMI); - - tda998x_reset(encoder); - - /* read version: */ - priv->rev = reg_read(encoder, REG_VERSION_LSB) | - reg_read(encoder, REG_VERSION_MSB) << 8; - - /* mask off feature bits: */ - priv->rev &= ~0x30; /* not-hdcp and not-scalar bit */ - - switch (priv->rev) { - case TDA9989N2: dev_info(dev->dev, "found TDA9989 n2"); break; - case TDA19989: dev_info(dev->dev, "found TDA19989"); break; - case TDA19989N2: dev_info(dev->dev, "found TDA19989 n2"); break; - case TDA19988: dev_info(dev->dev, "found TDA19988"); break; - default: - DBG("found unsupported device: %04x", priv->rev); - goto fail; - } - - /* after reset, enable DDC: */ - reg_write(encoder, REG_DDC_DISABLE, 0x00); - - /* set clock on DDC channel: */ - reg_write(encoder, REG_TX3, 39); - - /* if necessary, disable multi-master: */ - if (priv->rev == TDA19989) - reg_set(encoder, REG_I2C_MASTER, I2C_MASTER_DIS_MM); - - cec_write(encoder, REG_CEC_FRO_IM_CLK_CTRL, - CEC_FRO_IM_CLK_CTRL_GHOST_DIS | CEC_FRO_IM_CLK_CTRL_IMCLK_SEL); - - return 0; - -fail: - /* if encoder_init fails, the encoder slave is never registered, - * so cleanup here: - */ - if (priv->cec) - i2c_unregister_device(priv->cec); - kfree(priv); - encoder_slave->slave_priv = NULL; - encoder_slave->slave_funcs = NULL; - return -ENXIO; -} - -static struct i2c_device_id tda998x_ids[] = { - { "tda998x", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, tda998x_ids); - -static struct drm_i2c_encoder_driver tda998x_driver = { - .i2c_driver = { - .probe = tda998x_probe, - .remove = tda998x_remove, - .driver = { - .name = "tda998x", - }, - .id_table = tda998x_ids, - }, - .encoder_init = tda998x_encoder_init, -}; - -/* Module initialization */ - -static int __init -tda998x_init(void) -{ - DBG(""); - return drm_i2c_encoder_register(THIS_MODULE, &tda998x_driver); -} - -static void __exit -tda998x_exit(void) -{ - DBG(""); - drm_i2c_encoder_unregister(&tda998x_driver); -} - -MODULE_AUTHOR("Rob Clark gen >= 4) { intel_crtc->dspaddr_offset = - intel_gen4_compute_offset_xtiled(&x, &y, - fb->bits_per_pixel / 8, - fb->pitches[0]); + intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode, + fb->bits_per_pixel / 8, + fb->pitches[0]); linear_offset -= intel_crtc->dspaddr_offset; } else { intel_crtc->dspaddr_offset = linear_offset; @@ -2182,9 +2193,9 @@ static int ironlake_update_plane(struct drm_crtc *crtc, linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); intel_crtc->dspaddr_offset = - intel_gen4_compute_offset_xtiled(&x, &y, - fb->bits_per_pixel / 8, - fb->pitches[0]); + intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode, + fb->bits_per_pixel / 8, + fb->pitches[0]); linear_offset -= intel_crtc->dspaddr_offset; DRM_DEBUG_KMS("Writing base %08X %08lX %d %d %d\n", @@ -3727,6 +3738,10 @@ void intel_crtc_update_dpms(struct drm_crtc *crtc) intel_crtc_update_sarea(crtc, enable); } +static void intel_crtc_noop(struct drm_crtc *crtc) +{ +} + static void intel_crtc_disable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -3775,6 +3790,10 @@ void intel_modeset_disable(struct drm_device *dev) } } +void intel_encoder_noop(struct drm_encoder *encoder) +{ +} + void intel_encoder_destroy(struct drm_encoder *encoder) { struct intel_encoder *intel_encoder = to_intel_encoder(encoder); @@ -7348,6 +7367,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, static struct drm_crtc_helper_funcs intel_helper_funcs = { .mode_set_base_atomic = intel_pipe_set_base_atomic, .load_lut = intel_crtc_load_lut, + .disable = intel_crtc_noop, }; bool intel_encoder_check_is_cloned(struct intel_encoder *encoder) @@ -8057,9 +8077,14 @@ static int intel_crtc_set_config(struct drm_mode_set *set) BUG_ON(!set->crtc); BUG_ON(!set->crtc->helper_private); - /* Enforce sane interface api - has been abused by the fb helper. */ - BUG_ON(!set->mode && set->fb); - BUG_ON(set->fb && set->num_connectors == 0); + if (!set->mode) + set->fb = NULL; + + /* The fb helper likes to play gross jokes with ->mode_set_config. + * Unfortunately the crtc helper doesn't do much at all for this case, + * so we have to cope with this madness until the fb helper is fixed up. */ + if (set->fb && set->num_connectors == 0) + return 0; if (set->fb) { DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n", diff --git a/trunk/drivers/gpu/drm/i915/intel_dp.c b/trunk/drivers/gpu/drm/i915/intel_dp.c index 31c0205685ab..7b8bfe8982e6 100644 --- a/trunk/drivers/gpu/drm/i915/intel_dp.c +++ b/trunk/drivers/gpu/drm/i915/intel_dp.c @@ -2561,6 +2561,7 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder) static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = { .mode_fixup = intel_dp_mode_fixup, .mode_set = intel_dp_mode_set, + .disable = intel_encoder_noop, }; static const struct drm_connector_funcs intel_dp_connector_funcs = { diff --git a/trunk/drivers/gpu/drm/i915/intel_drv.h b/trunk/drivers/gpu/drm/i915/intel_drv.h index d282052aadd4..cba02619ec0f 100644 --- a/trunk/drivers/gpu/drm/i915/intel_drv.h +++ b/trunk/drivers/gpu/drm/i915/intel_drv.h @@ -525,6 +525,7 @@ extern void intel_modeset_disable(struct drm_device *dev); extern void intel_crtc_restore_mode(struct drm_crtc *crtc); extern void intel_crtc_load_lut(struct drm_crtc *crtc); extern void intel_crtc_update_dpms(struct drm_crtc *crtc); +extern void intel_encoder_noop(struct drm_encoder *encoder); extern void intel_encoder_destroy(struct drm_encoder *encoder); extern void intel_encoder_dpms(struct intel_encoder *encoder, int mode); extern bool intel_encoder_check_is_cloned(struct intel_encoder *encoder); @@ -648,9 +649,10 @@ extern void intel_update_sprite_watermarks(struct drm_device *dev, int pipe, extern void intel_update_linetime_watermarks(struct drm_device *dev, int pipe, struct drm_display_mode *mode); -extern unsigned long intel_gen4_compute_offset_xtiled(int *x, int *y, - unsigned int bpp, - unsigned int pitch); +extern unsigned long intel_gen4_compute_page_offset(int *x, int *y, + unsigned int tiling_mode, + unsigned int bpp, + unsigned int pitch); extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data, struct drm_file *file_priv); diff --git a/trunk/drivers/gpu/drm/i915/intel_dvo.c b/trunk/drivers/gpu/drm/i915/intel_dvo.c index 00e70dbe82da..15da99533e5b 100644 --- a/trunk/drivers/gpu/drm/i915/intel_dvo.c +++ b/trunk/drivers/gpu/drm/i915/intel_dvo.c @@ -345,6 +345,7 @@ static void intel_dvo_destroy(struct drm_connector *connector) static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = { .mode_fixup = intel_dvo_mode_fixup, .mode_set = intel_dvo_mode_set, + .disable = intel_encoder_noop, }; static const struct drm_connector_funcs intel_dvo_connector_funcs = { diff --git a/trunk/drivers/gpu/drm/i915/intel_fb.c b/trunk/drivers/gpu/drm/i915/intel_fb.c index 981bdce3634e..1c510da04d16 100644 --- a/trunk/drivers/gpu/drm/i915/intel_fb.c +++ b/trunk/drivers/gpu/drm/i915/intel_fb.c @@ -57,10 +57,9 @@ static struct fb_ops intelfb_ops = { .fb_debug_leave = drm_fb_helper_debug_leave, }; -static int intelfb_create(struct drm_fb_helper *helper, +static int intelfb_create(struct intel_fbdev *ifbdev, struct drm_fb_helper_surface_size *sizes) { - struct intel_fbdev *ifbdev = (struct intel_fbdev *)helper; struct drm_device *dev = ifbdev->helper.dev; struct drm_i915_private *dev_priv = dev->dev_private; struct fb_info *info; @@ -182,10 +181,26 @@ static int intelfb_create(struct drm_fb_helper *helper, return ret; } +static int intel_fb_find_or_create_single(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + struct intel_fbdev *ifbdev = (struct intel_fbdev *)helper; + int new_fb = 0; + int ret; + + if (!helper->fb) { + ret = intelfb_create(ifbdev, sizes); + if (ret) + return ret; + new_fb = 1; + } + return new_fb; +} + static struct drm_fb_helper_funcs intel_fb_helper_funcs = { .gamma_set = intel_crtc_fb_gamma_set, .gamma_get = intel_crtc_fb_gamma_get, - .fb_probe = intelfb_create, + .fb_probe = intel_fb_find_or_create_single, }; static void intel_fbdev_destroy(struct drm_device *dev, diff --git a/trunk/drivers/gpu/drm/i915/intel_hdmi.c b/trunk/drivers/gpu/drm/i915/intel_hdmi.c index 3ea0c8b6a00f..5a6138c62fe9 100644 --- a/trunk/drivers/gpu/drm/i915/intel_hdmi.c +++ b/trunk/drivers/gpu/drm/i915/intel_hdmi.c @@ -972,6 +972,7 @@ static void intel_hdmi_destroy(struct drm_connector *connector) static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = { .mode_fixup = intel_hdmi_mode_fixup, .mode_set = intel_hdmi_mode_set, + .disable = intel_encoder_noop, }; static const struct drm_connector_funcs intel_hdmi_connector_funcs = { diff --git a/trunk/drivers/gpu/drm/i915/intel_lvds.c b/trunk/drivers/gpu/drm/i915/intel_lvds.c index 3d1d97488cc9..c7154bfa54cf 100644 --- a/trunk/drivers/gpu/drm/i915/intel_lvds.c +++ b/trunk/drivers/gpu/drm/i915/intel_lvds.c @@ -663,6 +663,7 @@ static int intel_lvds_set_property(struct drm_connector *connector, static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = { .mode_fixup = intel_lvds_mode_fixup, .mode_set = intel_lvds_mode_set, + .disable = intel_encoder_noop, }; static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = { diff --git a/trunk/drivers/gpu/drm/i915/intel_sdvo.c b/trunk/drivers/gpu/drm/i915/intel_sdvo.c index 33b46d9694ea..f01063a2323a 100644 --- a/trunk/drivers/gpu/drm/i915/intel_sdvo.c +++ b/trunk/drivers/gpu/drm/i915/intel_sdvo.c @@ -2043,6 +2043,7 @@ intel_sdvo_set_property(struct drm_connector *connector, static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = { .mode_fixup = intel_sdvo_mode_fixup, .mode_set = intel_sdvo_mode_set, + .disable = intel_encoder_noop, }; static const struct drm_connector_funcs intel_sdvo_connector_funcs = { diff --git a/trunk/drivers/gpu/drm/i915/intel_sprite.c b/trunk/drivers/gpu/drm/i915/intel_sprite.c index d086e48a831a..1b6eb76beb7c 100644 --- a/trunk/drivers/gpu/drm/i915/intel_sprite.c +++ b/trunk/drivers/gpu/drm/i915/intel_sprite.c @@ -122,8 +122,8 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, linear_offset = y * fb->pitches[0] + x * pixel_size; sprsurf_offset = - intel_gen4_compute_offset_xtiled(&x, &y, - pixel_size, fb->pitches[0]); + intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode, + pixel_size, fb->pitches[0]); linear_offset -= sprsurf_offset; /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET @@ -295,8 +295,8 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, linear_offset = y * fb->pitches[0] + x * pixel_size; dvssurf_offset = - intel_gen4_compute_offset_xtiled(&x, &y, - pixel_size, fb->pitches[0]); + intel_gen4_compute_page_offset(&x, &y, obj->tiling_mode, + pixel_size, fb->pitches[0]); linear_offset -= dvssurf_offset; if (obj->tiling_mode != I915_TILING_NONE) diff --git a/trunk/drivers/gpu/drm/i915/intel_tv.c b/trunk/drivers/gpu/drm/i915/intel_tv.c index d808421c1c80..984a113c5d13 100644 --- a/trunk/drivers/gpu/drm/i915/intel_tv.c +++ b/trunk/drivers/gpu/drm/i915/intel_tv.c @@ -1487,6 +1487,7 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = { .mode_fixup = intel_tv_mode_fixup, .mode_set = intel_tv_mode_set, + .disable = intel_encoder_noop, }; static const struct drm_connector_funcs intel_tv_connector_funcs = { diff --git a/trunk/drivers/gpu/drm/mgag200/mgag200_fb.c b/trunk/drivers/gpu/drm/mgag200/mgag200_fb.c index d2253f639481..5c69b432f99a 100644 --- a/trunk/drivers/gpu/drm/mgag200/mgag200_fb.c +++ b/trunk/drivers/gpu/drm/mgag200/mgag200_fb.c @@ -13,7 +13,6 @@ #include #include #include -#include #include @@ -121,10 +120,9 @@ static int mgag200fb_create_object(struct mga_fbdev *afbdev, return ret; } -static int mgag200fb_create(struct drm_fb_helper *helper, +static int mgag200fb_create(struct mga_fbdev *mfbdev, struct drm_fb_helper_surface_size *sizes) { - struct mga_fbdev *mfbdev = (struct mga_fbdev *)helper; struct drm_device *dev = mfbdev->helper.dev; struct drm_mode_fb_cmd2 mode_cmd; struct mga_device *mdev = dev->dev_private; @@ -211,6 +209,23 @@ static int mgag200fb_create(struct drm_fb_helper *helper, return ret; } +static int mga_fb_find_or_create_single(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size + *sizes) +{ + struct mga_fbdev *mfbdev = (struct mga_fbdev *)helper; + int new_fb = 0; + int ret; + + if (!helper->fb) { + ret = mgag200fb_create(mfbdev, sizes); + if (ret) + return ret; + new_fb = 1; + } + return new_fb; +} + static int mga_fbdev_destroy(struct drm_device *dev, struct mga_fbdev *mfbdev) { @@ -241,7 +256,7 @@ static int mga_fbdev_destroy(struct drm_device *dev, static struct drm_fb_helper_funcs mga_fb_helper_funcs = { .gamma_set = mga_crtc_fb_gamma_set, .gamma_get = mga_crtc_fb_gamma_get, - .fb_probe = mgag200fb_create, + .fb_probe = mga_fb_find_or_create_single, }; int mgag200_fbdev_init(struct mga_device *mdev) @@ -263,10 +278,6 @@ int mgag200_fbdev_init(struct mga_device *mdev) return ret; } drm_fb_helper_single_add_all_connectors(&mfbdev->helper); - - /* disable all the possible outputs/crtcs before entering KMS mode */ - drm_helper_disable_unused_functions(mdev->dev); - drm_fb_helper_initial_config(&mfbdev->helper, 32); return 0; diff --git a/trunk/drivers/gpu/drm/nouveau/Kconfig b/trunk/drivers/gpu/drm/nouveau/Kconfig index a7ff6d5a34b9..47ccc1ad5405 100644 --- a/trunk/drivers/gpu/drm/nouveau/Kconfig +++ b/trunk/drivers/gpu/drm/nouveau/Kconfig @@ -11,9 +11,8 @@ config DRM_NOUVEAU select FRAMEBUFFER_CONSOLE if !EXPERT select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL && INPUT - select X86_PLATFORM_DEVICES if ACPI && X86 - select ACPI_WMI if ACPI && X86 - select MXM_WMI if ACPI && X86 + select ACPI_WMI if ACPI + select MXM_WMI if ACPI select POWER_SUPPLY help Choose this option for open-source nVidia support. diff --git a/trunk/drivers/gpu/drm/nouveau/Makefile b/trunk/drivers/gpu/drm/nouveau/Makefile index 90f9140eeefd..ab25752a0b1e 100644 --- a/trunk/drivers/gpu/drm/nouveau/Makefile +++ b/trunk/drivers/gpu/drm/nouveau/Makefile @@ -11,7 +11,6 @@ nouveau-y := core/core/client.o nouveau-y += core/core/engctx.o nouveau-y += core/core/engine.o nouveau-y += core/core/enum.o -nouveau-y += core/core/event.o nouveau-y += core/core/falcon.o nouveau-y += core/core/gpuobj.o nouveau-y += core/core/handle.o @@ -41,11 +40,6 @@ nouveau-y += core/subdev/bios/mxm.o nouveau-y += core/subdev/bios/perf.o nouveau-y += core/subdev/bios/pll.o nouveau-y += core/subdev/bios/therm.o -nouveau-y += core/subdev/bios/xpio.o -nouveau-y += core/subdev/bus/nv04.o -nouveau-y += core/subdev/bus/nv31.o -nouveau-y += core/subdev/bus/nv50.o -nouveau-y += core/subdev/bus/nvc0.o nouveau-y += core/subdev/clock/nv04.o nouveau-y += core/subdev/clock/nv40.o nouveau-y += core/subdev/clock/nv50.o @@ -91,16 +85,9 @@ nouveau-y += core/subdev/gpio/base.o nouveau-y += core/subdev/gpio/nv10.o nouveau-y += core/subdev/gpio/nv50.o nouveau-y += core/subdev/gpio/nvd0.o -nouveau-y += core/subdev/gpio/nve0.o nouveau-y += core/subdev/i2c/base.o -nouveau-y += core/subdev/i2c/anx9805.o nouveau-y += core/subdev/i2c/aux.o nouveau-y += core/subdev/i2c/bit.o -nouveau-y += core/subdev/i2c/nv04.o -nouveau-y += core/subdev/i2c/nv4e.o -nouveau-y += core/subdev/i2c/nv50.o -nouveau-y += core/subdev/i2c/nv94.o -nouveau-y += core/subdev/i2c/nvd0.o nouveau-y += core/subdev/ibus/nvc0.o nouveau-y += core/subdev/ibus/nve0.o nouveau-y += core/subdev/instmem/base.o @@ -119,15 +106,10 @@ nouveau-y += core/subdev/mxm/mxms.o nouveau-y += core/subdev/mxm/nv50.o nouveau-y += core/subdev/therm/base.o nouveau-y += core/subdev/therm/fan.o -nouveau-y += core/subdev/therm/fannil.o -nouveau-y += core/subdev/therm/fanpwm.o -nouveau-y += core/subdev/therm/fantog.o nouveau-y += core/subdev/therm/ic.o -nouveau-y += core/subdev/therm/temp.o nouveau-y += core/subdev/therm/nv40.o nouveau-y += core/subdev/therm/nv50.o -nouveau-y += core/subdev/therm/nva3.o -nouveau-y += core/subdev/therm/nvd0.o +nouveau-y += core/subdev/therm/temp.o nouveau-y += core/subdev/timer/base.o nouveau-y += core/subdev/timer/nv04.o nouveau-y += core/subdev/vm/base.o @@ -150,7 +132,6 @@ nouveau-y += core/engine/copy/nvc0.o nouveau-y += core/engine/copy/nve0.o nouveau-y += core/engine/crypt/nv84.o nouveau-y += core/engine/crypt/nv98.o -nouveau-y += core/engine/disp/base.o nouveau-y += core/engine/disp/nv04.o nouveau-y += core/engine/disp/nv50.o nouveau-y += core/engine/disp/nv84.o @@ -160,13 +141,11 @@ nouveau-y += core/engine/disp/nva3.o nouveau-y += core/engine/disp/nvd0.o nouveau-y += core/engine/disp/nve0.o nouveau-y += core/engine/disp/dacnv50.o -nouveau-y += core/engine/disp/dport.o nouveau-y += core/engine/disp/hdanva3.o nouveau-y += core/engine/disp/hdanvd0.o nouveau-y += core/engine/disp/hdminv84.o nouveau-y += core/engine/disp/hdminva3.o nouveau-y += core/engine/disp/hdminvd0.o -nouveau-y += core/engine/disp/piornv50.o nouveau-y += core/engine/disp/sornv50.o nouveau-y += core/engine/disp/sornv94.o nouveau-y += core/engine/disp/sornvd0.o @@ -215,8 +194,7 @@ nouveau-y += nouveau_drm.o nouveau_chan.o nouveau_dma.o nouveau_fence.o nouveau-y += nouveau_irq.o nouveau_vga.o nouveau_agp.o nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o nouveau-y += nouveau_prime.o nouveau_abi16.o -nouveau-y += nv04_fence.o nv10_fence.o nv17_fence.o -nouveau-y += nv50_fence.o nv84_fence.o nvc0_fence.o +nouveau-y += nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o # drm/kms nouveau-y += nouveau_bios.o nouveau_fbcon.o nouveau_display.o @@ -238,10 +216,7 @@ nouveau-y += nouveau_mem.o # other random bits nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o -ifdef CONFIG_X86 nouveau-$(CONFIG_ACPI) += nouveau_acpi.o -endif nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o -nouveau-$(CONFIG_DEBUG_FS) += nouveau_debugfs.o obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o diff --git a/trunk/drivers/gpu/drm/nouveau/core/core/client.c b/trunk/drivers/gpu/drm/nouveau/core/core/client.c index 295c22165eac..8bbb58f94a19 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/core/client.c +++ b/trunk/drivers/gpu/drm/nouveau/core/core/client.c @@ -99,13 +99,3 @@ nouveau_client_fini(struct nouveau_client *client, bool suspend) nv_debug(client, "%s completed with %d\n", name[suspend], ret); return ret; } - -const char * -nouveau_client_name(void *obj) -{ - const char *client_name = "unknown"; - struct nouveau_client *client = nouveau_client(obj); - if (client) - client_name = client->name; - return client_name; -} diff --git a/trunk/drivers/gpu/drm/nouveau/core/core/enum.c b/trunk/drivers/gpu/drm/nouveau/core/core/enum.c index dd434790ccc4..7cc7133d82de 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/core/enum.c +++ b/trunk/drivers/gpu/drm/nouveau/core/core/enum.c @@ -40,15 +40,14 @@ nouveau_enum_find(const struct nouveau_enum *en, u32 value) return NULL; } -const struct nouveau_enum * +void nouveau_enum_print(const struct nouveau_enum *en, u32 value) { en = nouveau_enum_find(en, value); if (en) - pr_cont("%s", en->name); + printk("%s", en->name); else - pr_cont("(unknown enum 0x%08x)", value); - return en; + printk("(unknown enum 0x%08x)", value); } void @@ -56,7 +55,7 @@ nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value) { while (bf->name) { if (value & bf->mask) { - pr_cont(" %s", bf->name); + printk(" %s", bf->name); value &= ~bf->mask; } @@ -64,5 +63,5 @@ nouveau_bitfield_print(const struct nouveau_bitfield *bf, u32 value) } if (value) - pr_cont(" (unknown bits 0x%08x)", value); + printk(" (unknown bits 0x%08x)", value); } diff --git a/trunk/drivers/gpu/drm/nouveau/core/core/event.c b/trunk/drivers/gpu/drm/nouveau/core/core/event.c deleted file mode 100644 index 6d01e0f0fc8a..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/core/event.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2013 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include - -static void -nouveau_event_put_locked(struct nouveau_event *event, int index, - struct nouveau_eventh *handler) -{ - if (!--event->index[index].refs) - event->disable(event, index); - list_del(&handler->head); -} - -void -nouveau_event_put(struct nouveau_event *event, int index, - struct nouveau_eventh *handler) -{ - unsigned long flags; - - spin_lock_irqsave(&event->lock, flags); - if (index < event->index_nr) - nouveau_event_put_locked(event, index, handler); - spin_unlock_irqrestore(&event->lock, flags); -} - -void -nouveau_event_get(struct nouveau_event *event, int index, - struct nouveau_eventh *handler) -{ - unsigned long flags; - - spin_lock_irqsave(&event->lock, flags); - if (index < event->index_nr) { - list_add(&handler->head, &event->index[index].list); - if (!event->index[index].refs++) - event->enable(event, index); - } - spin_unlock_irqrestore(&event->lock, flags); -} - -void -nouveau_event_trigger(struct nouveau_event *event, int index) -{ - struct nouveau_eventh *handler, *temp; - unsigned long flags; - - if (index >= event->index_nr) - return; - - spin_lock_irqsave(&event->lock, flags); - list_for_each_entry_safe(handler, temp, &event->index[index].list, head) { - if (handler->func(handler, index) == NVKM_EVENT_DROP) { - nouveau_event_put_locked(event, index, handler); - } - } - spin_unlock_irqrestore(&event->lock, flags); -} - -void -nouveau_event_destroy(struct nouveau_event **pevent) -{ - struct nouveau_event *event = *pevent; - if (event) { - kfree(event); - *pevent = NULL; - } -} - -int -nouveau_event_create(int index_nr, struct nouveau_event **pevent) -{ - struct nouveau_event *event; - int i; - - event = *pevent = kzalloc(sizeof(*event) + index_nr * - sizeof(event->index[0]), GFP_KERNEL); - if (!event) - return -ENOMEM; - - spin_lock_init(&event->lock); - for (i = 0; i < index_nr; i++) - INIT_LIST_HEAD(&event->index[i].list); - event->index_nr = index_nr; - return 0; -} diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c b/trunk/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c index d6dc2a65ccd1..283248c7b050 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/copy/nva3.c @@ -22,7 +22,6 @@ * Authors: Ben Skeggs */ -#include #include #include #include @@ -101,9 +100,8 @@ nva3_copy_intr(struct nouveau_subdev *subdev) if (stat & 0x00000040) { nv_error(falcon, "DISPATCH_ERROR ["); nouveau_enum_print(nva3_copy_isr_error_name, ssta); - pr_cont("] ch %d [0x%010llx %s] subc %d mthd 0x%04x data 0x%08x\n", - chid, inst << 12, nouveau_client_name(engctx), subc, - mthd, data); + printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n", + chid, inst << 12, subc, mthd, data); nv_wo32(falcon, 0x004, 0x00000040); stat &= ~0x00000040; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c b/trunk/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c index 5bc021f471f9..b97490512723 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c @@ -22,7 +22,6 @@ * Authors: Ben Skeggs */ -#include #include #include #include @@ -127,11 +126,10 @@ nv84_crypt_intr(struct nouveau_subdev *subdev) chid = pfifo->chid(pfifo, engctx); if (stat) { - nv_error(priv, "%s", ""); + nv_error(priv, ""); nouveau_bitfield_print(nv84_crypt_intr_mask, stat); - pr_cont(" ch %d [0x%010llx %s] mthd 0x%04x data 0x%08x\n", - chid, (u64)inst << 12, nouveau_client_name(engctx), - mthd, data); + printk(" ch %d [0x%010llx] mthd 0x%04x data 0x%08x\n", + chid, (u64)inst << 12, mthd, data); } nv_wr32(priv, 0x102130, stat); diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c b/trunk/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c index 8bf8955051d4..21986f3bf0c8 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c @@ -22,7 +22,6 @@ * Authors: Ben Skeggs */ -#include #include #include #include @@ -103,9 +102,8 @@ nv98_crypt_intr(struct nouveau_subdev *subdev) if (stat & 0x00000040) { nv_error(priv, "DISPATCH_ERROR ["); nouveau_enum_print(nv98_crypt_isr_error_name, ssta); - pr_cont("] ch %d [0x%010llx %s] subc %d mthd 0x%04x data 0x%08x\n", - chid, (u64)inst << 12, nouveau_client_name(engctx), - subc, mthd, data); + printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n", + chid, (u64)inst << 12, subc, mthd, data); nv_wr32(priv, 0x087004, 0x00000040); stat &= ~0x00000040; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/base.c b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/base.c deleted file mode 100644 index 7a5cae42834f..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/base.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2013 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include - -void -_nouveau_disp_dtor(struct nouveau_object *object) -{ - struct nouveau_disp *disp = (void *)object; - nouveau_event_destroy(&disp->vblank); - nouveau_engine_destroy(&disp->base); -} - -int -nouveau_disp_create_(struct nouveau_object *parent, - struct nouveau_object *engine, - struct nouveau_oclass *oclass, int heads, - const char *intname, const char *extname, - int length, void **pobject) -{ - struct nouveau_disp *disp; - int ret; - - ret = nouveau_engine_create_(parent, engine, oclass, true, - intname, extname, length, pobject); - disp = *pobject; - if (ret) - return ret; - - return nouveau_event_create(heads, &disp->vblank); -} diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/dport.c b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/dport.c deleted file mode 100644 index fa27b02ff829..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/dport.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright 2013 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include -#include -#include -#include -#include - -#include - -#include "dport.h" - -#define DBG(fmt, args...) nv_debug(dp->disp, "DP:%04x:%04x: " fmt, \ - dp->outp->hasht, dp->outp->hashm, ##args) -#define ERR(fmt, args...) nv_error(dp->disp, "DP:%04x:%04x: " fmt, \ - dp->outp->hasht, dp->outp->hashm, ##args) - -/****************************************************************************** - * link training - *****************************************************************************/ -struct dp_state { - const struct nouveau_dp_func *func; - struct nouveau_disp *disp; - struct dcb_output *outp; - struct nvbios_dpout info; - u8 version; - struct nouveau_i2c_port *aux; - int head; - u8 dpcd[4]; - int link_nr; - u32 link_bw; - u8 stat[6]; - u8 conf[4]; -}; - -static int -dp_set_link_config(struct dp_state *dp) -{ - struct nouveau_disp *disp = dp->disp; - struct nouveau_bios *bios = nouveau_bios(disp); - struct nvbios_init init = { - .subdev = nv_subdev(dp->disp), - .bios = bios, - .offset = 0x0000, - .outp = dp->outp, - .crtc = dp->head, - .execute = 1, - }; - u32 lnkcmp; - u8 sink[2]; - - DBG("%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); - - /* set desired link configuration on the sink */ - sink[0] = dp->link_bw / 27000; - sink[1] = dp->link_nr; - if (dp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP) - sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN; - - nv_wraux(dp->aux, DPCD_LC00, sink, 2); - - /* set desired link configuration on the source */ - if ((lnkcmp = dp->info.lnkcmp)) { - if (dp->version < 0x30) { - while ((dp->link_bw / 10) < nv_ro16(bios, lnkcmp)) - lnkcmp += 4; - init.offset = nv_ro16(bios, lnkcmp + 2); - } else { - while ((dp->link_bw / 27000) < nv_ro08(bios, lnkcmp)) - lnkcmp += 3; - init.offset = nv_ro16(bios, lnkcmp + 1); - } - - nvbios_exec(&init); - } - - return dp->func->lnk_ctl(dp->disp, dp->outp, dp->head, - dp->link_nr, dp->link_bw / 27000, - dp->dpcd[DPCD_RC02] & - DPCD_RC02_ENHANCED_FRAME_CAP); -} - -static void -dp_set_training_pattern(struct dp_state *dp, u8 pattern) -{ - u8 sink_tp; - - DBG("training pattern %d\n", pattern); - dp->func->pattern(dp->disp, dp->outp, dp->head, pattern); - - nv_rdaux(dp->aux, DPCD_LC02, &sink_tp, 1); - sink_tp &= ~DPCD_LC02_TRAINING_PATTERN_SET; - sink_tp |= pattern; - nv_wraux(dp->aux, DPCD_LC02, &sink_tp, 1); -} - -static int -dp_link_train_commit(struct dp_state *dp) -{ - int i; - - for (i = 0; i < dp->link_nr; i++) { - u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; - u8 lpre = (lane & 0x0c) >> 2; - u8 lvsw = (lane & 0x03) >> 0; - - dp->conf[i] = (lpre << 3) | lvsw; - if (lvsw == 3) - dp->conf[i] |= DPCD_LC03_MAX_SWING_REACHED; - if (lpre == 3) - dp->conf[i] |= DPCD_LC03_MAX_PRE_EMPHASIS_REACHED; - - DBG("config lane %d %02x\n", i, dp->conf[i]); - dp->func->drv_ctl(dp->disp, dp->outp, dp->head, i, lvsw, lpre); - } - - return nv_wraux(dp->aux, DPCD_LC03(0), dp->conf, 4); -} - -static int -dp_link_train_update(struct dp_state *dp, u32 delay) -{ - int ret; - - udelay(delay); - - ret = nv_rdaux(dp->aux, DPCD_LS02, dp->stat, 6); - if (ret) - return ret; - - DBG("status %*ph\n", 6, dp->stat); - return 0; -} - -static int -dp_link_train_cr(struct dp_state *dp) -{ - bool cr_done = false, abort = false; - int voltage = dp->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET; - int tries = 0, i; - - dp_set_training_pattern(dp, 1); - - do { - if (dp_link_train_commit(dp) || - dp_link_train_update(dp, 100)) - break; - - cr_done = true; - for (i = 0; i < dp->link_nr; i++) { - u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; - if (!(lane & DPCD_LS02_LANE0_CR_DONE)) { - cr_done = false; - if (dp->conf[i] & DPCD_LC03_MAX_SWING_REACHED) - abort = true; - break; - } - } - - if ((dp->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET) != voltage) { - voltage = dp->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET; - tries = 0; - } - } while (!cr_done && !abort && ++tries < 5); - - return cr_done ? 0 : -1; -} - -static int -dp_link_train_eq(struct dp_state *dp) -{ - bool eq_done, cr_done = true; - int tries = 0, i; - - dp_set_training_pattern(dp, 2); - - do { - if (dp_link_train_update(dp, 400)) - break; - - eq_done = !!(dp->stat[2] & DPCD_LS04_INTERLANE_ALIGN_DONE); - for (i = 0; i < dp->link_nr && eq_done; i++) { - u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; - if (!(lane & DPCD_LS02_LANE0_CR_DONE)) - cr_done = false; - if (!(lane & DPCD_LS02_LANE0_CHANNEL_EQ_DONE) || - !(lane & DPCD_LS02_LANE0_SYMBOL_LOCKED)) - eq_done = false; - } - - if (dp_link_train_commit(dp)) - break; - } while (!eq_done && cr_done && ++tries <= 5); - - return eq_done ? 0 : -1; -} - -static void -dp_link_train_init(struct dp_state *dp, bool spread) -{ - struct nvbios_init init = { - .subdev = nv_subdev(dp->disp), - .bios = nouveau_bios(dp->disp), - .outp = dp->outp, - .crtc = dp->head, - .execute = 1, - }; - - /* set desired spread */ - if (spread) - init.offset = dp->info.script[2]; - else - init.offset = dp->info.script[3]; - nvbios_exec(&init); - - /* pre-train script */ - init.offset = dp->info.script[0]; - nvbios_exec(&init); -} - -static void -dp_link_train_fini(struct dp_state *dp) -{ - struct nvbios_init init = { - .subdev = nv_subdev(dp->disp), - .bios = nouveau_bios(dp->disp), - .outp = dp->outp, - .crtc = dp->head, - .execute = 1, - }; - - /* post-train script */ - init.offset = dp->info.script[1], - nvbios_exec(&init); -} - -int -nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func, - struct dcb_output *outp, int head, u32 datarate) -{ - struct nouveau_bios *bios = nouveau_bios(disp); - struct nouveau_i2c *i2c = nouveau_i2c(disp); - struct dp_state _dp = { - .disp = disp, - .func = func, - .outp = outp, - .head = head, - }, *dp = &_dp; - const u32 bw_list[] = { 270000, 162000, 0 }; - const u32 *link_bw = bw_list; - u8 hdr, cnt, len; - u32 data; - int ret; - - /* find the bios displayport data relevant to this output */ - data = nvbios_dpout_match(bios, outp->hasht, outp->hashm, &dp->version, - &hdr, &cnt, &len, &dp->info); - if (!data) { - ERR("bios data not found\n"); - return -EINVAL; - } - - /* acquire the aux channel and fetch some info about the display */ - if (outp->location) - dp->aux = i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(outp->extdev)); - else - dp->aux = i2c->find(i2c, NV_I2C_TYPE_DCBI2C(outp->i2c_index)); - if (!dp->aux) { - ERR("no aux channel?!\n"); - return -ENODEV; - } - - ret = nv_rdaux(dp->aux, 0x00000, dp->dpcd, sizeof(dp->dpcd)); - if (ret) { - ERR("failed to read DPCD\n"); - return ret; - } - - /* adjust required bandwidth for 8B/10B coding overhead */ - datarate = (datarate / 8) * 10; - - /* enable down-spreading and execute pre-train script from vbios */ - dp_link_train_init(dp, dp->dpcd[3] & 0x01); - - /* start off at highest link rate supported by encoder and display */ - while (*link_bw > (dp->dpcd[1] * 27000)) - link_bw++; - - while (link_bw[0]) { - /* find minimum required lane count at this link rate */ - dp->link_nr = dp->dpcd[2] & DPCD_RC02_MAX_LANE_COUNT; - while ((dp->link_nr >> 1) * link_bw[0] > datarate) - dp->link_nr >>= 1; - - /* drop link rate to minimum with this lane count */ - while ((link_bw[1] * dp->link_nr) > datarate) - link_bw++; - dp->link_bw = link_bw[0]; - - /* program selected link configuration */ - ret = dp_set_link_config(dp); - if (ret == 0) { - /* attempt to train the link at this configuration */ - memset(dp->stat, 0x00, sizeof(dp->stat)); - if (!dp_link_train_cr(dp) && - !dp_link_train_eq(dp)) - break; - } else - if (ret >= 1) { - /* dp_set_link_config() handled training */ - break; - } - - /* retry at lower rate */ - link_bw++; - } - - /* finish link training */ - dp_set_training_pattern(dp, 0); - - /* execute post-train script from vbios */ - dp_link_train_fini(dp); - return true; -} diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/dport.h b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/dport.h deleted file mode 100644 index 0e1bbd18ff6c..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/dport.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef __NVKM_DISP_DPORT_H__ -#define __NVKM_DISP_DPORT_H__ - -/* DPCD Receiver Capabilities */ -#define DPCD_RC00 0x00000 -#define DPCD_RC00_DPCD_REV 0xff -#define DPCD_RC01 0x00001 -#define DPCD_RC01_MAX_LINK_RATE 0xff -#define DPCD_RC02 0x00002 -#define DPCD_RC02_ENHANCED_FRAME_CAP 0x80 -#define DPCD_RC02_MAX_LANE_COUNT 0x1f -#define DPCD_RC03 0x00003 -#define DPCD_RC03_MAX_DOWNSPREAD 0x01 - -/* DPCD Link Configuration */ -#define DPCD_LC00 0x00100 -#define DPCD_LC00_LINK_BW_SET 0xff -#define DPCD_LC01 0x00101 -#define DPCD_LC01_ENHANCED_FRAME_EN 0x80 -#define DPCD_LC01_LANE_COUNT_SET 0x1f -#define DPCD_LC02 0x00102 -#define DPCD_LC02_TRAINING_PATTERN_SET 0x03 -#define DPCD_LC03(l) ((l) + 0x00103) -#define DPCD_LC03_MAX_PRE_EMPHASIS_REACHED 0x20 -#define DPCD_LC03_PRE_EMPHASIS_SET 0x18 -#define DPCD_LC03_MAX_SWING_REACHED 0x04 -#define DPCD_LC03_VOLTAGE_SWING_SET 0x03 - -/* DPCD Link/Sink Status */ -#define DPCD_LS02 0x00202 -#define DPCD_LS02_LANE1_SYMBOL_LOCKED 0x40 -#define DPCD_LS02_LANE1_CHANNEL_EQ_DONE 0x20 -#define DPCD_LS02_LANE1_CR_DONE 0x10 -#define DPCD_LS02_LANE0_SYMBOL_LOCKED 0x04 -#define DPCD_LS02_LANE0_CHANNEL_EQ_DONE 0x02 -#define DPCD_LS02_LANE0_CR_DONE 0x01 -#define DPCD_LS03 0x00203 -#define DPCD_LS03_LANE3_SYMBOL_LOCKED 0x40 -#define DPCD_LS03_LANE3_CHANNEL_EQ_DONE 0x20 -#define DPCD_LS03_LANE3_CR_DONE 0x10 -#define DPCD_LS03_LANE2_SYMBOL_LOCKED 0x04 -#define DPCD_LS03_LANE2_CHANNEL_EQ_DONE 0x02 -#define DPCD_LS03_LANE2_CR_DONE 0x01 -#define DPCD_LS04 0x00204 -#define DPCD_LS04_LINK_STATUS_UPDATED 0x80 -#define DPCD_LS04_DOWNSTREAM_PORT_STATUS_CHANGED 0x40 -#define DPCD_LS04_INTERLANE_ALIGN_DONE 0x01 -#define DPCD_LS06 0x00206 -#define DPCD_LS06_LANE1_PRE_EMPHASIS 0xc0 -#define DPCD_LS06_LANE1_VOLTAGE_SWING 0x30 -#define DPCD_LS06_LANE0_PRE_EMPHASIS 0x0c -#define DPCD_LS06_LANE0_VOLTAGE_SWING 0x03 -#define DPCD_LS07 0x00207 -#define DPCD_LS07_LANE3_PRE_EMPHASIS 0xc0 -#define DPCD_LS07_LANE3_VOLTAGE_SWING 0x30 -#define DPCD_LS07_LANE2_PRE_EMPHASIS 0x0c -#define DPCD_LS07_LANE2_VOLTAGE_SWING 0x03 - -struct nouveau_disp; -struct dcb_output; - -struct nouveau_dp_func { - int (*pattern)(struct nouveau_disp *, struct dcb_output *, - int head, int pattern); - int (*lnk_ctl)(struct nouveau_disp *, struct dcb_output *, int head, - int link_nr, int link_bw, bool enh_frame); - int (*drv_ctl)(struct nouveau_disp *, struct dcb_output *, int head, - int lane, int swing, int preem); -}; - -extern const struct nouveau_dp_func nv94_sor_dp_func; -extern const struct nouveau_dp_func nvd0_sor_dp_func; -extern const struct nouveau_dp_func nv50_pior_dp_func; - -int nouveau_dp_train(struct nouveau_disp *, const struct nouveau_dp_func *, - struct dcb_output *, int, u32); - -#endif diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c index 05e903f08a36..1c919f2af89f 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv04.c @@ -24,33 +24,21 @@ #include -#include -#include - struct nv04_disp_priv { struct nouveau_disp base; }; static struct nouveau_oclass nv04_disp_sclass[] = { - { NV04_DISP_CLASS, &nouveau_object_ofuncs }, {}, }; -/******************************************************************************* - * Display engine implementation - ******************************************************************************/ - -static void -nv04_disp_vblank_enable(struct nouveau_event *event, int head) -{ - nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000001); -} - static void -nv04_disp_vblank_disable(struct nouveau_event *event, int head) +nv04_disp_intr_vblank(struct nv04_disp_priv *priv, int crtc) { - nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000000); + struct nouveau_disp *disp = &priv->base; + if (disp->vblank.notify) + disp->vblank.notify(disp->vblank.data, crtc); } static void @@ -61,25 +49,25 @@ nv04_disp_intr(struct nouveau_subdev *subdev) u32 crtc1 = nv_rd32(priv, 0x602100); if (crtc0 & 0x00000001) { - nouveau_event_trigger(priv->base.vblank, 0); + nv04_disp_intr_vblank(priv, 0); nv_wr32(priv, 0x600100, 0x00000001); } if (crtc1 & 0x00000001) { - nouveau_event_trigger(priv->base.vblank, 1); + nv04_disp_intr_vblank(priv, 1); nv_wr32(priv, 0x602100, 0x00000001); } } static int nv04_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { struct nv04_disp_priv *priv; int ret; - ret = nouveau_disp_create(parent, engine, oclass, 2, "DISPLAY", + ret = nouveau_disp_create(parent, engine, oclass, "DISPLAY", "display", &priv); *pobject = nv_object(priv); if (ret) @@ -87,9 +75,6 @@ nv04_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->sclass = nv04_disp_sclass; nv_subdev(priv)->intr = nv04_disp_intr; - priv->base.vblank->priv = priv; - priv->base.vblank->enable = nv04_disp_vblank_enable; - priv->base.vblank->disable = nv04_disp_vblank_disable; return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 5fa13267bd9f..ca1a7d76a95b 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -36,6 +37,7 @@ #include #include #include +#include #include #include "nv50.h" @@ -333,7 +335,7 @@ nv50_disp_sync_ctor(struct nouveau_object *parent, struct nv50_disp_dmac *dmac; int ret; - if (size < sizeof(*args) || args->head > 1) + if (size < sizeof(*data) || args->head > 1) return -EINVAL; ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf, @@ -372,7 +374,7 @@ nv50_disp_ovly_ctor(struct nouveau_object *parent, struct nv50_disp_dmac *dmac; int ret; - if (size < sizeof(*args) || args->head > 1) + if (size < sizeof(*data) || args->head > 1) return -EINVAL; ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf, @@ -541,18 +543,6 @@ nv50_disp_curs_ofuncs = { * Base display object ******************************************************************************/ -static void -nv50_disp_base_vblank_enable(struct nouveau_event *event, int head) -{ - nv_mask(event->priv, 0x61002c, (1 << head), (1 << head)); -} - -static void -nv50_disp_base_vblank_disable(struct nouveau_event *event, int head) -{ - nv_mask(event->priv, 0x61002c, (1 << head), (0 << head)); -} - static int nv50_disp_base_ctor(struct nouveau_object *parent, struct nouveau_object *engine, @@ -569,9 +559,6 @@ nv50_disp_base_ctor(struct nouveau_object *parent, if (ret) return ret; - priv->base.vblank->priv = priv; - priv->base.vblank->enable = nv50_disp_base_vblank_enable; - priv->base.vblank->disable = nv50_disp_base_vblank_disable; return nouveau_ramht_new(parent, parent, 0x1000, 0, &base->ramht); } @@ -626,7 +613,7 @@ nv50_disp_base_init(struct nouveau_object *object) nv_wr32(priv, 0x6101e0 + (i * 0x04), tmp); } - /* ... PIOR caps */ + /* ... EXT caps */ for (i = 0; i < 3; i++) { tmp = nv_rd32(priv, 0x61e000 + (i * 0x800)); nv_wr32(priv, 0x6101f0 + (i * 0x04), tmp); @@ -678,9 +665,6 @@ nv50_disp_base_omthds[] = { { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, - { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, - { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, - { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd }, {}, }; @@ -772,6 +756,50 @@ nv50_disp_intr_error(struct nv50_disp_priv *priv) } } +static void +nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) +{ + struct nouveau_bar *bar = nouveau_bar(priv); + struct nouveau_disp *disp = &priv->base; + struct nouveau_software_chan *chan, *temp; + unsigned long flags; + + spin_lock_irqsave(&disp->vblank.lock, flags); + list_for_each_entry_safe(chan, temp, &disp->vblank.list, vblank.head) { + if (chan->vblank.crtc != crtc) + continue; + + if (nv_device(priv)->chipset >= 0xc0) { + nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel); + bar->flush(bar); + nv_wr32(priv, 0x06000c, + upper_32_bits(chan->vblank.offset)); + nv_wr32(priv, 0x060010, + lower_32_bits(chan->vblank.offset)); + nv_wr32(priv, 0x060014, chan->vblank.value); + } else { + nv_wr32(priv, 0x001704, chan->vblank.channel); + nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); + bar->flush(bar); + if (nv_device(priv)->chipset == 0x50) { + nv_wr32(priv, 0x001570, chan->vblank.offset); + nv_wr32(priv, 0x001574, chan->vblank.value); + } else { + nv_wr32(priv, 0x060010, chan->vblank.offset); + nv_wr32(priv, 0x060014, chan->vblank.value); + } + } + + list_del(&chan->vblank.head); + if (disp->vblank.put) + disp->vblank.put(disp->vblank.data, crtc); + } + spin_unlock_irqrestore(&disp->vblank.lock, flags); + + if (disp->vblank.notify) + disp->vblank.notify(disp->vblank.data, crtc); +} + static u16 exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, @@ -783,8 +811,8 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, if (outp < 4) { type = DCB_OUTPUT_ANALOG; mask = 0; - } else - if (outp < 8) { + } else { + outp -= 4; switch (ctrl & 0x00000f00) { case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break; case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break; @@ -796,17 +824,6 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); return 0x0000; } - outp -= 4; - } else { - outp = outp - 8; - type = 0x0010; - mask = 0; - switch (ctrl & 0x00000f00) { - case 0x00000000: type |= priv->pior.type[outp]; break; - default: - nv_error(priv, "unknown PIOR mc 0x%08x\n", ctrl); - return 0x0000; - } } mask = 0x00c0 & (mask << 6); @@ -817,10 +834,6 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, if (!data) return 0x0000; - /* off-chip encoders require matching the exact encoder type */ - if (dcb->location != 0) - type |= dcb->extdev << 8; - return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info); } @@ -835,11 +848,9 @@ exec_script(struct nv50_disp_priv *priv, int head, int id) u32 ctrl = 0x00000000; int i; - /* DAC */ for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) ctrl = nv_rd32(priv, 0x610b5c + (i * 8)); - /* SOR */ if (!(ctrl & (1 << head))) { if (nv_device(priv)->chipset < 0x90 || nv_device(priv)->chipset == 0x92 || @@ -854,13 +865,6 @@ exec_script(struct nv50_disp_priv *priv, int head, int id) } } - /* PIOR */ - if (!(ctrl & (1 << head))) { - for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) - ctrl = nv_rd32(priv, 0x610b84 + (i * 8)); - i += 8; - } - if (!(ctrl & (1 << head))) return false; i--; @@ -890,15 +894,13 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, struct nvbios_outp info1; struct nvbios_ocfg info2; u8 ver, hdr, cnt, len; + u16 data, conf; u32 ctrl = 0x00000000; - u32 data, conf = ~0; int i; - /* DAC */ for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) ctrl = nv_rd32(priv, 0x610b58 + (i * 8)); - /* SOR */ if (!(ctrl & (1 << head))) { if (nv_device(priv)->chipset < 0x90 || nv_device(priv)->chipset == 0x92 || @@ -913,46 +915,34 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, } } - /* PIOR */ - if (!(ctrl & (1 << head))) { - for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) - ctrl = nv_rd32(priv, 0x610b80 + (i * 8)); - i += 8; - } - if (!(ctrl & (1 << head))) - return conf; + return 0x0000; i--; data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1); if (!data) - return conf; - - if (outp->location == 0) { - switch (outp->type) { - case DCB_OUTPUT_TMDS: - conf = (ctrl & 0x00000f00) >> 8; - if (pclk >= 165000) - conf |= 0x0100; - break; - case DCB_OUTPUT_LVDS: - conf = priv->sor.lvdsconf; - break; - case DCB_OUTPUT_DP: - conf = (ctrl & 0x00000f00) >> 8; - break; - case DCB_OUTPUT_ANALOG: - default: - conf = 0x00ff; - break; - } - } else { + return 0x0000; + + switch (outp->type) { + case DCB_OUTPUT_TMDS: + conf = (ctrl & 0x00000f00) >> 8; + if (pclk >= 165000) + conf |= 0x0100; + break; + case DCB_OUTPUT_LVDS: + conf = priv->sor.lvdsconf; + break; + case DCB_OUTPUT_DP: conf = (ctrl & 0x00000f00) >> 8; - pclk = pclk / 2; + break; + case DCB_OUTPUT_ANALOG: + default: + conf = 0x00ff; + break; } data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2); - if (data && id < 0xff) { + if (data) { data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk); if (data) { struct nvbios_init init = { @@ -964,37 +954,32 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, .execute = 1, }; - nvbios_exec(&init); + if (nvbios_exec(&init)) + return 0x0000; + return conf; } } - return conf; -} - -static void -nv50_disp_intr_unk10_0(struct nv50_disp_priv *priv, int head) -{ - exec_script(priv, head, 1); + return 0x0000; } static void -nv50_disp_intr_unk20_0(struct nv50_disp_priv *priv, int head) +nv50_disp_intr_unk10(struct nv50_disp_priv *priv, u32 super) { - exec_script(priv, head, 2); -} + int head = ffs((super & 0x00000060) >> 5) - 1; + if (head >= 0) { + head = ffs((super & 0x00000180) >> 7) - 1; + if (head >= 0) + exec_script(priv, head, 1); + } -static void -nv50_disp_intr_unk20_1(struct nv50_disp_priv *priv, int head) -{ - struct nouveau_clock *clk = nouveau_clock(priv); - u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; - if (pclk) - clk->pll_set(clk, PLL_VPLL0 + head, pclk); + nv_wr32(priv, 0x610024, 0x00000010); + nv_wr32(priv, 0x610030, 0x80000000); } static void -nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv, - struct dcb_output *outp, u32 pclk) +nv50_disp_intr_unk20_dp(struct nv50_disp_priv *priv, + struct dcb_output *outp, u32 pclk) { const int link = !(outp->sorconf.link & 1); const int or = ffs(outp->or) - 1; @@ -1100,54 +1085,53 @@ nv50_disp_intr_unk20_2_dp(struct nv50_disp_priv *priv, } static void -nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head) +nv50_disp_intr_unk20(struct nv50_disp_priv *priv, u32 super) { struct dcb_output outp; - u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; - u32 hval, hreg = 0x614200 + (head * 0x800); - u32 oval, oreg; - u32 conf = exec_clkcmp(priv, head, 0xff, pclk, &outp); - if (conf != ~0) { - if (outp.location == 0 && outp.type == DCB_OUTPUT_DP) { - u32 soff = (ffs(outp.or) - 1) * 0x08; - u32 ctrl = nv_rd32(priv, 0x610798 + soff); - u32 datarate; - - switch ((ctrl & 0x000f0000) >> 16) { - case 6: datarate = pclk * 30 / 8; break; - case 5: datarate = pclk * 24 / 8; break; - case 2: - default: - datarate = pclk * 18 / 8; - break; - } + u32 addr, mask, data; + int head; - nouveau_dp_train(&priv->base, priv->sor.dp, - &outp, head, datarate); + /* finish detaching encoder? */ + head = ffs((super & 0x00000180) >> 7) - 1; + if (head >= 0) + exec_script(priv, head, 2); + + /* check whether a vpll change is required */ + head = ffs((super & 0x00000600) >> 9) - 1; + if (head >= 0) { + u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; + if (pclk) { + struct nouveau_clock *clk = nouveau_clock(priv); + clk->pll_set(clk, PLL_VPLL0 + head, pclk); } - exec_clkcmp(priv, head, 0, pclk, &outp); - - if (!outp.location && outp.type == DCB_OUTPUT_ANALOG) { - oreg = 0x614280 + (ffs(outp.or) - 1) * 0x800; - oval = 0x00000000; - hval = 0x00000000; - } else - if (!outp.location) { - if (outp.type == DCB_OUTPUT_DP) - nv50_disp_intr_unk20_2_dp(priv, &outp, pclk); - oreg = 0x614300 + (ffs(outp.or) - 1) * 0x800; - oval = (conf & 0x0100) ? 0x00000101 : 0x00000000; - hval = 0x00000000; - } else { - oreg = 0x614380 + (ffs(outp.or) - 1) * 0x800; - oval = 0x00000001; - hval = 0x00000001; - } + nv_mask(priv, 0x614200 + head * 0x800, 0x0000000f, 0x00000000); + } - nv_mask(priv, hreg, 0x0000000f, hval); - nv_mask(priv, oreg, 0x00000707, oval); + /* (re)attach the relevant OR to the head */ + head = ffs((super & 0x00000180) >> 7) - 1; + if (head >= 0) { + u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; + u32 conf = exec_clkcmp(priv, head, 0, pclk, &outp); + if (conf) { + if (outp.type == DCB_OUTPUT_ANALOG) { + addr = 0x614280 + (ffs(outp.or) - 1) * 0x800; + mask = 0xffffffff; + data = 0x00000000; + } else { + if (outp.type == DCB_OUTPUT_DP) + nv50_disp_intr_unk20_dp(priv, &outp, pclk); + addr = 0x614300 + (ffs(outp.or) - 1) * 0x800; + mask = 0x00000707; + data = (conf & 0x0100) ? 0x0101 : 0x0000; + } + + nv_mask(priv, addr, mask, data); + } } + + nv_wr32(priv, 0x610024, 0x00000020); + nv_wr32(priv, 0x610030, 0x80000000); } /* If programming a TMDS output on a SOR that can also be configured for @@ -1159,7 +1143,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head) * programmed for DisplayPort. */ static void -nv50_disp_intr_unk40_0_tmds(struct nv50_disp_priv *priv, struct dcb_output *outp) +nv50_disp_intr_unk40_tmds(struct nv50_disp_priv *priv, struct dcb_output *outp) { struct nouveau_bios *bios = nouveau_bios(priv); const int link = !(outp->sorconf.link & 1); @@ -1173,79 +1157,35 @@ nv50_disp_intr_unk40_0_tmds(struct nv50_disp_priv *priv, struct dcb_output *outp } static void -nv50_disp_intr_unk40_0(struct nv50_disp_priv *priv, int head) +nv50_disp_intr_unk40(struct nv50_disp_priv *priv, u32 super) { - struct dcb_output outp; - u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; - if (exec_clkcmp(priv, head, 1, pclk, &outp) != ~0) { - if (outp.location == 0 && outp.type == DCB_OUTPUT_TMDS) - nv50_disp_intr_unk40_0_tmds(priv, &outp); - else - if (outp.location == 1 && outp.type == DCB_OUTPUT_DP) { - u32 soff = (ffs(outp.or) - 1) * 0x08; - u32 ctrl = nv_rd32(priv, 0x610b84 + soff); - u32 datarate; - - switch ((ctrl & 0x000f0000) >> 16) { - case 6: datarate = pclk * 30 / 8; break; - case 5: datarate = pclk * 24 / 8; break; - case 2: - default: - datarate = pclk * 18 / 8; - break; - } - - nouveau_dp_train(&priv->base, priv->pior.dp, - &outp, head, datarate); + int head = ffs((super & 0x00000180) >> 7) - 1; + if (head >= 0) { + struct dcb_output outp; + u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; + if (pclk && exec_clkcmp(priv, head, 1, pclk, &outp)) { + if (outp.type == DCB_OUTPUT_TMDS) + nv50_disp_intr_unk40_tmds(priv, &outp); } } + + nv_wr32(priv, 0x610024, 0x00000040); + nv_wr32(priv, 0x610030, 0x80000000); } -void -nv50_disp_intr_supervisor(struct work_struct *work) +static void +nv50_disp_intr_super(struct nv50_disp_priv *priv, u32 intr1) { - struct nv50_disp_priv *priv = - container_of(work, struct nv50_disp_priv, supervisor); u32 super = nv_rd32(priv, 0x610030); - int head; - nv_debug(priv, "supervisor 0x%08x 0x%08x\n", priv->super, super); + nv_debug(priv, "supervisor 0x%08x 0x%08x\n", intr1, super); - if (priv->super & 0x00000010) { - for (head = 0; head < priv->head.nr; head++) { - if (!(super & (0x00000020 << head))) - continue; - if (!(super & (0x00000080 << head))) - continue; - nv50_disp_intr_unk10_0(priv, head); - } - } else - if (priv->super & 0x00000020) { - for (head = 0; head < priv->head.nr; head++) { - if (!(super & (0x00000080 << head))) - continue; - nv50_disp_intr_unk20_0(priv, head); - } - for (head = 0; head < priv->head.nr; head++) { - if (!(super & (0x00000200 << head))) - continue; - nv50_disp_intr_unk20_1(priv, head); - } - for (head = 0; head < priv->head.nr; head++) { - if (!(super & (0x00000080 << head))) - continue; - nv50_disp_intr_unk20_2(priv, head); - } - } else - if (priv->super & 0x00000040) { - for (head = 0; head < priv->head.nr; head++) { - if (!(super & (0x00000080 << head))) - continue; - nv50_disp_intr_unk40_0(priv, head); - } - } - - nv_wr32(priv, 0x610030, 0x80000000); + if (intr1 & 0x00000010) + nv50_disp_intr_unk10(priv, super); + if (intr1 & 0x00000020) + nv50_disp_intr_unk20(priv, super); + if (intr1 & 0x00000040) + nv50_disp_intr_unk40(priv, super); } void @@ -1261,21 +1201,19 @@ nv50_disp_intr(struct nouveau_subdev *subdev) } if (intr1 & 0x00000004) { - nouveau_event_trigger(priv->base.vblank, 0); + nv50_disp_intr_vblank(priv, 0); nv_wr32(priv, 0x610024, 0x00000004); intr1 &= ~0x00000004; } if (intr1 & 0x00000008) { - nouveau_event_trigger(priv->base.vblank, 1); + nv50_disp_intr_vblank(priv, 1); nv_wr32(priv, 0x610024, 0x00000008); intr1 &= ~0x00000008; } if (intr1 & 0x00000070) { - priv->super = (intr1 & 0x00000070); - schedule_work(&priv->supervisor); - nv_wr32(priv, 0x610024, priv->super); + nv50_disp_intr_super(priv, intr1); intr1 &= ~0x00000070; } } @@ -1288,7 +1226,7 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nv50_disp_priv *priv; int ret; - ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP", + ret = nouveau_disp_create(parent, engine, oclass, "PDISP", "display", &priv); *pobject = nv_object(priv); if (ret) @@ -1297,17 +1235,16 @@ nv50_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->sclass = nv50_disp_base_oclass; nv_engine(priv)->cclass = &nv50_disp_cclass; nv_subdev(priv)->intr = nv50_disp_intr; - INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); priv->sclass = nv50_disp_sclass; priv->head.nr = 2; priv->dac.nr = 3; priv->sor.nr = 2; - priv->pior.nr = 3; priv->dac.power = nv50_dac_power; priv->dac.sense = nv50_dac_sense; priv->sor.power = nv50_sor_power; - priv->pior.power = nv50_pior_power; - priv->pior.dp = &nv50_pior_dp_func; + + INIT_LIST_HEAD(&priv->base.vblank.list); + spin_lock_init(&priv->base.vblank.lock); return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h index 1ae6ceb56704..a6bb931450f1 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv50.h @@ -3,22 +3,16 @@ #include #include -#include #include -#include #include #include -#include "dport.h" +struct dcb_output; struct nv50_disp_priv { struct nouveau_disp base; struct nouveau_oclass *sclass; - - struct work_struct supervisor; - u32 super; - struct { int nr; } head; @@ -32,15 +26,23 @@ struct nv50_disp_priv { int (*power)(struct nv50_disp_priv *, int sor, u32 data); int (*hda_eld)(struct nv50_disp_priv *, int sor, u8 *, u32); int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32); + int (*dp_train_init)(struct nv50_disp_priv *, int sor, int link, + int head, u16 type, u16 mask, u32 data, + struct dcb_output *); + int (*dp_train_fini)(struct nv50_disp_priv *, int sor, int link, + int head, u16 type, u16 mask, u32 data, + struct dcb_output *); + int (*dp_train)(struct nv50_disp_priv *, int sor, int link, + u16 type, u16 mask, u32 data, + struct dcb_output *); + int (*dp_lnkctl)(struct nv50_disp_priv *, int sor, int link, + int head, u16 type, u16 mask, u32 data, + struct dcb_output *); + int (*dp_drvctl)(struct nv50_disp_priv *, int sor, int link, + int lane, u16 type, u16 mask, u32 data, + struct dcb_output *); u32 lvdsconf; - const struct nouveau_dp_func *dp; } sor; - struct { - int nr; - int (*power)(struct nv50_disp_priv *, int ext, u32 data); - u8 type[3]; - const struct nouveau_dp_func *dp; - } pior; }; #define DAC_MTHD(n) (n), (n) + 0x03 @@ -79,11 +81,6 @@ int nvd0_sor_dp_lnkctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32, int nvd0_sor_dp_drvctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32, struct dcb_output *); -#define PIOR_MTHD(n) (n), (n) + 0x03 - -int nv50_pior_mthd(struct nouveau_object *, u32, void *, u32); -int nv50_pior_power(struct nv50_disp_priv *, int, u32); - struct nv50_disp_base { struct nouveau_parent base; struct nouveau_ramht *ramht; @@ -127,7 +124,6 @@ extern struct nouveau_ofuncs nv50_disp_oimm_ofuncs; extern struct nouveau_ofuncs nv50_disp_curs_ofuncs; extern struct nouveau_ofuncs nv50_disp_base_ofuncs; extern struct nouveau_oclass nv50_disp_cclass; -void nv50_disp_intr_supervisor(struct work_struct *); void nv50_disp_intr(struct nouveau_subdev *); extern struct nouveau_omthds nv84_disp_base_omthds[]; @@ -141,7 +137,6 @@ extern struct nouveau_ofuncs nvd0_disp_oimm_ofuncs; extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs; extern struct nouveau_ofuncs nvd0_disp_base_ofuncs; extern struct nouveau_oclass nvd0_disp_cclass; -void nvd0_disp_intr_supervisor(struct work_struct *); void nvd0_disp_intr(struct nouveau_subdev *); #endif diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c index d8c74c0883a1..fc84eacdfbec 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv84.c @@ -46,9 +46,6 @@ nv84_disp_base_omthds[] = { { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, - { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, - { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, - { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd }, {}, }; @@ -66,7 +63,7 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nv50_disp_priv *priv; int ret; - ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP", + ret = nouveau_disp_create(parent, engine, oclass, "PDISP", "display", &priv); *pobject = nv_object(priv); if (ret) @@ -75,18 +72,17 @@ nv84_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->sclass = nv84_disp_base_oclass; nv_engine(priv)->cclass = &nv50_disp_cclass; nv_subdev(priv)->intr = nv50_disp_intr; - INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); priv->sclass = nv84_disp_sclass; priv->head.nr = 2; priv->dac.nr = 3; priv->sor.nr = 2; - priv->pior.nr = 3; priv->dac.power = nv50_dac_power; priv->dac.sense = nv50_dac_sense; priv->sor.power = nv50_sor_power; priv->sor.hdmi = nv84_hdmi_ctrl; - priv->pior.power = nv50_pior_power; - priv->pior.dp = &nv50_pior_dp_func; + + INIT_LIST_HEAD(&priv->base.vblank.list); + spin_lock_init(&priv->base.vblank.lock); return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c index a66f949c1f84..ba9dfd4669a2 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nv94.c @@ -44,11 +44,14 @@ nv94_disp_base_omthds[] = { { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, + { SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd }, + { SOR_MTHD(NV94_DISP_SOR_DP_LNKCTL) , nv50_sor_mthd }, + { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(0)), nv50_sor_mthd }, + { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(1)), nv50_sor_mthd }, + { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(2)), nv50_sor_mthd }, + { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(3)), nv50_sor_mthd }, { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, - { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, - { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, - { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd }, {}, }; @@ -66,7 +69,7 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nv50_disp_priv *priv; int ret; - ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP", + ret = nouveau_disp_create(parent, engine, oclass, "PDISP", "display", &priv); *pobject = nv_object(priv); if (ret) @@ -75,19 +78,22 @@ nv94_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->sclass = nv94_disp_base_oclass; nv_engine(priv)->cclass = &nv50_disp_cclass; nv_subdev(priv)->intr = nv50_disp_intr; - INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); priv->sclass = nv94_disp_sclass; priv->head.nr = 2; priv->dac.nr = 3; priv->sor.nr = 4; - priv->pior.nr = 3; priv->dac.power = nv50_dac_power; priv->dac.sense = nv50_dac_sense; priv->sor.power = nv50_sor_power; priv->sor.hdmi = nv84_hdmi_ctrl; - priv->sor.dp = &nv94_sor_dp_func; - priv->pior.power = nv50_pior_power; - priv->pior.dp = &nv50_pior_dp_func; + priv->sor.dp_train = nv94_sor_dp_train; + priv->sor.dp_train_init = nv94_sor_dp_train_init; + priv->sor.dp_train_fini = nv94_sor_dp_train_fini; + priv->sor.dp_lnkctl = nv94_sor_dp_lnkctl; + priv->sor.dp_drvctl = nv94_sor_dp_drvctl; + + INIT_LIST_HEAD(&priv->base.vblank.list); + spin_lock_init(&priv->base.vblank.lock); return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c index 6cf8eefac368..5d63902cdeda 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nva0.c @@ -53,7 +53,7 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nv50_disp_priv *priv; int ret; - ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP", + ret = nouveau_disp_create(parent, engine, oclass, "PDISP", "display", &priv); *pobject = nv_object(priv); if (ret) @@ -62,18 +62,17 @@ nva0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->sclass = nva0_disp_base_oclass; nv_engine(priv)->cclass = &nv50_disp_cclass; nv_subdev(priv)->intr = nv50_disp_intr; - INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); priv->sclass = nva0_disp_sclass; priv->head.nr = 2; priv->dac.nr = 3; priv->sor.nr = 2; - priv->pior.nr = 3; priv->dac.power = nv50_dac_power; priv->dac.sense = nv50_dac_sense; priv->sor.power = nv50_sor_power; priv->sor.hdmi = nv84_hdmi_ctrl; - priv->pior.power = nv50_pior_power; - priv->pior.dp = &nv50_pior_dp_func; + + INIT_LIST_HEAD(&priv->base.vblank.list); + spin_lock_init(&priv->base.vblank.lock); return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c index b75413169eae..e9192ca389fa 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nva3.c @@ -45,11 +45,14 @@ nva3_disp_base_omthds[] = { { SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd }, { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, + { SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd }, + { SOR_MTHD(NV94_DISP_SOR_DP_LNKCTL) , nv50_sor_mthd }, + { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(0)), nv50_sor_mthd }, + { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(1)), nv50_sor_mthd }, + { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(2)), nv50_sor_mthd }, + { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(3)), nv50_sor_mthd }, { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, - { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, - { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, - { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd }, {}, }; @@ -67,7 +70,7 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nv50_disp_priv *priv; int ret; - ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP", + ret = nouveau_disp_create(parent, engine, oclass, "PDISP", "display", &priv); *pobject = nv_object(priv); if (ret) @@ -76,20 +79,23 @@ nva3_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->sclass = nva3_disp_base_oclass; nv_engine(priv)->cclass = &nv50_disp_cclass; nv_subdev(priv)->intr = nv50_disp_intr; - INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); priv->sclass = nva3_disp_sclass; priv->head.nr = 2; priv->dac.nr = 3; priv->sor.nr = 4; - priv->pior.nr = 3; priv->dac.power = nv50_dac_power; priv->dac.sense = nv50_dac_sense; priv->sor.power = nv50_sor_power; priv->sor.hda_eld = nva3_hda_eld; priv->sor.hdmi = nva3_hdmi_ctrl; - priv->sor.dp = &nv94_sor_dp_func; - priv->pior.power = nv50_pior_power; - priv->pior.dp = &nv50_pior_dp_func; + priv->sor.dp_train = nv94_sor_dp_train; + priv->sor.dp_train_init = nv94_sor_dp_train_init; + priv->sor.dp_train_fini = nv94_sor_dp_train_fini; + priv->sor.dp_lnkctl = nv94_sor_dp_lnkctl; + priv->sor.dp_drvctl = nv94_sor_dp_drvctl; + + INIT_LIST_HEAD(&priv->base.vblank.list); + spin_lock_init(&priv->base.vblank.lock); return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c index 788dd34ccb54..9e38ebff5fb3 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c @@ -27,10 +27,12 @@ #include #include +#include #include #include #include +#include #include #include @@ -228,7 +230,7 @@ nvd0_disp_sync_ctor(struct nouveau_object *parent, struct nv50_disp_dmac *dmac; int ret; - if (size < sizeof(*args) || args->head >= priv->head.nr) + if (size < sizeof(*data) || args->head >= priv->head.nr) return -EINVAL; ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf, @@ -268,7 +270,7 @@ nvd0_disp_ovly_ctor(struct nouveau_object *parent, struct nv50_disp_dmac *dmac; int ret; - if (size < sizeof(*args) || args->head >= priv->head.nr) + if (size < sizeof(*data) || args->head >= priv->head.nr) return -EINVAL; ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf, @@ -441,18 +443,6 @@ nvd0_disp_curs_ofuncs = { * Base display object ******************************************************************************/ -static void -nvd0_disp_base_vblank_enable(struct nouveau_event *event, int head) -{ - nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001); -} - -static void -nvd0_disp_base_vblank_disable(struct nouveau_event *event, int head) -{ - nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000); -} - static int nvd0_disp_base_ctor(struct nouveau_object *parent, struct nouveau_object *engine, @@ -469,10 +459,6 @@ nvd0_disp_base_ctor(struct nouveau_object *parent, if (ret) return ret; - priv->base.vblank->priv = priv; - priv->base.vblank->enable = nvd0_disp_base_vblank_enable; - priv->base.vblank->disable = nvd0_disp_base_vblank_disable; - return nouveau_ramht_new(parent, parent, 0x1000, 0, &base->ramht); } @@ -623,24 +609,13 @@ exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, } static bool -exec_script(struct nv50_disp_priv *priv, int head, int id) +exec_script(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, int id) { struct nouveau_bios *bios = nouveau_bios(priv); struct nvbios_outp info; struct dcb_output dcb; u8 ver, hdr, cnt, len; - u32 ctrl = 0x00000000; u16 data; - int outp; - - for (outp = 0; !(ctrl & (1 << head)) && outp < 8; outp++) { - ctrl = nv_rd32(priv, 0x640180 + (outp * 0x20)); - if (ctrl & (1 << head)) - break; - } - - if (outp == 8) - return false; data = exec_lookup(priv, head, outp, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info); if (data) { @@ -660,31 +635,21 @@ exec_script(struct nv50_disp_priv *priv, int head, int id) } static u32 -exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, - u32 pclk, struct dcb_output *dcb) +exec_clkcmp(struct nv50_disp_priv *priv, int head, int outp, + u32 ctrl, int id, u32 pclk) { struct nouveau_bios *bios = nouveau_bios(priv); struct nvbios_outp info1; struct nvbios_ocfg info2; + struct dcb_output dcb; u8 ver, hdr, cnt, len; - u32 ctrl = 0x00000000; - u32 data, conf = ~0; - int outp; + u16 data, conf; - for (outp = 0; !(ctrl & (1 << head)) && outp < 8; outp++) { - ctrl = nv_rd32(priv, 0x660180 + (outp * 0x20)); - if (ctrl & (1 << head)) - break; - } - - if (outp == 8) - return false; - - data = exec_lookup(priv, head, outp, ctrl, dcb, &ver, &hdr, &cnt, &len, &info1); + data = exec_lookup(priv, head, outp, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info1); if (data == 0x0000) - return conf; + return false; - switch (dcb->type) { + switch (dcb.type) { case DCB_OUTPUT_TMDS: conf = (ctrl & 0x00000f00) >> 8; if (pclk >= 165000) @@ -703,52 +668,46 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, } data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2); - if (data && id < 0xff) { + if (data) { data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk); if (data) { struct nvbios_init init = { .subdev = nv_subdev(priv), .bios = bios, .offset = data, - .outp = dcb, + .outp = &dcb, .crtc = head, .execute = 1, }; - nvbios_exec(&init); + if (nvbios_exec(&init)) + return 0x0000; + return conf; } } - return conf; + return 0x0000; } static void -nvd0_disp_intr_unk1_0(struct nv50_disp_priv *priv, int head) +nvd0_display_unk1_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) { - exec_script(priv, head, 1); -} + int i; -static void -nvd0_disp_intr_unk2_0(struct nv50_disp_priv *priv, int head) -{ - exec_script(priv, head, 2); -} + for (i = 0; mask && i < 8; i++) { + u32 mcc = nv_rd32(priv, 0x640180 + (i * 0x20)); + if (mcc & (1 << head)) + exec_script(priv, head, i, mcc, 1); + } -static void -nvd0_disp_intr_unk2_1(struct nv50_disp_priv *priv, int head) -{ - struct nouveau_clock *clk = nouveau_clock(priv); - u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; - if (pclk) - clk->pll_set(clk, PLL_VPLL0 + head, pclk); - nv_wr32(priv, 0x612200 + (head * 0x800), 0x00000000); + nv_wr32(priv, 0x6101d4, 0x00000000); + nv_wr32(priv, 0x6109d4, 0x00000000); + nv_wr32(priv, 0x6101d0, 0x80000000); } static void -nvd0_disp_intr_unk2_2_tu(struct nv50_disp_priv *priv, int head, - struct dcb_output *outp) +nvd0_display_unk2_calc_tu(struct nv50_disp_priv *priv, int head, int or) { - const int or = ffs(outp->or) - 1; const u32 ctrl = nv_rd32(priv, 0x660200 + (or * 0x020)); const u32 conf = nv_rd32(priv, 0x660404 + (head * 0x300)); const u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; @@ -791,104 +750,107 @@ nvd0_disp_intr_unk2_2_tu(struct nv50_disp_priv *priv, int head, } static void -nvd0_disp_intr_unk2_2(struct nv50_disp_priv *priv, int head) +nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) { - struct dcb_output outp; - u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; - u32 conf = exec_clkcmp(priv, head, 0xff, pclk, &outp); - if (conf != ~0) { - u32 addr, data; - - if (outp.type == DCB_OUTPUT_DP) { - u32 sync = nv_rd32(priv, 0x660404 + (head * 0x300)); - switch ((sync & 0x000003c0) >> 6) { - case 6: pclk = pclk * 30 / 8; break; - case 5: pclk = pclk * 24 / 8; break; - case 2: - default: - pclk = pclk * 18 / 8; - break; - } + u32 pclk; + int i; - nouveau_dp_train(&priv->base, priv->sor.dp, - &outp, head, pclk); - } + for (i = 0; mask && i < 8; i++) { + u32 mcc = nv_rd32(priv, 0x640180 + (i * 0x20)); + if (mcc & (1 << head)) + exec_script(priv, head, i, mcc, 2); + } - exec_clkcmp(priv, head, 0, pclk, &outp); + pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; + nv_debug(priv, "head %d pclk %d mask 0x%08x\n", head, pclk, mask); + if (pclk && (mask & 0x00010000)) { + struct nouveau_clock *clk = nouveau_clock(priv); + clk->pll_set(clk, PLL_VPLL0 + head, pclk); + } - if (outp.type == DCB_OUTPUT_ANALOG) { - addr = 0x612280 + (ffs(outp.or) - 1) * 0x800; - data = 0x00000000; - } else { - if (outp.type == DCB_OUTPUT_DP) - nvd0_disp_intr_unk2_2_tu(priv, head, &outp); - addr = 0x612300 + (ffs(outp.or) - 1) * 0x800; - data = (conf & 0x0100) ? 0x00000101 : 0x00000000; - } + nv_wr32(priv, 0x612200 + (head * 0x800), 0x00000000); - nv_mask(priv, addr, 0x00000707, data); + for (i = 0; mask && i < 8; i++) { + u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20)), cfg; + if (mcp & (1 << head)) { + if ((cfg = exec_clkcmp(priv, head, i, mcp, 0, pclk))) { + u32 addr, mask, data = 0x00000000; + if (i < 4) { + addr = 0x612280 + ((i - 0) * 0x800); + mask = 0xffffffff; + } else { + switch (mcp & 0x00000f00) { + case 0x00000800: + case 0x00000900: + nvd0_display_unk2_calc_tu(priv, head, i - 4); + break; + default: + break; + } + + addr = 0x612300 + ((i - 4) * 0x800); + mask = 0x00000707; + if (cfg & 0x00000100) + data = 0x00000101; + } + nv_mask(priv, addr, mask, data); + } + break; + } } + + nv_wr32(priv, 0x6101d4, 0x00000000); + nv_wr32(priv, 0x6109d4, 0x00000000); + nv_wr32(priv, 0x6101d0, 0x80000000); } static void -nvd0_disp_intr_unk4_0(struct nv50_disp_priv *priv, int head) +nvd0_display_unk4_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) { - struct dcb_output outp; - u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; - exec_clkcmp(priv, head, 1, pclk, &outp); -} + int pclk, i; -void -nvd0_disp_intr_supervisor(struct work_struct *work) -{ - struct nv50_disp_priv *priv = - container_of(work, struct nv50_disp_priv, supervisor); - u32 mask[4]; - int head; - - nv_debug(priv, "supervisor %08x\n", priv->super); - for (head = 0; head < priv->head.nr; head++) { - mask[head] = nv_rd32(priv, 0x6101d4 + (head * 0x800)); - nv_debug(priv, "head %d: 0x%08x\n", head, mask[head]); - } + pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; - if (priv->super & 0x00000001) { - for (head = 0; head < priv->head.nr; head++) { - if (!(mask[head] & 0x00001000)) - continue; - nvd0_disp_intr_unk1_0(priv, head); - } - } else - if (priv->super & 0x00000002) { - for (head = 0; head < priv->head.nr; head++) { - if (!(mask[head] & 0x00001000)) - continue; - nvd0_disp_intr_unk2_0(priv, head); - } - for (head = 0; head < priv->head.nr; head++) { - if (!(mask[head] & 0x00010000)) - continue; - nvd0_disp_intr_unk2_1(priv, head); - } - for (head = 0; head < priv->head.nr; head++) { - if (!(mask[head] & 0x00001000)) - continue; - nvd0_disp_intr_unk2_2(priv, head); - } - } else - if (priv->super & 0x00000004) { - for (head = 0; head < priv->head.nr; head++) { - if (!(mask[head] & 0x00001000)) - continue; - nvd0_disp_intr_unk4_0(priv, head); - } + for (i = 0; mask && i < 8; i++) { + u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20)); + if (mcp & (1 << head)) + exec_clkcmp(priv, head, i, mcp, 1, pclk); } - for (head = 0; head < priv->head.nr; head++) - nv_wr32(priv, 0x6101d4 + (head * 0x800), 0x00000000); + nv_wr32(priv, 0x6101d4, 0x00000000); + nv_wr32(priv, 0x6109d4, 0x00000000); nv_wr32(priv, 0x6101d0, 0x80000000); } +static void +nvd0_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) +{ + struct nouveau_bar *bar = nouveau_bar(priv); + struct nouveau_disp *disp = &priv->base; + struct nouveau_software_chan *chan, *temp; + unsigned long flags; + + spin_lock_irqsave(&disp->vblank.lock, flags); + list_for_each_entry_safe(chan, temp, &disp->vblank.list, vblank.head) { + if (chan->vblank.crtc != crtc) + continue; + + nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel); + bar->flush(bar); + nv_wr32(priv, 0x06000c, upper_32_bits(chan->vblank.offset)); + nv_wr32(priv, 0x060010, lower_32_bits(chan->vblank.offset)); + nv_wr32(priv, 0x060014, chan->vblank.value); + + list_del(&chan->vblank.head); + if (disp->vblank.put) + disp->vblank.put(disp->vblank.data, crtc); + } + spin_unlock_irqrestore(&disp->vblank.lock, flags); + + if (disp->vblank.notify) + disp->vblank.notify(disp->vblank.data, crtc); +} + void nvd0_disp_intr(struct nouveau_subdev *subdev) { @@ -922,11 +884,27 @@ nvd0_disp_intr(struct nouveau_subdev *subdev) if (intr & 0x00100000) { u32 stat = nv_rd32(priv, 0x6100ac); - if (stat & 0x00000007) { - priv->super = (stat & 0x00000007); - schedule_work(&priv->supervisor); - nv_wr32(priv, 0x6100ac, priv->super); - stat &= ~0x00000007; + u32 mask = 0, crtc = ~0; + + while (!mask && ++crtc < priv->head.nr) + mask = nv_rd32(priv, 0x6101d4 + (crtc * 0x800)); + + if (stat & 0x00000001) { + nv_wr32(priv, 0x6100ac, 0x00000001); + nvd0_display_unk1_handler(priv, crtc, mask); + stat &= ~0x00000001; + } + + if (stat & 0x00000002) { + nv_wr32(priv, 0x6100ac, 0x00000002); + nvd0_display_unk2_handler(priv, crtc, mask); + stat &= ~0x00000002; + } + + if (stat & 0x00000004) { + nv_wr32(priv, 0x6100ac, 0x00000004); + nvd0_display_unk4_handler(priv, crtc, mask); + stat &= ~0x00000004; } if (stat) { @@ -942,7 +920,7 @@ nvd0_disp_intr(struct nouveau_subdev *subdev) if (mask & intr) { u32 stat = nv_rd32(priv, 0x6100bc + (i * 0x800)); if (stat & 0x00000001) - nouveau_event_trigger(priv->base.vblank, i); + nvd0_disp_intr_vblank(priv, i); nv_mask(priv, 0x6100bc + (i * 0x800), 0, 0); nv_rd32(priv, 0x6100c0 + (i * 0x800)); } @@ -955,11 +933,10 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_object **pobject) { struct nv50_disp_priv *priv; - int heads = nv_rd32(parent, 0x022448); int ret; - ret = nouveau_disp_create(parent, engine, oclass, heads, - "PDISP", "display", &priv); + ret = nouveau_disp_create(parent, engine, oclass, "PDISP", + "display", &priv); *pobject = nv_object(priv); if (ret) return ret; @@ -967,9 +944,8 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->sclass = nvd0_disp_base_oclass; nv_engine(priv)->cclass = &nv50_disp_cclass; nv_subdev(priv)->intr = nvd0_disp_intr; - INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor); priv->sclass = nvd0_disp_sclass; - priv->head.nr = heads; + priv->head.nr = nv_rd32(priv, 0x022448); priv->dac.nr = 3; priv->sor.nr = 4; priv->dac.power = nv50_dac_power; @@ -977,7 +953,14 @@ nvd0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->sor.power = nv50_sor_power; priv->sor.hda_eld = nvd0_hda_eld; priv->sor.hdmi = nvd0_hdmi_ctrl; - priv->sor.dp = &nvd0_sor_dp_func; + priv->sor.dp_train = nvd0_sor_dp_train; + priv->sor.dp_train_init = nv94_sor_dp_train_init; + priv->sor.dp_train_fini = nv94_sor_dp_train_fini; + priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl; + priv->sor.dp_drvctl = nvd0_sor_dp_drvctl; + + INIT_LIST_HEAD(&priv->base.vblank.list); + spin_lock_init(&priv->base.vblank.lock); return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c index 20725b363d58..259537c4587e 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/nve0.c @@ -51,11 +51,10 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_object **pobject) { struct nv50_disp_priv *priv; - int heads = nv_rd32(parent, 0x022448); int ret; - ret = nouveau_disp_create(parent, engine, oclass, heads, - "PDISP", "display", &priv); + ret = nouveau_disp_create(parent, engine, oclass, "PDISP", + "display", &priv); *pobject = nv_object(priv); if (ret) return ret; @@ -63,9 +62,8 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, nv_engine(priv)->sclass = nve0_disp_base_oclass; nv_engine(priv)->cclass = &nv50_disp_cclass; nv_subdev(priv)->intr = nvd0_disp_intr; - INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor); priv->sclass = nve0_disp_sclass; - priv->head.nr = heads; + priv->head.nr = nv_rd32(priv, 0x022448); priv->dac.nr = 3; priv->sor.nr = 4; priv->dac.power = nv50_dac_power; @@ -73,7 +71,14 @@ nve0_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->sor.power = nv50_sor_power; priv->sor.hda_eld = nvd0_hda_eld; priv->sor.hdmi = nvd0_hdmi_ctrl; - priv->sor.dp = &nvd0_sor_dp_func; + priv->sor.dp_train = nvd0_sor_dp_train; + priv->sor.dp_train_init = nv94_sor_dp_train_init; + priv->sor.dp_train_fini = nv94_sor_dp_train_fini; + priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl; + priv->sor.dp_drvctl = nvd0_sor_dp_drvctl; + + INIT_LIST_HEAD(&priv->base.vblank.list); + spin_lock_init(&priv->base.vblank.lock); return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c deleted file mode 100644 index 2c8ce351b52d..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include -#include - -#include -#include -#include -#include - -#include "nv50.h" - -/****************************************************************************** - * DisplayPort - *****************************************************************************/ -static struct nouveau_i2c_port * -nv50_pior_dp_find(struct nouveau_disp *disp, struct dcb_output *outp) -{ - struct nouveau_i2c *i2c = nouveau_i2c(disp); - return i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(outp->extdev)); -} - -static int -nv50_pior_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp, - int head, int pattern) -{ - struct nouveau_i2c_port *port; - int ret = -EINVAL; - - port = nv50_pior_dp_find(disp, outp); - if (port) { - if (port->func->pattern) - ret = port->func->pattern(port, pattern); - else - ret = 0; - } - - return ret; -} - -static int -nv50_pior_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp, - int head, int lane_nr, int link_bw, bool enh) -{ - struct nouveau_i2c_port *port; - int ret = -EINVAL; - - port = nv50_pior_dp_find(disp, outp); - if (port && port->func->lnk_ctl) - ret = port->func->lnk_ctl(port, lane_nr, link_bw, enh); - - return ret; -} - -static int -nv50_pior_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp, - int head, int lane, int vsw, int pre) -{ - struct nouveau_i2c_port *port; - int ret = -EINVAL; - - port = nv50_pior_dp_find(disp, outp); - if (port) { - if (port->func->drv_ctl) - ret = port->func->drv_ctl(port, lane, vsw, pre); - else - ret = 0; - } - - return ret; -} - -const struct nouveau_dp_func -nv50_pior_dp_func = { - .pattern = nv50_pior_dp_pattern, - .lnk_ctl = nv50_pior_dp_lnk_ctl, - .drv_ctl = nv50_pior_dp_drv_ctl, -}; - -/****************************************************************************** - * General PIOR handling - *****************************************************************************/ -int -nv50_pior_power(struct nv50_disp_priv *priv, int or, u32 data) -{ - const u32 stat = data & NV50_DISP_PIOR_PWR_STATE; - const u32 soff = (or * 0x800); - nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000); - nv_mask(priv, 0x61e004 + soff, 0x80000101, 0x80000000 | stat); - nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000); - return 0; -} - -int -nv50_pior_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) -{ - struct nv50_disp_priv *priv = (void *)object->engine; - const u8 type = (mthd & NV50_DISP_PIOR_MTHD_TYPE) >> 12; - const u8 or = (mthd & NV50_DISP_PIOR_MTHD_OR); - u32 *data = args; - int ret; - - if (size < sizeof(u32)) - return -EINVAL; - - mthd &= ~NV50_DISP_PIOR_MTHD_TYPE; - mthd &= ~NV50_DISP_PIOR_MTHD_OR; - switch (mthd) { - case NV50_DISP_PIOR_PWR: - ret = priv->pior.power(priv, or, data[0]); - priv->pior.type[or] = type; - break; - default: - return -EINVAL; - } - - return ret; -} diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c index ab1e918469a8..39b6b67732d0 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c @@ -79,6 +79,31 @@ nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID; ret = 0; break; + case NV94_DISP_SOR_DP_TRAIN: + switch (data & NV94_DISP_SOR_DP_TRAIN_OP) { + case NV94_DISP_SOR_DP_TRAIN_OP_PATTERN: + ret = priv->sor.dp_train(priv, or, link, type, mask, data, &outp); + break; + case NV94_DISP_SOR_DP_TRAIN_OP_INIT: + ret = priv->sor.dp_train_init(priv, or, link, head, type, mask, data, &outp); + break; + case NV94_DISP_SOR_DP_TRAIN_OP_FINI: + ret = priv->sor.dp_train_fini(priv, or, link, head, type, mask, data, &outp); + break; + default: + break; + } + break; + case NV94_DISP_SOR_DP_LNKCTL: + ret = priv->sor.dp_lnkctl(priv, or, link, head, type, mask, data, &outp); + break; + case NV94_DISP_SOR_DP_DRVCTL(0): + case NV94_DISP_SOR_DP_DRVCTL(1): + case NV94_DISP_SOR_DP_DRVCTL(2): + case NV94_DISP_SOR_DP_DRVCTL(3): + ret = priv->sor.dp_drvctl(priv, or, link, (mthd & 0xc0) >> 6, + type, mask, data, &outp); + break; default: BUG_ON(1); } diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c index 7ec4ee83fb64..f6edd009762e 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c @@ -32,18 +32,6 @@ #include "nv50.h" -static inline u32 -nv94_sor_soff(struct dcb_output *outp) -{ - return (ffs(outp->or) - 1) * 0x800; -} - -static inline u32 -nv94_sor_loff(struct dcb_output *outp) -{ - return nv94_sor_soff(outp) + !(outp->sorconf.link & 1) * 0x80; -} - static inline u32 nv94_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane) { @@ -54,32 +42,115 @@ nv94_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane) return nv94[lane]; } -static int -nv94_sor_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp, - int head, int pattern) +int +nv94_sor_dp_train_init(struct nv50_disp_priv *priv, int or, int link, int head, + u16 type, u16 mask, u32 data, struct dcb_output *dcbo) +{ + struct nouveau_bios *bios = nouveau_bios(priv); + struct nvbios_dpout info; + u8 ver, hdr, cnt, len; + u16 outp; + + outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info); + if (outp) { + struct nvbios_init init = { + .subdev = nv_subdev(priv), + .bios = bios, + .outp = dcbo, + .crtc = head, + .execute = 1, + }; + + if (data & NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON) + init.offset = info.script[2]; + else + init.offset = info.script[3]; + nvbios_exec(&init); + + init.offset = info.script[0]; + nvbios_exec(&init); + } + + return 0; +} + +int +nv94_sor_dp_train_fini(struct nv50_disp_priv *priv, int or, int link, int head, + u16 type, u16 mask, u32 data, struct dcb_output *dcbo) { - struct nv50_disp_priv *priv = (void *)disp; - const u32 loff = nv94_sor_loff(outp); - nv_mask(priv, 0x61c10c + loff, 0x0f000000, pattern << 24); + struct nouveau_bios *bios = nouveau_bios(priv); + struct nvbios_dpout info; + u8 ver, hdr, cnt, len; + u16 outp; + + outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info); + if (outp) { + struct nvbios_init init = { + .subdev = nv_subdev(priv), + .bios = bios, + .offset = info.script[1], + .outp = dcbo, + .crtc = head, + .execute = 1, + }; + + nvbios_exec(&init); + } + + return 0; +} + +int +nv94_sor_dp_train(struct nv50_disp_priv *priv, int or, int link, + u16 type, u16 mask, u32 data, struct dcb_output *info) +{ + const u32 loff = (or * 0x800) + (link * 0x80); + const u32 patt = (data & NV94_DISP_SOR_DP_TRAIN_PATTERN); + nv_mask(priv, 0x61c10c + loff, 0x0f000000, patt << 24); return 0; } -static int -nv94_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp, - int head, int link_nr, int link_bw, bool enh_frame) +int +nv94_sor_dp_lnkctl(struct nv50_disp_priv *priv, int or, int link, int head, + u16 type, u16 mask, u32 data, struct dcb_output *dcbo) { - struct nv50_disp_priv *priv = (void *)disp; - const u32 soff = nv94_sor_soff(outp); - const u32 loff = nv94_sor_loff(outp); + struct nouveau_bios *bios = nouveau_bios(priv); + const u32 loff = (or * 0x800) + (link * 0x80); + const u32 soff = (or * 0x800); + u16 link_bw = (data & NV94_DISP_SOR_DP_LNKCTL_WIDTH) >> 8; + u8 link_nr = (data & NV94_DISP_SOR_DP_LNKCTL_COUNT); u32 dpctrl = 0x00000000; u32 clksor = 0x00000000; - u32 lane = 0; + u32 outp, lane = 0; + u8 ver, hdr, cnt, len; + struct nvbios_dpout info; int i; + /* -> 10Khz units */ + link_bw *= 2700; + + outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info); + if (outp && info.lnkcmp) { + struct nvbios_init init = { + .subdev = nv_subdev(priv), + .bios = bios, + .offset = 0x0000, + .outp = dcbo, + .crtc = head, + .execute = 1, + }; + + while (link_bw < nv_ro16(bios, info.lnkcmp)) + info.lnkcmp += 4; + init.offset = nv_ro16(bios, info.lnkcmp + 2); + + nvbios_exec(&init); + } + dpctrl |= ((1 << link_nr) - 1) << 16; - if (enh_frame) + if (data & NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH) dpctrl |= 0x00004000; - if (link_bw > 0x06) + if (link_bw > 16200) clksor |= 0x00040000; for (i = 0; i < link_nr; i++) @@ -91,25 +162,24 @@ nv94_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp, return 0; } -static int -nv94_sor_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp, - int head, int lane, int swing, int preem) +int +nv94_sor_dp_drvctl(struct nv50_disp_priv *priv, int or, int link, int lane, + u16 type, u16 mask, u32 data, struct dcb_output *dcbo) { - struct nouveau_bios *bios = nouveau_bios(disp); - struct nv50_disp_priv *priv = (void *)disp; - const u32 loff = nv94_sor_loff(outp); + struct nouveau_bios *bios = nouveau_bios(priv); + const u32 loff = (or * 0x800) + (link * 0x80); + const u8 swing = (data & NV94_DISP_SOR_DP_DRVCTL_VS) >> 8; + const u8 preem = (data & NV94_DISP_SOR_DP_DRVCTL_PE); u32 addr, shift = nv94_sor_dp_lane_map(priv, lane); u8 ver, hdr, cnt, len; - struct nvbios_dpout info; + struct nvbios_dpout outp; struct nvbios_dpcfg ocfg; - addr = nvbios_dpout_match(bios, outp->hasht, outp->hashm, - &ver, &hdr, &cnt, &len, &info); + addr = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &outp); if (!addr) return -ENODEV; - addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem, - &ver, &hdr, &cnt, &len, &ocfg); + addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem, &ver, &hdr, &cnt, &len, &ocfg); if (!addr) return -EINVAL; @@ -118,10 +188,3 @@ nv94_sor_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp, nv_mask(priv, 0x61c130 + loff, 0x0000ff00, ocfg.unk << 8); return 0; } - -const struct nouveau_dp_func -nv94_sor_dp_func = { - .pattern = nv94_sor_dp_pattern, - .lnk_ctl = nv94_sor_dp_lnk_ctl, - .drv_ctl = nv94_sor_dp_drv_ctl, -}; diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c index 9e1d435d7282..c37ce7e29f5d 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c @@ -32,18 +32,6 @@ #include "nv50.h" -static inline u32 -nvd0_sor_soff(struct dcb_output *outp) -{ - return (ffs(outp->or) - 1) * 0x800; -} - -static inline u32 -nvd0_sor_loff(struct dcb_output *outp) -{ - return nvd0_sor_soff(outp) + !(outp->sorconf.link & 1) * 0x80; -} - static inline u32 nvd0_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane) { @@ -51,31 +39,53 @@ nvd0_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane) return nvd0[lane]; } -static int -nvd0_sor_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp, - int head, int pattern) +int +nvd0_sor_dp_train(struct nv50_disp_priv *priv, int or, int link, + u16 type, u16 mask, u32 data, struct dcb_output *info) { - struct nv50_disp_priv *priv = (void *)disp; - const u32 loff = nvd0_sor_loff(outp); - nv_mask(priv, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern); + const u32 loff = (or * 0x800) + (link * 0x80); + const u32 patt = (data & NV94_DISP_SOR_DP_TRAIN_PATTERN); + nv_mask(priv, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * patt); return 0; } -static int -nvd0_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp, - int head, int link_nr, int link_bw, bool enh_frame) +int +nvd0_sor_dp_lnkctl(struct nv50_disp_priv *priv, int or, int link, int head, + u16 type, u16 mask, u32 data, struct dcb_output *dcbo) { - struct nv50_disp_priv *priv = (void *)disp; - const u32 soff = nvd0_sor_soff(outp); - const u32 loff = nvd0_sor_loff(outp); + struct nouveau_bios *bios = nouveau_bios(priv); + const u32 loff = (or * 0x800) + (link * 0x80); + const u32 soff = (or * 0x800); + const u8 link_bw = (data & NV94_DISP_SOR_DP_LNKCTL_WIDTH) >> 8; + const u8 link_nr = (data & NV94_DISP_SOR_DP_LNKCTL_COUNT); u32 dpctrl = 0x00000000; u32 clksor = 0x00000000; - u32 lane = 0; + u32 outp, lane = 0; + u8 ver, hdr, cnt, len; + struct nvbios_dpout info; int i; + outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info); + if (outp && info.lnkcmp) { + struct nvbios_init init = { + .subdev = nv_subdev(priv), + .bios = bios, + .offset = 0x0000, + .outp = dcbo, + .crtc = head, + .execute = 1, + }; + + while (nv_ro08(bios, info.lnkcmp) < link_bw) + info.lnkcmp += 3; + init.offset = nv_ro16(bios, info.lnkcmp + 1); + + nvbios_exec(&init); + } + clksor |= link_bw << 18; dpctrl |= ((1 << link_nr) - 1) << 16; - if (enh_frame) + if (data & NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH) dpctrl |= 0x00004000; for (i = 0; i < link_nr; i++) @@ -87,25 +97,24 @@ nvd0_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp, return 0; } -static int -nvd0_sor_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp, - int head, int lane, int swing, int preem) +int +nvd0_sor_dp_drvctl(struct nv50_disp_priv *priv, int or, int link, int lane, + u16 type, u16 mask, u32 data, struct dcb_output *dcbo) { - struct nouveau_bios *bios = nouveau_bios(disp); - struct nv50_disp_priv *priv = (void *)disp; - const u32 loff = nvd0_sor_loff(outp); + struct nouveau_bios *bios = nouveau_bios(priv); + const u32 loff = (or * 0x800) + (link * 0x80); + const u8 swing = (data & NV94_DISP_SOR_DP_DRVCTL_VS) >> 8; + const u8 preem = (data & NV94_DISP_SOR_DP_DRVCTL_PE); u32 addr, shift = nvd0_sor_dp_lane_map(priv, lane); u8 ver, hdr, cnt, len; - struct nvbios_dpout info; + struct nvbios_dpout outp; struct nvbios_dpcfg ocfg; - addr = nvbios_dpout_match(bios, outp->hasht, outp->hashm, - &ver, &hdr, &cnt, &len, &info); + addr = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &outp); if (!addr) return -ENODEV; - addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem, - &ver, &hdr, &cnt, &len, &ocfg); + addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem, &ver, &hdr, &cnt, &len, &ocfg); if (!addr) return -EINVAL; @@ -115,10 +124,3 @@ nvd0_sor_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp, nv_mask(priv, 0x61c13c + loff, 0x00000000, 0x00000000); return 0; } - -const struct nouveau_dp_func -nvd0_sor_dp_func = { - .pattern = nvd0_sor_dp_pattern, - .lnk_ctl = nvd0_sor_dp_lnk_ctl, - .drv_ctl = nvd0_sor_dp_drv_ctl, -}; diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/base.c b/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/base.c index 7341ebe131fa..c2b9db335816 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/base.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/base.c @@ -22,10 +22,8 @@ * Authors: Ben Skeggs */ -#include #include #include -#include #include #include @@ -148,25 +146,10 @@ nouveau_fifo_chid(struct nouveau_fifo *priv, struct nouveau_object *object) return -1; } -const char * -nouveau_client_name_for_fifo_chid(struct nouveau_fifo *fifo, u32 chid) -{ - struct nouveau_fifo_chan *chan = NULL; - unsigned long flags; - - spin_lock_irqsave(&fifo->lock, flags); - if (chid >= fifo->min && chid <= fifo->max) - chan = (void *)fifo->channel[chid]; - spin_unlock_irqrestore(&fifo->lock, flags); - - return nouveau_client_name(chan); -} - void nouveau_fifo_destroy(struct nouveau_fifo *priv) { kfree(priv->channel); - nouveau_event_destroy(&priv->uevent); nouveau_engine_destroy(&priv->base); } @@ -191,10 +174,6 @@ nouveau_fifo_create_(struct nouveau_object *parent, if (!priv->channel) return -ENOMEM; - ret = nouveau_event_create(1, &priv->uevent); - if (ret) - return ret; - priv->chid = nouveau_fifo_chid; spin_lock_init(&priv->lock); return 0; diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c b/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c index f877bd524a92..a47a8548f9e0 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include @@ -399,98 +398,6 @@ nv04_fifo_swmthd(struct nv04_fifo_priv *priv, u32 chid, u32 addr, u32 data) return handled; } -static void -nv04_fifo_cache_error(struct nouveau_device *device, - struct nv04_fifo_priv *priv, u32 chid, u32 get) -{ - u32 mthd, data; - int ptr; - - /* NV_PFIFO_CACHE1_GET actually goes to 0xffc before wrapping on my - * G80 chips, but CACHE1 isn't big enough for this much data.. Tests - * show that it wraps around to the start at GET=0x800.. No clue as to - * why.. - */ - ptr = (get & 0x7ff) >> 2; - - if (device->card_type < NV_40) { - mthd = nv_rd32(priv, NV04_PFIFO_CACHE1_METHOD(ptr)); - data = nv_rd32(priv, NV04_PFIFO_CACHE1_DATA(ptr)); - } else { - mthd = nv_rd32(priv, NV40_PFIFO_CACHE1_METHOD(ptr)); - data = nv_rd32(priv, NV40_PFIFO_CACHE1_DATA(ptr)); - } - - if (!nv04_fifo_swmthd(priv, chid, mthd, data)) { - const char *client_name = - nouveau_client_name_for_fifo_chid(&priv->base, chid); - nv_error(priv, - "CACHE_ERROR - ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n", - chid, client_name, (mthd >> 13) & 7, mthd & 0x1ffc, - data); - } - - nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, 0); - nv_wr32(priv, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR); - - nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, - nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) & ~1); - nv_wr32(priv, NV03_PFIFO_CACHE1_GET, get + 4); - nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, - nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) | 1); - nv_wr32(priv, NV04_PFIFO_CACHE1_HASH, 0); - - nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, - nv_rd32(priv, NV04_PFIFO_CACHE1_DMA_PUSH) | 1); - nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); -} - -static void -nv04_fifo_dma_pusher(struct nouveau_device *device, struct nv04_fifo_priv *priv, - u32 chid) -{ - const char *client_name; - u32 dma_get = nv_rd32(priv, 0x003244); - u32 dma_put = nv_rd32(priv, 0x003240); - u32 push = nv_rd32(priv, 0x003220); - u32 state = nv_rd32(priv, 0x003228); - - client_name = nouveau_client_name_for_fifo_chid(&priv->base, chid); - - if (device->card_type == NV_50) { - u32 ho_get = nv_rd32(priv, 0x003328); - u32 ho_put = nv_rd32(priv, 0x003320); - u32 ib_get = nv_rd32(priv, 0x003334); - u32 ib_put = nv_rd32(priv, 0x003330); - - nv_error(priv, - "DMA_PUSHER - ch %d [%s] get 0x%02x%08x put 0x%02x%08x ib_get 0x%08x ib_put 0x%08x state 0x%08x (err: %s) push 0x%08x\n", - chid, client_name, ho_get, dma_get, ho_put, dma_put, - ib_get, ib_put, state, nv_dma_state_err(state), push); - - /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ - nv_wr32(priv, 0x003364, 0x00000000); - if (dma_get != dma_put || ho_get != ho_put) { - nv_wr32(priv, 0x003244, dma_put); - nv_wr32(priv, 0x003328, ho_put); - } else - if (ib_get != ib_put) - nv_wr32(priv, 0x003334, ib_put); - } else { - nv_error(priv, - "DMA_PUSHER - ch %d [%s] get 0x%08x put 0x%08x state 0x%08x (err: %s) push 0x%08x\n", - chid, client_name, dma_get, dma_put, state, - nv_dma_state_err(state), push); - - if (dma_get != dma_put) - nv_wr32(priv, 0x003244, dma_put); - } - - nv_wr32(priv, 0x003228, 0x00000000); - nv_wr32(priv, 0x003220, 0x00000001); - nv_wr32(priv, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); -} - void nv04_fifo_intr(struct nouveau_subdev *subdev) { @@ -509,12 +416,96 @@ nv04_fifo_intr(struct nouveau_subdev *subdev) get = nv_rd32(priv, NV03_PFIFO_CACHE1_GET); if (status & NV_PFIFO_INTR_CACHE_ERROR) { - nv04_fifo_cache_error(device, priv, chid, get); + uint32_t mthd, data; + int ptr; + + /* NV_PFIFO_CACHE1_GET actually goes to 0xffc before + * wrapping on my G80 chips, but CACHE1 isn't big + * enough for this much data.. Tests show that it + * wraps around to the start at GET=0x800.. No clue + * as to why.. + */ + ptr = (get & 0x7ff) >> 2; + + if (device->card_type < NV_40) { + mthd = nv_rd32(priv, + NV04_PFIFO_CACHE1_METHOD(ptr)); + data = nv_rd32(priv, + NV04_PFIFO_CACHE1_DATA(ptr)); + } else { + mthd = nv_rd32(priv, + NV40_PFIFO_CACHE1_METHOD(ptr)); + data = nv_rd32(priv, + NV40_PFIFO_CACHE1_DATA(ptr)); + } + + if (!nv04_fifo_swmthd(priv, chid, mthd, data)) { + nv_error(priv, "CACHE_ERROR - Ch %d/%d " + "Mthd 0x%04x Data 0x%08x\n", + chid, (mthd >> 13) & 7, mthd & 0x1ffc, + data); + } + + nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, 0); + nv_wr32(priv, NV03_PFIFO_INTR_0, + NV_PFIFO_INTR_CACHE_ERROR); + + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, + nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) & ~1); + nv_wr32(priv, NV03_PFIFO_CACHE1_GET, get + 4); + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, + nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) | 1); + nv_wr32(priv, NV04_PFIFO_CACHE1_HASH, 0); + + nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, + nv_rd32(priv, NV04_PFIFO_CACHE1_DMA_PUSH) | 1); + nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); + status &= ~NV_PFIFO_INTR_CACHE_ERROR; } if (status & NV_PFIFO_INTR_DMA_PUSHER) { - nv04_fifo_dma_pusher(device, priv, chid); + u32 dma_get = nv_rd32(priv, 0x003244); + u32 dma_put = nv_rd32(priv, 0x003240); + u32 push = nv_rd32(priv, 0x003220); + u32 state = nv_rd32(priv, 0x003228); + + if (device->card_type == NV_50) { + u32 ho_get = nv_rd32(priv, 0x003328); + u32 ho_put = nv_rd32(priv, 0x003320); + u32 ib_get = nv_rd32(priv, 0x003334); + u32 ib_put = nv_rd32(priv, 0x003330); + + nv_error(priv, "DMA_PUSHER - Ch %d Get 0x%02x%08x " + "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " + "State 0x%08x (err: %s) Push 0x%08x\n", + chid, ho_get, dma_get, ho_put, + dma_put, ib_get, ib_put, state, + nv_dma_state_err(state), + push); + + /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ + nv_wr32(priv, 0x003364, 0x00000000); + if (dma_get != dma_put || ho_get != ho_put) { + nv_wr32(priv, 0x003244, dma_put); + nv_wr32(priv, 0x003328, ho_put); + } else + if (ib_get != ib_put) { + nv_wr32(priv, 0x003334, ib_put); + } + } else { + nv_error(priv, "DMA_PUSHER - Ch %d Get 0x%08x " + "Put 0x%08x State 0x%08x (err: %s) Push 0x%08x\n", + chid, dma_get, dma_put, state, + nv_dma_state_err(state), push); + + if (dma_get != dma_put) + nv_wr32(priv, 0x003244, dma_put); + } + + nv_wr32(priv, 0x003228, 0x00000000); + nv_wr32(priv, 0x003220, 0x00000001); + nv_wr32(priv, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); status &= ~NV_PFIFO_INTR_DMA_PUSHER; } @@ -537,12 +528,6 @@ nv04_fifo_intr(struct nouveau_subdev *subdev) status &= ~0x00000010; nv_wr32(priv, 0x002100, 0x00000010); } - - if (status & 0x40000000) { - nouveau_event_trigger(priv->base.uevent, 0); - nv_wr32(priv, 0x002100, 0x40000000); - status &= ~0x40000000; - } } if (status) { diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index 840af6172788..bd096364f680 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c @@ -129,8 +129,7 @@ nv50_fifo_context_detach(struct nouveau_object *parent, bool suspend, /* do the kickoff... */ nv_wr32(priv, 0x0032fc, nv_gpuobj(base)->addr >> 12); if (!nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff)) { - nv_error(priv, "channel %d [%s] unload timeout\n", - chan->base.chid, nouveau_client_name(chan)); + nv_error(priv, "channel %d unload timeout\n", chan->base.chid); if (suspend) ret = -EBUSY; } @@ -481,7 +480,7 @@ nv50_fifo_init(struct nouveau_object *object) nv_wr32(priv, 0x002044, 0x01003fff); nv_wr32(priv, 0x002100, 0xffffffff); - nv_wr32(priv, 0x002140, 0xbfffffff); + nv_wr32(priv, 0x002140, 0xffffffff); for (i = 0; i < 128; i++) nv_wr32(priv, 0x002600 + (i * 4), 0x00000000); diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index 094000e87871..1eb1c512f503 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -101,8 +100,7 @@ nv84_fifo_context_detach(struct nouveau_object *parent, bool suspend, done = nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff); nv_wr32(priv, 0x002520, save); if (!done) { - nv_error(priv, "channel %d [%s] unload timeout\n", - chan->base.chid, nouveau_client_name(chan)); + nv_error(priv, "channel %d unload timeout\n", chan->base.chid); if (suspend) return -EBUSY; } @@ -380,20 +378,6 @@ nv84_fifo_cclass = { * PFIFO engine ******************************************************************************/ -static void -nv84_fifo_uevent_enable(struct nouveau_event *event, int index) -{ - struct nv84_fifo_priv *priv = event->priv; - nv_mask(priv, 0x002140, 0x40000000, 0x40000000); -} - -static void -nv84_fifo_uevent_disable(struct nouveau_event *event, int index) -{ - struct nv84_fifo_priv *priv = event->priv; - nv_mask(priv, 0x002140, 0x40000000, 0x00000000); -} - static int nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -417,10 +401,6 @@ nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - priv->base.uevent->enable = nv84_fifo_uevent_enable; - priv->base.uevent->disable = nv84_fifo_uevent_disable; - priv->base.uevent->priv = priv; - nv_subdev(priv)->unit = 0x00000100; nv_subdev(priv)->intr = nv04_fifo_intr; nv_engine(priv)->cclass = &nv84_fifo_cclass; diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index 4f226afb5591..b4365dde1859 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -150,8 +149,7 @@ nvc0_fifo_context_detach(struct nouveau_object *parent, bool suspend, nv_wr32(priv, 0x002634, chan->base.chid); if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { - nv_error(priv, "channel %d [%s] kick timeout\n", - chan->base.chid, nouveau_client_name(chan)); + nv_error(priv, "channel %d kick timeout\n", chan->base.chid); if (suspend) return -EBUSY; } @@ -335,17 +333,17 @@ nvc0_fifo_cclass = { ******************************************************************************/ static const struct nouveau_enum nvc0_fifo_fault_unit[] = { - { 0x00, "PGRAPH", NULL, NVDEV_ENGINE_GR }, + { 0x00, "PGRAPH" }, { 0x03, "PEEPHOLE" }, { 0x04, "BAR1" }, { 0x05, "BAR3" }, - { 0x07, "PFIFO", NULL, NVDEV_ENGINE_FIFO }, - { 0x10, "PBSP", NULL, NVDEV_ENGINE_BSP }, - { 0x11, "PPPP", NULL, NVDEV_ENGINE_PPP }, + { 0x07, "PFIFO" }, + { 0x10, "PBSP" }, + { 0x11, "PPPP" }, { 0x13, "PCOUNTER" }, - { 0x14, "PVP", NULL, NVDEV_ENGINE_VP }, - { 0x15, "PCOPY0", NULL, NVDEV_ENGINE_COPY0 }, - { 0x16, "PCOPY1", NULL, NVDEV_ENGINE_COPY1 }, + { 0x14, "PVP" }, + { 0x15, "PCOPY0" }, + { 0x16, "PCOPY1" }, { 0x17, "PDAEMON" }, {} }; @@ -404,9 +402,6 @@ nvc0_fifo_isr_vm_fault(struct nvc0_fifo_priv *priv, int unit) u32 vahi = nv_rd32(priv, 0x002808 + (unit * 0x10)); u32 stat = nv_rd32(priv, 0x00280c + (unit * 0x10)); u32 client = (stat & 0x00001f00) >> 8; - const struct nouveau_enum *en; - struct nouveau_engine *engine; - struct nouveau_object *engctx = NULL; switch (unit) { case 3: /* PEEPHOLE */ @@ -425,26 +420,16 @@ nvc0_fifo_isr_vm_fault(struct nvc0_fifo_priv *priv, int unit) nv_error(priv, "%s fault at 0x%010llx [", (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo); nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f); - pr_cont("] from "); - en = nouveau_enum_print(nvc0_fifo_fault_unit, unit); + printk("] from "); + nouveau_enum_print(nvc0_fifo_fault_unit, unit); if (stat & 0x00000040) { - pr_cont("/"); + printk("/"); nouveau_enum_print(nvc0_fifo_fault_hubclient, client); } else { - pr_cont("/GPC%d/", (stat & 0x1f000000) >> 24); + printk("/GPC%d/", (stat & 0x1f000000) >> 24); nouveau_enum_print(nvc0_fifo_fault_gpcclient, client); } - - if (en && en->data2) { - engine = nouveau_engine(priv, en->data2); - if (engine) - engctx = nouveau_engctx_get(engine, inst); - - } - pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12, - nouveau_client_name(engctx)); - - nouveau_engctx_put(engctx); + printk(" on channel 0x%010llx\n", (u64)inst << 12); } static int @@ -499,12 +484,10 @@ nvc0_fifo_isr_subfifo_intr(struct nvc0_fifo_priv *priv, int unit) if (show) { nv_error(priv, "SUBFIFO%d:", unit); nouveau_bitfield_print(nvc0_fifo_subfifo_intr, show); - pr_cont("\n"); - nv_error(priv, - "SUBFIFO%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n", - unit, chid, - nouveau_client_name_for_fifo_chid(&priv->base, chid), - subc, mthd, data); + printk("\n"); + nv_error(priv, "SUBFIFO%d: ch %d subc %d mthd 0x%04x " + "data 0x%08x\n", + unit, chid, subc, mthd, data); } nv_wr32(priv, 0x0400c0 + (unit * 0x2000), 0x80600008); @@ -518,34 +501,12 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev) u32 mask = nv_rd32(priv, 0x002140); u32 stat = nv_rd32(priv, 0x002100) & mask; - if (stat & 0x00000001) { - u32 intr = nv_rd32(priv, 0x00252c); - nv_warn(priv, "INTR 0x00000001: 0x%08x\n", intr); - nv_wr32(priv, 0x002100, 0x00000001); - stat &= ~0x00000001; - } - if (stat & 0x00000100) { - u32 intr = nv_rd32(priv, 0x00254c); - nv_warn(priv, "INTR 0x00000100: 0x%08x\n", intr); + nv_warn(priv, "unknown status 0x00000100\n"); nv_wr32(priv, 0x002100, 0x00000100); stat &= ~0x00000100; } - if (stat & 0x00010000) { - u32 intr = nv_rd32(priv, 0x00256c); - nv_warn(priv, "INTR 0x00010000: 0x%08x\n", intr); - nv_wr32(priv, 0x002100, 0x00010000); - stat &= ~0x00010000; - } - - if (stat & 0x01000000) { - u32 intr = nv_rd32(priv, 0x00258c); - nv_warn(priv, "INTR 0x01000000: 0x%08x\n", intr); - nv_wr32(priv, 0x002100, 0x01000000); - stat &= ~0x01000000; - } - if (stat & 0x10000000) { u32 units = nv_rd32(priv, 0x00259c); u32 u = units; @@ -575,20 +536,11 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev) } if (stat & 0x40000000) { - u32 intr0 = nv_rd32(priv, 0x0025a4); - u32 intr1 = nv_mask(priv, 0x002a00, 0x00000000, 0x00000); - nv_debug(priv, "INTR 0x40000000: 0x%08x 0x%08x\n", - intr0, intr1); + nv_warn(priv, "unknown status 0x40000000\n"); + nv_mask(priv, 0x002a00, 0x00000000, 0x00000000); stat &= ~0x40000000; } - if (stat & 0x80000000) { - u32 intr = nv_mask(priv, 0x0025a8, 0x00000000, 0x00000000); - nouveau_event_trigger(priv->base.uevent, 0); - nv_debug(priv, "INTR 0x80000000: 0x%08x\n", intr); - stat &= ~0x80000000; - } - if (stat) { nv_fatal(priv, "unhandled status 0x%08x\n", stat); nv_wr32(priv, 0x002100, stat); @@ -596,20 +548,6 @@ nvc0_fifo_intr(struct nouveau_subdev *subdev) } } -static void -nvc0_fifo_uevent_enable(struct nouveau_event *event, int index) -{ - struct nvc0_fifo_priv *priv = event->priv; - nv_mask(priv, 0x002140, 0x80000000, 0x80000000); -} - -static void -nvc0_fifo_uevent_disable(struct nouveau_event *event, int index) -{ - struct nvc0_fifo_priv *priv = event->priv; - nv_mask(priv, 0x002140, 0x80000000, 0x00000000); -} - static int nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -643,10 +581,6 @@ nvc0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - priv->base.uevent->enable = nvc0_fifo_uevent_enable; - priv->base.uevent->disable = nvc0_fifo_uevent_disable; - priv->base.uevent->priv = priv; - nv_subdev(priv)->unit = 0x00000100; nv_subdev(priv)->intr = nvc0_fifo_intr; nv_engine(priv)->cclass = &nvc0_fifo_cclass; @@ -705,8 +639,7 @@ nvc0_fifo_init(struct nouveau_object *object) nv_wr32(priv, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */ nv_wr32(priv, 0x002100, 0xffffffff); - nv_wr32(priv, 0x002140, 0x3fffffff); - nv_wr32(priv, 0x002628, 0x00000001); /* makes mthd 0x20 work */ + nv_wr32(priv, 0x002140, 0xbfffffff); return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 4419e40d88e9..c930da99c2c1 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -185,8 +184,7 @@ nve0_fifo_context_detach(struct nouveau_object *parent, bool suspend, nv_wr32(priv, 0x002634, chan->base.chid); if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { - nv_error(priv, "channel %d [%s] kick timeout\n", - chan->base.chid, nouveau_client_name(chan)); + nv_error(priv, "channel %d kick timeout\n", chan->base.chid); if (suspend) return -EBUSY; } @@ -414,34 +412,20 @@ nve0_fifo_isr_vm_fault(struct nve0_fifo_priv *priv, int unit) u32 vahi = nv_rd32(priv, 0x2808 + (unit * 0x10)); u32 stat = nv_rd32(priv, 0x280c + (unit * 0x10)); u32 client = (stat & 0x00001f00) >> 8; - const struct nouveau_enum *en; - struct nouveau_engine *engine; - struct nouveau_object *engctx = NULL; nv_error(priv, "PFIFO: %s fault at 0x%010llx [", (stat & 0x00000080) ? "write" : "read", (u64)vahi << 32 | valo); nouveau_enum_print(nve0_fifo_fault_reason, stat & 0x0000000f); - pr_cont("] from "); - en = nouveau_enum_print(nve0_fifo_fault_unit, unit); + printk("] from "); + nouveau_enum_print(nve0_fifo_fault_unit, unit); if (stat & 0x00000040) { - pr_cont("/"); + printk("/"); nouveau_enum_print(nve0_fifo_fault_hubclient, client); } else { - pr_cont("/GPC%d/", (stat & 0x1f000000) >> 24); + printk("/GPC%d/", (stat & 0x1f000000) >> 24); nouveau_enum_print(nve0_fifo_fault_gpcclient, client); } - - if (en && en->data2) { - engine = nouveau_engine(priv, en->data2); - if (engine) - engctx = nouveau_engctx_get(engine, inst); - - } - - pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12, - nouveau_client_name(engctx)); - - nouveau_engctx_put(engctx); + printk(" on channel 0x%010llx\n", (u64)inst << 12); } static int @@ -496,12 +480,10 @@ nve0_fifo_isr_subfifo_intr(struct nve0_fifo_priv *priv, int unit) if (show) { nv_error(priv, "SUBFIFO%d:", unit); nouveau_bitfield_print(nve0_fifo_subfifo_intr, show); - pr_cont("\n"); - nv_error(priv, - "SUBFIFO%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n", - unit, chid, - nouveau_client_name_for_fifo_chid(&priv->base, chid), - subc, mthd, data); + printk("\n"); + nv_error(priv, "SUBFIFO%d: ch %d subc %d mthd 0x%04x " + "data 0x%08x\n", + unit, chid, subc, mthd, data); } nv_wr32(priv, 0x0400c0 + (unit * 0x2000), 0x80600008); @@ -555,12 +537,6 @@ nve0_fifo_intr(struct nouveau_subdev *subdev) stat &= ~0x40000000; } - if (stat & 0x80000000) { - nouveau_event_trigger(priv->base.uevent, 0); - nv_wr32(priv, 0x002100, 0x80000000); - stat &= ~0x80000000; - } - if (stat) { nv_fatal(priv, "unhandled status 0x%08x\n", stat); nv_wr32(priv, 0x002100, stat); @@ -568,20 +544,6 @@ nve0_fifo_intr(struct nouveau_subdev *subdev) } } -static void -nve0_fifo_uevent_enable(struct nouveau_event *event, int index) -{ - struct nve0_fifo_priv *priv = event->priv; - nv_mask(priv, 0x002140, 0x80000000, 0x80000000); -} - -static void -nve0_fifo_uevent_disable(struct nouveau_event *event, int index) -{ - struct nve0_fifo_priv *priv = event->priv; - nv_mask(priv, 0x002140, 0x80000000, 0x00000000); -} - static int nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -605,10 +567,6 @@ nve0_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, if (ret) return ret; - priv->base.uevent->enable = nve0_fifo_uevent_enable; - priv->base.uevent->disable = nve0_fifo_uevent_disable; - priv->base.uevent->priv = priv; - nv_subdev(priv)->unit = 0x00000100; nv_subdev(priv)->intr = nve0_fifo_intr; nv_engine(priv)->cclass = &nve0_fifo_cclass; @@ -659,7 +617,7 @@ nve0_fifo_init(struct nouveau_object *object) nv_wr32(priv, 0x002a00, 0xffffffff); nv_wr32(priv, 0x002100, 0xffffffff); - nv_wr32(priv, 0x002140, 0x3fffffff); + nv_wr32(priv, 0x002140, 0xbfffffff); return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c index ad13dcdd15f9..e30a9c5ff1fc 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv04.c @@ -22,7 +22,6 @@ * DEALINGS IN THE SOFTWARE. */ -#include #include #include #include @@ -1298,17 +1297,16 @@ nv04_graph_intr(struct nouveau_subdev *subdev) nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); if (show) { - nv_error(priv, "%s", ""); + nv_error(priv, ""); nouveau_bitfield_print(nv04_graph_intr_name, show); - pr_cont(" nsource:"); + printk(" nsource:"); nouveau_bitfield_print(nv04_graph_nsource, nsource); - pr_cont(" nstatus:"); + printk(" nstatus:"); nouveau_bitfield_print(nv04_graph_nstatus, nstatus); - pr_cont("\n"); - nv_error(priv, - "ch %d [%s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, nouveau_client_name(chan), subc, class, mthd, - data); + printk("\n"); + nv_error(priv, "ch %d/%d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + chid, subc, class, mthd, data); } nouveau_namedb_put(handle); diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c index 23c143aaa556..5c0f843ea249 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv10.c @@ -22,7 +22,6 @@ * DEALINGS IN THE SOFTWARE. */ -#include #include #include #include @@ -1194,17 +1193,16 @@ nv10_graph_intr(struct nouveau_subdev *subdev) nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); if (show) { - nv_error(priv, "%s", ""); + nv_error(priv, ""); nouveau_bitfield_print(nv10_graph_intr_name, show); - pr_cont(" nsource:"); + printk(" nsource:"); nouveau_bitfield_print(nv04_graph_nsource, nsource); - pr_cont(" nstatus:"); + printk(" nstatus:"); nouveau_bitfield_print(nv10_graph_nstatus, nstatus); - pr_cont("\n"); - nv_error(priv, - "ch %d [%s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, nouveau_client_name(chan), subc, class, mthd, - data); + printk("\n"); + nv_error(priv, "ch %d/%d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + chid, subc, class, mthd, data); } nouveau_namedb_put(handle); diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c index 0607b9801748..5b20401bf911 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv20.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -225,17 +224,15 @@ nv20_graph_intr(struct nouveau_subdev *subdev) nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); if (show) { - nv_error(priv, "%s", ""); + nv_error(priv, ""); nouveau_bitfield_print(nv10_graph_intr_name, show); - pr_cont(" nsource:"); + printk(" nsource:"); nouveau_bitfield_print(nv04_graph_nsource, nsource); - pr_cont(" nstatus:"); + printk(" nstatus:"); nouveau_bitfield_print(nv10_graph_nstatus, nstatus); - pr_cont("\n"); - nv_error(priv, - "ch %d [%s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, nouveau_client_name(engctx), subc, class, mthd, - data); + printk("\n"); + nv_error(priv, "ch %d/%d class 0x%04x mthd 0x%04x data 0x%08x\n", + chid, subc, class, mthd, data); } nouveau_engctx_put(engctx); diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c index 17049d5c723d..0b36dd3deebd 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv40.c @@ -22,7 +22,6 @@ * Authors: Ben Skeggs */ -#include #include #include #include @@ -322,17 +321,16 @@ nv40_graph_intr(struct nouveau_subdev *subdev) nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); if (show) { - nv_error(priv, "%s", ""); + nv_error(priv, ""); nouveau_bitfield_print(nv10_graph_intr_name, show); - pr_cont(" nsource:"); + printk(" nsource:"); nouveau_bitfield_print(nv04_graph_nsource, nsource); - pr_cont(" nstatus:"); + printk(" nstatus:"); nouveau_bitfield_print(nv10_graph_nstatus, nstatus); - pr_cont("\n"); - nv_error(priv, - "ch %d [0x%08x %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst << 4, nouveau_client_name(engctx), subc, - class, mthd, data); + printk("\n"); + nv_error(priv, "ch %d [0x%08x] subc %d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + chid, inst << 4, subc, class, mthd, data); } nouveau_engctx_put(engctx); diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c index f2b1a7a124f2..b1c3d835b4c2 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nv50.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -419,7 +418,7 @@ nv50_priv_mp_trap(struct nv50_graph_priv *priv, int tpid, int display) nv_error(priv, "TRAP_MP_EXEC - " "TP %d MP %d: ", tpid, i); nouveau_enum_print(nv50_mp_exec_error_names, status); - pr_cont(" at %06x warp %d, opcode %08x %08x\n", + printk(" at %06x warp %d, opcode %08x %08x\n", pc&0xffffff, pc >> 24, oplow, ophigh); } @@ -533,7 +532,7 @@ nv50_priv_tp_trap(struct nv50_graph_priv *priv, int type, u32 ustatus_old, static int nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display, - int chid, u64 inst, struct nouveau_object *engctx) + int chid, u64 inst) { u32 status = nv_rd32(priv, 0x400108); u32 ustatus; @@ -566,11 +565,12 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display, nv_error(priv, "TRAP DISPATCH_FAULT\n"); if (display && (addr & 0x80000000)) { - nv_error(priv, - "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x%08x 400808 0x%08x 400848 0x%08x\n", - chid, inst, - nouveau_client_name(engctx), subc, - class, mthd, datah, datal, addr, r848); + nv_error(priv, "ch %d [0x%010llx] " + "subc %d class 0x%04x mthd 0x%04x " + "data 0x%08x%08x " + "400808 0x%08x 400848 0x%08x\n", + chid, inst, subc, class, mthd, datah, + datal, addr, r848); } else if (display) { nv_error(priv, "no stuck command?\n"); @@ -591,11 +591,11 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display, nv_error(priv, "TRAP DISPATCH_QUERY\n"); if (display && (addr & 0x80000000)) { - nv_error(priv, - "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x 40084c 0x%08x\n", - chid, inst, - nouveau_client_name(engctx), subc, - class, mthd, data, addr); + nv_error(priv, "ch %d [0x%010llx] " + "subc %d class 0x%04x mthd 0x%04x " + "data 0x%08x 40084c 0x%08x\n", + chid, inst, subc, class, mthd, + data, addr); } else if (display) { nv_error(priv, "no stuck command?\n"); @@ -623,7 +623,7 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display, if (display) { nv_error(priv, "TRAP_M2MF"); nouveau_bitfield_print(nv50_graph_trap_m2mf, ustatus); - pr_cont("\n"); + printk("\n"); nv_error(priv, "TRAP_M2MF %08x %08x %08x %08x\n", nv_rd32(priv, 0x406804), nv_rd32(priv, 0x406808), nv_rd32(priv, 0x40680c), nv_rd32(priv, 0x406810)); @@ -644,7 +644,7 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display, if (display) { nv_error(priv, "TRAP_VFETCH"); nouveau_bitfield_print(nv50_graph_trap_vfetch, ustatus); - pr_cont("\n"); + printk("\n"); nv_error(priv, "TRAP_VFETCH %08x %08x %08x %08x\n", nv_rd32(priv, 0x400c00), nv_rd32(priv, 0x400c08), nv_rd32(priv, 0x400c0c), nv_rd32(priv, 0x400c10)); @@ -661,7 +661,7 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display, if (display) { nv_error(priv, "TRAP_STRMOUT"); nouveau_bitfield_print(nv50_graph_trap_strmout, ustatus); - pr_cont("\n"); + printk("\n"); nv_error(priv, "TRAP_STRMOUT %08x %08x %08x %08x\n", nv_rd32(priv, 0x401804), nv_rd32(priv, 0x401808), nv_rd32(priv, 0x40180c), nv_rd32(priv, 0x401810)); @@ -682,7 +682,7 @@ nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display, if (display) { nv_error(priv, "TRAP_CCACHE"); nouveau_bitfield_print(nv50_graph_trap_ccache, ustatus); - pr_cont("\n"); + printk("\n"); nv_error(priv, "TRAP_CCACHE %08x %08x %08x %08x" " %08x %08x %08x\n", nv_rd32(priv, 0x405000), nv_rd32(priv, 0x405004), @@ -774,12 +774,11 @@ nv50_graph_intr(struct nouveau_subdev *subdev) u32 ecode = nv_rd32(priv, 0x400110); nv_error(priv, "DATA_ERROR "); nouveau_enum_print(nv50_data_error_names, ecode); - pr_cont("\n"); + printk("\n"); } if (stat & 0x00200000) { - if (!nv50_graph_trap_handler(priv, show, chid, (u64)inst << 12, - engctx)) + if (!nv50_graph_trap_handler(priv, show, chid, (u64)inst << 12)) show &= ~0x00200000; } @@ -787,13 +786,12 @@ nv50_graph_intr(struct nouveau_subdev *subdev) nv_wr32(priv, 0x400500, 0x00010001); if (show) { - nv_error(priv, "%s", ""); + nv_error(priv, ""); nouveau_bitfield_print(nv50_graph_intr_name, show); - pr_cont("\n"); - nv_error(priv, - "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, (u64)inst << 12, nouveau_client_name(engctx), - subc, class, mthd, data); + printk("\n"); + nv_error(priv, "ch %d [0x%010llx] subc %d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + chid, (u64)inst << 12, subc, class, mthd, data); } if (nv_rd32(priv, 0x400824) & (1 << 31)) @@ -909,8 +907,9 @@ nv50_graph_init(struct nouveau_object *object) nv_wr32(priv, 0x400828, 0x00000000); nv_wr32(priv, 0x40082c, 0x00000000); nv_wr32(priv, 0x400830, 0x00000000); + nv_wr32(priv, 0x400724, 0x00000000); nv_wr32(priv, 0x40032c, 0x00000000); - nv_wr32(priv, 0x400330, 0x00000000); + nv_wr32(priv, 0x400320, 4); /* CTXCTL_CMD = NEWCTXDMA */ /* some unknown zcull magic */ switch (nv_device(priv)->chipset & 0xf0) { diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c index 0de0dd724aff..45aff5f5085a 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c @@ -433,10 +433,10 @@ nvc0_graph_intr(struct nouveau_subdev *subdev) if (stat & 0x00000010) { handle = nouveau_handle_get_class(engctx, class); if (!handle || nv_call(handle->object, mthd, data)) { - nv_error(priv, - "ILLEGAL_MTHD ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst << 12, nouveau_client_name(engctx), - subc, class, mthd, data); + nv_error(priv, "ILLEGAL_MTHD ch %d [0x%010llx] " + "subc %d class 0x%04x mthd 0x%04x " + "data 0x%08x\n", + chid, inst << 12, subc, class, mthd, data); } nouveau_handle_put(handle); nv_wr32(priv, 0x400100, 0x00000010); @@ -444,10 +444,9 @@ nvc0_graph_intr(struct nouveau_subdev *subdev) } if (stat & 0x00000020) { - nv_error(priv, - "ILLEGAL_CLASS ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst << 12, nouveau_client_name(engctx), subc, - class, mthd, data); + nv_error(priv, "ILLEGAL_CLASS ch %d [0x%010llx] subc %d " + "class 0x%04x mthd 0x%04x data 0x%08x\n", + chid, inst << 12, subc, class, mthd, data); nv_wr32(priv, 0x400100, 0x00000020); stat &= ~0x00000020; } @@ -455,16 +454,15 @@ nvc0_graph_intr(struct nouveau_subdev *subdev) if (stat & 0x00100000) { nv_error(priv, "DATA_ERROR ["); nouveau_enum_print(nv50_data_error_names, code); - pr_cont("] ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst << 12, nouveau_client_name(engctx), subc, - class, mthd, data); + printk("] ch %d [0x%010llx] subc %d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + chid, inst << 12, subc, class, mthd, data); nv_wr32(priv, 0x400100, 0x00100000); stat &= ~0x00100000; } if (stat & 0x00200000) { - nv_error(priv, "TRAP ch %d [0x%010llx %s]\n", chid, inst << 12, - nouveau_client_name(engctx)); + nv_error(priv, "TRAP ch %d [0x%010llx]\n", chid, inst << 12); nvc0_graph_trap_intr(priv); nv_wr32(priv, 0x400100, 0x00200000); stat &= ~0x00200000; @@ -613,8 +611,10 @@ nvc0_graph_ctor(struct nouveau_object *parent, struct nouveau_object *engine, static void nvc0_graph_dtor_fw(struct nvc0_graph_fuc *fuc) { - kfree(fuc->data); - fuc->data = NULL; + if (fuc->data) { + kfree(fuc->data); + fuc->data = NULL; + } } void @@ -622,7 +622,8 @@ nvc0_graph_dtor(struct nouveau_object *object) { struct nvc0_graph_priv *priv = (void *)object; - kfree(priv->data); + if (priv->data) + kfree(priv->data); nvc0_graph_dtor_fw(&priv->fuc409c); nvc0_graph_dtor_fw(&priv->fuc409d); diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index 61cec0f6ff1c..9f82e9702b46 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c @@ -78,16 +78,15 @@ nve0_graph_ctxctl_isr(struct nvc0_graph_priv *priv) } static void -nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst, - struct nouveau_object *engctx) +nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst) { u32 trap = nv_rd32(priv, 0x400108); int rop; if (trap & 0x00000001) { u32 stat = nv_rd32(priv, 0x404000); - nv_error(priv, "DISPATCH ch %d [0x%010llx %s] 0x%08x\n", - chid, inst, nouveau_client_name(engctx), stat); + nv_error(priv, "DISPATCH ch %d [0x%010llx] 0x%08x\n", + chid, inst, stat); nv_wr32(priv, 0x404000, 0xc0000000); nv_wr32(priv, 0x400108, 0x00000001); trap &= ~0x00000001; @@ -95,8 +94,8 @@ nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst, if (trap & 0x00000010) { u32 stat = nv_rd32(priv, 0x405840); - nv_error(priv, "SHADER ch %d [0x%010llx %s] 0x%08x\n", - chid, inst, nouveau_client_name(engctx), stat); + nv_error(priv, "SHADER ch %d [0x%010llx] 0x%08x\n", + chid, inst, stat); nv_wr32(priv, 0x405840, 0xc0000000); nv_wr32(priv, 0x400108, 0x00000010); trap &= ~0x00000010; @@ -106,10 +105,8 @@ nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst, for (rop = 0; rop < priv->rop_nr; rop++) { u32 statz = nv_rd32(priv, ROP_UNIT(rop, 0x070)); u32 statc = nv_rd32(priv, ROP_UNIT(rop, 0x144)); - nv_error(priv, - "ROP%d ch %d [0x%010llx %s] 0x%08x 0x%08x\n", - rop, chid, inst, nouveau_client_name(engctx), - statz, statc); + nv_error(priv, "ROP%d ch %d [0x%010llx] 0x%08x 0x%08x\n", + rop, chid, inst, statz, statc); nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); } @@ -118,8 +115,8 @@ nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst, } if (trap) { - nv_error(priv, "TRAP ch %d [0x%010llx %s] 0x%08x\n", - chid, inst, nouveau_client_name(engctx), trap); + nv_error(priv, "TRAP ch %d [0x%010llx] 0x%08x\n", + chid, inst, trap); nv_wr32(priv, 0x400108, trap); } } @@ -148,10 +145,10 @@ nve0_graph_intr(struct nouveau_subdev *subdev) if (stat & 0x00000010) { handle = nouveau_handle_get_class(engctx, class); if (!handle || nv_call(handle->object, mthd, data)) { - nv_error(priv, - "ILLEGAL_MTHD ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst, nouveau_client_name(engctx), subc, - class, mthd, data); + nv_error(priv, "ILLEGAL_MTHD ch %d [0x%010llx] " + "subc %d class 0x%04x mthd 0x%04x " + "data 0x%08x\n", + chid, inst, subc, class, mthd, data); } nouveau_handle_put(handle); nv_wr32(priv, 0x400100, 0x00000010); @@ -159,10 +156,9 @@ nve0_graph_intr(struct nouveau_subdev *subdev) } if (stat & 0x00000020) { - nv_error(priv, - "ILLEGAL_CLASS ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst, nouveau_client_name(engctx), subc, class, - mthd, data); + nv_error(priv, "ILLEGAL_CLASS ch %d [0x%010llx] subc %d " + "class 0x%04x mthd 0x%04x data 0x%08x\n", + chid, inst, subc, class, mthd, data); nv_wr32(priv, 0x400100, 0x00000020); stat &= ~0x00000020; } @@ -170,15 +166,15 @@ nve0_graph_intr(struct nouveau_subdev *subdev) if (stat & 0x00100000) { nv_error(priv, "DATA_ERROR ["); nouveau_enum_print(nv50_data_error_names, code); - pr_cont("] ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", - chid, inst, nouveau_client_name(engctx), subc, class, - mthd, data); + printk("] ch %d [0x%010llx] subc %d class 0x%04x " + "mthd 0x%04x data 0x%08x\n", + chid, inst, subc, class, mthd, data); nv_wr32(priv, 0x400100, 0x00100000); stat &= ~0x00100000; } if (stat & 0x00200000) { - nve0_graph_trap_isr(priv, chid, inst, engctx); + nve0_graph_trap_isr(priv, chid, inst); nv_wr32(priv, 0x400100, 0x00200000); stat &= ~0x00200000; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c b/trunk/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c index 49ecbb859b25..9fd86375f4c4 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c @@ -22,7 +22,6 @@ * Authors: Ben Skeggs */ -#include #include #include #include @@ -232,10 +231,8 @@ nv31_mpeg_intr(struct nouveau_subdev *subdev) nv_wr32(priv, 0x00b230, 0x00000001); if (show) { - nv_error(priv, - "ch %d [0x%08x %s] 0x%08x 0x%08x 0x%08x 0x%08x\n", - chid, inst << 4, nouveau_client_name(engctx), stat, - type, mthd, data); + nv_error(priv, "ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", + chid, inst << 4, stat, type, mthd, data); } nouveau_engctx_put(engctx); diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/software/nv50.c b/trunk/drivers/gpu/drm/nouveau/core/engine/software/nv50.c index c48e74953771..b0e7e1c01ce6 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/software/nv50.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/software/nv50.c @@ -28,9 +28,6 @@ #include #include #include -#include - -#include #include #include @@ -93,11 +90,18 @@ nv50_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd, { struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); struct nouveau_disp *disp = nouveau_disp(object); + unsigned long flags; u32 crtc = *(u32 *)args; + if (crtc > 1) return -EINVAL; - nouveau_event_get(disp->vblank, crtc, &chan->base.vblank.event); + disp->vblank.get(disp->vblank.data, crtc); + + spin_lock_irqsave(&disp->vblank.lock, flags); + list_add(&chan->base.vblank.head, &disp->vblank.list); + chan->base.vblank.crtc = crtc; + spin_unlock_irqrestore(&disp->vblank.lock, flags); return 0; } @@ -131,29 +135,6 @@ nv50_software_sclass[] = { * software context ******************************************************************************/ -static int -nv50_software_vblsem_release(struct nouveau_eventh *event, int head) -{ - struct nouveau_software_chan *chan = - container_of(event, struct nouveau_software_chan, vblank.event); - struct nv50_software_priv *priv = (void *)nv_object(chan)->engine; - struct nouveau_bar *bar = nouveau_bar(priv); - - nv_wr32(priv, 0x001704, chan->vblank.channel); - nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); - bar->flush(bar); - - if (nv_device(priv)->chipset == 0x50) { - nv_wr32(priv, 0x001570, chan->vblank.offset); - nv_wr32(priv, 0x001574, chan->vblank.value); - } else { - nv_wr32(priv, 0x060010, chan->vblank.offset); - nv_wr32(priv, 0x060014, chan->vblank.value); - } - - return NVKM_EVENT_DROP; -} - static int nv50_software_context_ctor(struct nouveau_object *parent, struct nouveau_object *engine, @@ -169,7 +150,6 @@ nv50_software_context_ctor(struct nouveau_object *parent, return ret; chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12; - chan->base.vblank.event.func = nv50_software_vblsem_release; return 0; } @@ -190,8 +170,8 @@ nv50_software_cclass = { static int nv50_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { struct nv50_software_priv *priv; int ret; diff --git a/trunk/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c b/trunk/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c index a523eaad47e3..282a1cd1bc2f 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c +++ b/trunk/drivers/gpu/drm/nouveau/core/engine/software/nvc0.c @@ -25,9 +25,6 @@ #include #include #include -#include - -#include #include #include @@ -75,12 +72,18 @@ nvc0_software_mthd_vblsem_release(struct nouveau_object *object, u32 mthd, { struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent); struct nouveau_disp *disp = nouveau_disp(object); + unsigned long flags; u32 crtc = *(u32 *)args; if ((nv_device(object)->card_type < NV_E0 && crtc > 1) || crtc > 3) return -EINVAL; - nouveau_event_get(disp->vblank, crtc, &chan->base.vblank.event); + disp->vblank.get(disp->vblank.data, crtc); + + spin_lock_irqsave(&disp->vblank.lock, flags); + list_add(&chan->base.vblank.head, &disp->vblank.list); + chan->base.vblank.crtc = crtc; + spin_unlock_irqrestore(&disp->vblank.lock, flags); return 0; } @@ -114,23 +117,6 @@ nvc0_software_sclass[] = { * software context ******************************************************************************/ -static int -nvc0_software_vblsem_release(struct nouveau_eventh *event, int head) -{ - struct nouveau_software_chan *chan = - container_of(event, struct nouveau_software_chan, vblank.event); - struct nvc0_software_priv *priv = (void *)nv_object(chan)->engine; - struct nouveau_bar *bar = nouveau_bar(priv); - - nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel); - bar->flush(bar); - nv_wr32(priv, 0x06000c, upper_32_bits(chan->vblank.offset)); - nv_wr32(priv, 0x060010, lower_32_bits(chan->vblank.offset)); - nv_wr32(priv, 0x060014, chan->vblank.value); - - return NVKM_EVENT_DROP; -} - static int nvc0_software_context_ctor(struct nouveau_object *parent, struct nouveau_object *engine, @@ -146,7 +132,6 @@ nvc0_software_context_ctor(struct nouveau_object *parent, return ret; chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12; - chan->base.vblank.event.func = nvc0_software_vblsem_release; return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/core/class.h b/trunk/drivers/gpu/drm/nouveau/core/include/core/class.h index 92d3ab11d962..47c4b3a5bd3a 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/core/class.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/core/class.h @@ -154,14 +154,6 @@ struct nve0_channel_ind_class { u32 engine; }; -/* 0046: NV04_DISP - */ - -#define NV04_DISP_CLASS 0x00000046 - -struct nv04_display_class { -}; - /* 5070: NV50_DISP * 8270: NV84_DISP * 8370: NVA0_DISP @@ -198,6 +190,25 @@ struct nv04_display_class { #define NV84_DISP_SOR_HDMI_PWR_REKEY 0x0000007f #define NV50_DISP_SOR_LVDS_SCRIPT 0x00013000 #define NV50_DISP_SOR_LVDS_SCRIPT_ID 0x0000ffff +#define NV94_DISP_SOR_DP_TRAIN 0x00016000 +#define NV94_DISP_SOR_DP_TRAIN_OP 0xf0000000 +#define NV94_DISP_SOR_DP_TRAIN_OP_PATTERN 0x00000000 +#define NV94_DISP_SOR_DP_TRAIN_OP_INIT 0x10000000 +#define NV94_DISP_SOR_DP_TRAIN_OP_FINI 0x20000000 +#define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD 0x00000001 +#define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_OFF 0x00000000 +#define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON 0x00000001 +#define NV94_DISP_SOR_DP_TRAIN_PATTERN 0x00000003 +#define NV94_DISP_SOR_DP_TRAIN_PATTERN_DISABLED 0x00000000 +#define NV94_DISP_SOR_DP_LNKCTL 0x00016040 +#define NV94_DISP_SOR_DP_LNKCTL_FRAME 0x80000000 +#define NV94_DISP_SOR_DP_LNKCTL_FRAME_STD 0x00000000 +#define NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH 0x80000000 +#define NV94_DISP_SOR_DP_LNKCTL_WIDTH 0x00001f00 +#define NV94_DISP_SOR_DP_LNKCTL_COUNT 0x00000007 +#define NV94_DISP_SOR_DP_DRVCTL(l) ((l) * 0x40 + 0x00016100) +#define NV94_DISP_SOR_DP_DRVCTL_VS 0x00000300 +#define NV94_DISP_SOR_DP_DRVCTL_PE 0x00000003 #define NV50_DISP_DAC_MTHD 0x00020000 #define NV50_DISP_DAC_MTHD_TYPE 0x0000f000 @@ -219,23 +230,6 @@ struct nv04_display_class { #define NV50_DISP_DAC_LOAD 0x0002000c #define NV50_DISP_DAC_LOAD_VALUE 0x00000007 -#define NV50_DISP_PIOR_MTHD 0x00030000 -#define NV50_DISP_PIOR_MTHD_TYPE 0x0000f000 -#define NV50_DISP_PIOR_MTHD_OR 0x00000003 - -#define NV50_DISP_PIOR_PWR 0x00030000 -#define NV50_DISP_PIOR_PWR_STATE 0x00000001 -#define NV50_DISP_PIOR_PWR_STATE_ON 0x00000001 -#define NV50_DISP_PIOR_PWR_STATE_OFF 0x00000000 -#define NV50_DISP_PIOR_TMDS_PWR 0x00032000 -#define NV50_DISP_PIOR_TMDS_PWR_STATE 0x00000001 -#define NV50_DISP_PIOR_TMDS_PWR_STATE_ON 0x00000001 -#define NV50_DISP_PIOR_TMDS_PWR_STATE_OFF 0x00000000 -#define NV50_DISP_PIOR_DP_PWR 0x00036000 -#define NV50_DISP_PIOR_DP_PWR_STATE 0x00000001 -#define NV50_DISP_PIOR_DP_PWR_STATE_ON 0x00000001 -#define NV50_DISP_PIOR_DP_PWR_STATE_OFF 0x00000000 - struct nv50_display_class { }; diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/core/client.h b/trunk/drivers/gpu/drm/nouveau/core/include/core/client.h index c66eac513803..63acc0346ff2 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/core/client.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/core/client.h @@ -7,7 +7,7 @@ struct nouveau_client { struct nouveau_namedb base; struct nouveau_handle *root; struct nouveau_object *device; - char name[32]; + char name[16]; u32 debug; struct nouveau_vm *vm; }; @@ -41,6 +41,5 @@ int nouveau_client_create_(const char *name, u64 device, const char *cfg, int nouveau_client_init(struct nouveau_client *); int nouveau_client_fini(struct nouveau_client *, bool suspend); -const char *nouveau_client_name(void *obj); #endif diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/core/device.h b/trunk/drivers/gpu/drm/nouveau/core/include/core/device.h index d351a4e5819c..e58b6f0984c1 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/core/device.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/core/device.h @@ -26,7 +26,6 @@ enum nv_subdev_type { */ NVDEV_SUBDEV_MXM, NVDEV_SUBDEV_MC, - NVDEV_SUBDEV_BUS, NVDEV_SUBDEV_TIMER, NVDEV_SUBDEV_FB, NVDEV_SUBDEV_LTCG, diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/core/enum.h b/trunk/drivers/gpu/drm/nouveau/core/include/core/enum.h index 4fc62bb8c1f0..e7b1e181943b 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/core/enum.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/core/enum.h @@ -5,13 +5,12 @@ struct nouveau_enum { u32 value; const char *name; const void *data; - u32 data2; }; const struct nouveau_enum * nouveau_enum_find(const struct nouveau_enum *, u32 value); -const struct nouveau_enum * +void nouveau_enum_print(const struct nouveau_enum *en, u32 value); struct nouveau_bitfield { diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/core/event.h b/trunk/drivers/gpu/drm/nouveau/core/include/core/event.h deleted file mode 100644 index 9e094408f14e..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/include/core/event.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __NVKM_EVENT_H__ -#define __NVKM_EVENT_H__ - -/* return codes from event handlers */ -#define NVKM_EVENT_DROP 0 -#define NVKM_EVENT_KEEP 1 - -struct nouveau_eventh { - struct list_head head; - int (*func)(struct nouveau_eventh *, int index); -}; - -struct nouveau_event { - spinlock_t lock; - - void *priv; - void (*enable)(struct nouveau_event *, int index); - void (*disable)(struct nouveau_event *, int index); - - int index_nr; - struct { - struct list_head list; - int refs; - } index[]; -}; - -int nouveau_event_create(int index_nr, struct nouveau_event **); -void nouveau_event_destroy(struct nouveau_event **); -void nouveau_event_trigger(struct nouveau_event *, int index); - -void nouveau_event_get(struct nouveau_event *, int index, - struct nouveau_eventh *); -void nouveau_event_put(struct nouveau_event *, int index, - struct nouveau_eventh *); - -#endif diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/core/object.h b/trunk/drivers/gpu/drm/nouveau/core/include/core/object.h index 6a902672f6f4..5982935ee23a 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/core/object.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/core/object.h @@ -133,7 +133,7 @@ static inline u8 nv_ro08(void *obj, u64 addr) { u8 data = nv_ofuncs(obj)->rd08(obj, addr); - nv_spam(obj, "nv_ro08 0x%08llx 0x%02x\n", addr, data); + nv_spam(obj, "nv_ro08 0x%08x 0x%02x\n", addr, data); return data; } @@ -141,7 +141,7 @@ static inline u16 nv_ro16(void *obj, u64 addr) { u16 data = nv_ofuncs(obj)->rd16(obj, addr); - nv_spam(obj, "nv_ro16 0x%08llx 0x%04x\n", addr, data); + nv_spam(obj, "nv_ro16 0x%08x 0x%04x\n", addr, data); return data; } @@ -149,28 +149,28 @@ static inline u32 nv_ro32(void *obj, u64 addr) { u32 data = nv_ofuncs(obj)->rd32(obj, addr); - nv_spam(obj, "nv_ro32 0x%08llx 0x%08x\n", addr, data); + nv_spam(obj, "nv_ro32 0x%08x 0x%08x\n", addr, data); return data; } static inline void nv_wo08(void *obj, u64 addr, u8 data) { - nv_spam(obj, "nv_wo08 0x%08llx 0x%02x\n", addr, data); + nv_spam(obj, "nv_wo08 0x%08x 0x%02x\n", addr, data); nv_ofuncs(obj)->wr08(obj, addr, data); } static inline void nv_wo16(void *obj, u64 addr, u16 data) { - nv_spam(obj, "nv_wo16 0x%08llx 0x%04x\n", addr, data); + nv_spam(obj, "nv_wo16 0x%08x 0x%04x\n", addr, data); nv_ofuncs(obj)->wr16(obj, addr, data); } static inline void nv_wo32(void *obj, u64 addr, u32 data) { - nv_spam(obj, "nv_wo32 0x%08llx 0x%08x\n", addr, data); + nv_spam(obj, "nv_wo32 0x%08x 0x%08x\n", addr, data); nv_ofuncs(obj)->wr32(obj, addr, data); } diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/core/printk.h b/trunk/drivers/gpu/drm/nouveau/core/include/core/printk.h index febed2ea5c80..1d629664f32d 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/core/printk.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/core/printk.h @@ -15,8 +15,7 @@ struct nouveau_object; #define NV_PRINTK_TRACE KERN_DEBUG #define NV_PRINTK_SPAM KERN_DEBUG -void __printf(4, 5) -nv_printk_(struct nouveau_object *, const char *, int, const char *, ...); +void nv_printk_(struct nouveau_object *, const char *, int, const char *, ...); #define nv_printk(o,l,f,a...) do { \ if (NV_DBG_##l <= CONFIG_NOUVEAU_DEBUG) \ diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/engine/disp.h b/trunk/drivers/gpu/drm/nouveau/core/include/engine/disp.h index 28da6772c095..46948285f3e7 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/engine/disp.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/engine/disp.h @@ -4,11 +4,18 @@ #include #include #include -#include struct nouveau_disp { struct nouveau_engine base; - struct nouveau_event *vblank; + + struct { + struct list_head list; + spinlock_t lock; + void (*notify)(void *, int); + void (*get)(void *, int); + void (*put)(void *, int); + void *data; + } vblank; }; static inline struct nouveau_disp * @@ -17,22 +24,16 @@ nouveau_disp(void *obj) return (void *)nv_device(obj)->subdev[NVDEV_ENGINE_DISP]; } -#define nouveau_disp_create(p,e,c,h,i,x,d) \ - nouveau_disp_create_((p), (e), (c), (h), (i), (x), \ - sizeof(**d), (void **)d) -#define nouveau_disp_destroy(d) ({ \ - struct nouveau_disp *disp = (d); \ - _nouveau_disp_dtor(nv_object(disp)); \ -}) +#define nouveau_disp_create(p,e,c,i,x,d) \ + nouveau_engine_create((p), (e), (c), true, (i), (x), (d)) +#define nouveau_disp_destroy(d) \ + nouveau_engine_destroy(&(d)->base) #define nouveau_disp_init(d) \ nouveau_engine_init(&(d)->base) #define nouveau_disp_fini(d,s) \ nouveau_engine_fini(&(d)->base, (s)) -int nouveau_disp_create_(struct nouveau_object *, struct nouveau_object *, - struct nouveau_oclass *, int heads, - const char *, const char *, int, void **); -void _nouveau_disp_dtor(struct nouveau_object *); +#define _nouveau_disp_dtor _nouveau_engine_dtor #define _nouveau_disp_init _nouveau_engine_init #define _nouveau_disp_fini _nouveau_engine_fini diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/engine/fifo.h b/trunk/drivers/gpu/drm/nouveau/core/include/engine/fifo.h index b46c197709f3..f18846c8c6fe 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/engine/fifo.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/engine/fifo.h @@ -65,8 +65,6 @@ struct nouveau_fifo_base { struct nouveau_fifo { struct nouveau_engine base; - struct nouveau_event *uevent; - struct nouveau_object **channel; spinlock_t lock; u16 min; @@ -94,8 +92,6 @@ int nouveau_fifo_create_(struct nouveau_object *, struct nouveau_object *, struct nouveau_oclass *, int min, int max, int size, void **); void nouveau_fifo_destroy(struct nouveau_fifo *); -const char * -nouveau_client_name_for_fifo_chid(struct nouveau_fifo *fifo, u32 chid); #define _nouveau_fifo_init _nouveau_engine_init #define _nouveau_fifo_fini _nouveau_engine_fini diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/engine/software.h b/trunk/drivers/gpu/drm/nouveau/core/include/engine/software.h index 45799487e573..c945691c8564 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/engine/software.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/engine/software.h @@ -3,17 +3,17 @@ #include #include -#include struct nouveau_software_chan { struct nouveau_engctx base; struct { - struct nouveau_eventh event; + struct list_head head; u32 channel; u32 ctxdma; u64 offset; u32 value; + u32 crtc; } vblank; int (*flip)(void *); diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h index 123270e9813a..b79025da581e 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h @@ -16,8 +16,6 @@ enum dcb_output_type { struct dcb_output { int index; /* may not be raw dcb index if merging has happened */ - u16 hasht; - u16 hashm; enum dcb_output_type type; uint8_t i2c_index; uint8_t heads; @@ -27,7 +25,6 @@ struct dcb_output { uint8_t or; uint8_t link; bool duallink_possible; - uint8_t extdev; union { struct sor_conf { int link; diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h index 96d3364f6db3..e6563b5cb08e 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h @@ -1,22 +1,17 @@ #ifndef __NVBIOS_GPIO_H__ #define __NVBIOS_GPIO_H__ +struct nouveau_bios; + enum dcb_gpio_func_name { DCB_GPIO_PANEL_POWER = 0x01, DCB_GPIO_TVDAC0 = 0x0c, DCB_GPIO_TVDAC1 = 0x2d, - DCB_GPIO_FAN = 0x09, + DCB_GPIO_PWM_FAN = 0x09, DCB_GPIO_FAN_SENSE = 0x3d, DCB_GPIO_UNUSED = 0xff }; -#define DCB_GPIO_LOG_DIR 0x02 -#define DCB_GPIO_LOG_DIR_OUT 0x00 -#define DCB_GPIO_LOG_DIR_IN 0x02 -#define DCB_GPIO_LOG_VAL 0x01 -#define DCB_GPIO_LOG_VAL_LO 0x00 -#define DCB_GPIO_LOG_VAL_HI 0x01 - struct dcb_gpio_func { u8 func; u8 line; diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h index 10b57a19a7de..5079bedfd985 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h @@ -15,7 +15,7 @@ struct dcb_i2c_entry { enum dcb_i2c_type type; u8 drive; u8 sense; - u8 share; + u32 data; }; u16 dcb_i2c_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h index 083541dbe9c8..a2c4296fc5f6 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h @@ -23,27 +23,11 @@ struct nvbios_therm_sensor { struct nvbios_therm_threshold thrs_shutdown; }; -/* no vbios have more than 6 */ -#define NOUVEAU_TEMP_FAN_TRIP_MAX 10 -struct nouveau_therm_trip_point { - int fan_duty; - int temp; - int hysteresis; -}; - struct nvbios_therm_fan { u16 pwm_freq; u8 min_duty; u8 max_duty; - - u16 bump_period; - u16 slow_down_period; - - struct nouveau_therm_trip_point trip[NOUVEAU_TEMP_FAN_TRIP_MAX]; - u8 nr_fan_trip; - u8 linear_min_temp; - u8 linear_max_temp; }; enum nvbios_therm_domain { diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/xpio.h b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/xpio.h deleted file mode 100644 index 360baab52e4c..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bios/xpio.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __NVBIOS_XPIO_H__ -#define __NVBIOS_XPIO_H__ - -#define NVBIOS_XPIO_FLAG_AUX 0x10 -#define NVBIOS_XPIO_FLAG_AUX0 0x00 -#define NVBIOS_XPIO_FLAG_AUX1 0x10 - -struct nvbios_xpio { - u8 type; - u8 addr; - u8 flags; -}; - -u16 dcb_xpio_table(struct nouveau_bios *, u8 idx, - u8 *ver, u8 *hdr, u8 *cnt, u8 *len); -u16 dcb_xpio_parse(struct nouveau_bios *, u8 idx, - u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_xpio *); - -#endif diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bus.h b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bus.h deleted file mode 100644 index 7d88ec4a6d06..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/bus.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __NOUVEAU_BUS_H__ -#define __NOUVEAU_BUS_H__ - -#include -#include - -struct nouveau_bus_intr { - u32 stat; - u32 unit; -}; - -struct nouveau_bus { - struct nouveau_subdev base; -}; - -static inline struct nouveau_bus * -nouveau_bus(void *obj) -{ - return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_BUS]; -} - -#define nouveau_bus_create(p, e, o, d) \ - nouveau_subdev_create_((p), (e), (o), 0, "PBUS", "master", \ - sizeof(**d), (void **)d) -#define nouveau_bus_destroy(p) \ - nouveau_subdev_destroy(&(p)->base) -#define nouveau_bus_init(p) \ - nouveau_subdev_init(&(p)->base) -#define nouveau_bus_fini(p, s) \ - nouveau_subdev_fini(&(p)->base, (s)) - -#define _nouveau_bus_dtor _nouveau_subdev_dtor -#define _nouveau_bus_init _nouveau_subdev_init -#define _nouveau_bus_fini _nouveau_subdev_fini - -extern struct nouveau_oclass nv04_bus_oclass; -extern struct nouveau_oclass nv31_bus_oclass; -extern struct nouveau_oclass nv50_bus_oclass; -extern struct nouveau_oclass nvc0_bus_oclass; - -#endif diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h index c85b9f1579ad..b75e8f18e52c 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/gpio.h @@ -3,7 +3,6 @@ #include #include -#include #include #include @@ -11,18 +10,28 @@ struct nouveau_gpio { struct nouveau_subdev base; - struct nouveau_event *events; - /* hardware interfaces */ void (*reset)(struct nouveau_gpio *, u8 func); int (*drive)(struct nouveau_gpio *, int line, int dir, int out); int (*sense)(struct nouveau_gpio *, int line); + void (*irq_enable)(struct nouveau_gpio *, int line, bool); /* software interfaces */ int (*find)(struct nouveau_gpio *, int idx, u8 tag, u8 line, struct dcb_gpio_func *); int (*set)(struct nouveau_gpio *, int idx, u8 tag, u8 line, int state); int (*get)(struct nouveau_gpio *, int idx, u8 tag, u8 line); + int (*irq)(struct nouveau_gpio *, int idx, u8 tag, u8 line, bool on); + + /* interrupt handling */ + struct list_head isr; + spinlock_t lock; + + void (*isr_run)(struct nouveau_gpio *, int idx, u32 mask); + int (*isr_add)(struct nouveau_gpio *, int idx, u8 tag, u8 line, + void (*)(void *, int state), void *data); + void (*isr_del)(struct nouveau_gpio *, int idx, u8 tag, u8 line, + void (*)(void *, int state), void *data); }; static inline struct nouveau_gpio * @@ -31,23 +40,25 @@ nouveau_gpio(void *obj) return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_GPIO]; } -#define nouveau_gpio_create(p,e,o,l,d) \ - nouveau_gpio_create_((p), (e), (o), (l), sizeof(**d), (void **)d) -#define nouveau_gpio_destroy(p) ({ \ - struct nouveau_gpio *gpio = (p); \ - _nouveau_gpio_dtor(nv_object(gpio)); \ -}) +#define nouveau_gpio_create(p,e,o,d) \ + nouveau_gpio_create_((p), (e), (o), sizeof(**d), (void **)d) +#define nouveau_gpio_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) #define nouveau_gpio_fini(p,s) \ nouveau_subdev_fini(&(p)->base, (s)) -int nouveau_gpio_create_(struct nouveau_object *, struct nouveau_object *, - struct nouveau_oclass *, int, int, void **); -void _nouveau_gpio_dtor(struct nouveau_object *); -int nouveau_gpio_init(struct nouveau_gpio *); +int nouveau_gpio_create_(struct nouveau_object *, struct nouveau_object *, + struct nouveau_oclass *, int, void **); +int nouveau_gpio_init(struct nouveau_gpio *); extern struct nouveau_oclass nv10_gpio_oclass; extern struct nouveau_oclass nv50_gpio_oclass; extern struct nouveau_oclass nvd0_gpio_oclass; -extern struct nouveau_oclass nve0_gpio_oclass; + +void nv50_gpio_dtor(struct nouveau_object *); +int nv50_gpio_init(struct nouveau_object *); +int nv50_gpio_fini(struct nouveau_object *, bool); +void nv50_gpio_intr(struct nouveau_subdev *); +void nv50_gpio_irq_enable(struct nouveau_gpio *, int line, bool); #endif diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h index 888384c0bed8..b93ab01e3785 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h @@ -10,59 +10,23 @@ #define NV_I2C_PORT(n) (0x00 + (n)) #define NV_I2C_DEFAULT(n) (0x80 + (n)) -#define NV_I2C_TYPE_DCBI2C(n) (0x0000 | (n)) -#define NV_I2C_TYPE_EXTDDC(e) (0x0005 | (e) << 8) -#define NV_I2C_TYPE_EXTAUX(e) (0x0006 | (e) << 8) - struct nouveau_i2c_port { - struct nouveau_object base; struct i2c_adapter adapter; - + struct nouveau_i2c *i2c; + struct i2c_algo_bit_data bit; struct list_head head; u8 index; - - const struct nouveau_i2c_func *func; -}; - -struct nouveau_i2c_func { - void (*acquire)(struct nouveau_i2c_port *); - void (*release)(struct nouveau_i2c_port *); - - void (*drive_scl)(struct nouveau_i2c_port *, int); - void (*drive_sda)(struct nouveau_i2c_port *, int); - int (*sense_scl)(struct nouveau_i2c_port *); - int (*sense_sda)(struct nouveau_i2c_port *); - - int (*aux)(struct nouveau_i2c_port *, u8, u32, u8 *, u8); - int (*pattern)(struct nouveau_i2c_port *, int pattern); - int (*lnk_ctl)(struct nouveau_i2c_port *, int nr, int bw, bool enh); - int (*drv_ctl)(struct nouveau_i2c_port *, int lane, int sw, int pe); + u8 type; + u32 dcb; + u32 drive; + u32 sense; + u32 state; }; -#define nouveau_i2c_port_create(p,e,o,i,a,d) \ - nouveau_i2c_port_create_((p), (e), (o), (i), (a), \ - sizeof(**d), (void **)d) -#define nouveau_i2c_port_destroy(p) ({ \ - struct nouveau_i2c_port *port = (p); \ - _nouveau_i2c_port_dtor(nv_object(i2c)); \ -}) -#define nouveau_i2c_port_init(p) \ - nouveau_object_init(&(p)->base) -#define nouveau_i2c_port_fini(p,s) \ - nouveau_object_fini(&(p)->base, (s)) - -int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *, - struct nouveau_oclass *, u8, - const struct i2c_algorithm *, int, void **); -void _nouveau_i2c_port_dtor(struct nouveau_object *); -#define _nouveau_i2c_port_init nouveau_object_init -#define _nouveau_i2c_port_fini nouveau_object_fini - struct nouveau_i2c { struct nouveau_subdev base; struct nouveau_i2c_port *(*find)(struct nouveau_i2c *, u8 index); - struct nouveau_i2c_port *(*find_type)(struct nouveau_i2c *, u16 type); int (*identify)(struct nouveau_i2c *, int index, const char *what, struct i2c_board_info *, bool (*match)(struct nouveau_i2c_port *, @@ -76,76 +40,21 @@ nouveau_i2c(void *obj) return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_I2C]; } -#define nouveau_i2c_create(p,e,o,s,d) \ - nouveau_i2c_create_((p), (e), (o), (s), sizeof(**d), (void **)d) -#define nouveau_i2c_destroy(p) ({ \ - struct nouveau_i2c *i2c = (p); \ - _nouveau_i2c_dtor(nv_object(i2c)); \ -}) -#define nouveau_i2c_init(p) ({ \ - struct nouveau_i2c *i2c = (p); \ - _nouveau_i2c_init(nv_object(i2c)); \ -}) -#define nouveau_i2c_fini(p,s) ({ \ - struct nouveau_i2c *i2c = (p); \ - _nouveau_i2c_fini(nv_object(i2c), (s)); \ -}) - -int nouveau_i2c_create_(struct nouveau_object *, struct nouveau_object *, - struct nouveau_oclass *, struct nouveau_oclass *, - int, void **); -void _nouveau_i2c_dtor(struct nouveau_object *); -int _nouveau_i2c_init(struct nouveau_object *); -int _nouveau_i2c_fini(struct nouveau_object *, bool); - -extern struct nouveau_oclass nv04_i2c_oclass; -extern struct nouveau_oclass nv4e_i2c_oclass; -extern struct nouveau_oclass nv50_i2c_oclass; -extern struct nouveau_oclass nv94_i2c_oclass; -extern struct nouveau_oclass nvd0_i2c_oclass; -extern struct nouveau_oclass nouveau_anx9805_sclass[]; - -extern const struct i2c_algorithm nouveau_i2c_bit_algo; -extern const struct i2c_algorithm nouveau_i2c_aux_algo; - -static inline int -nv_rdi2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg) -{ - u8 val; - struct i2c_msg msgs[] = { - { .addr = addr, .flags = 0, .len = 1, .buf = ® }, - { .addr = addr, .flags = I2C_M_RD, .len = 1, .buf = &val }, - }; - - int ret = i2c_transfer(&port->adapter, msgs, 2); - if (ret != 2) - return -EIO; - - return val; -} - -static inline int -nv_wri2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg, u8 val) -{ - u8 buf[2] = { reg, val }; - struct i2c_msg msgs[] = { - { .addr = addr, .flags = 0, .len = 2, .buf = buf }, - }; - - int ret = i2c_transfer(&port->adapter, msgs, 1); - if (ret != 1) - return -EIO; +extern struct nouveau_oclass nouveau_i2c_oclass; - return 0; -} +void nouveau_i2c_drive_scl(void *, int); +void nouveau_i2c_drive_sda(void *, int); +int nouveau_i2c_sense_scl(void *); +int nouveau_i2c_sense_sda(void *); -static inline bool -nv_probe_i2c(struct nouveau_i2c_port *port, u8 addr) -{ - return nv_rdi2cr(port, addr, 0) >= 0; -} +int nv_rdi2cr(struct nouveau_i2c_port *, u8 addr, u8 reg); +int nv_wri2cr(struct nouveau_i2c_port *, u8 addr, u8 reg, u8 val); +bool nv_probe_i2c(struct nouveau_i2c_port *, u8 addr); int nv_rdaux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size); int nv_wraux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size); +extern const struct i2c_algorithm nouveau_i2c_bit_algo; +extern const struct i2c_algorithm nouveau_i2c_aux_algo; + #endif diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/therm.h b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/therm.h index 6b17b614629f..faee569fd458 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/therm.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/therm.h @@ -4,10 +4,10 @@ #include #include -enum nouveau_therm_mode { - NOUVEAU_THERM_CTRL_NONE = 0, - NOUVEAU_THERM_CTRL_MANUAL = 1, - NOUVEAU_THERM_CTRL_AUTO = 2, +enum nouveau_therm_fan_mode { + FAN_CONTROL_NONE = 0, + FAN_CONTROL_MANUAL = 1, + FAN_CONTROL_NR, }; enum nouveau_therm_attr_type { @@ -28,11 +28,6 @@ enum nouveau_therm_attr_type { struct nouveau_therm { struct nouveau_subdev base; - int (*pwm_ctrl)(struct nouveau_therm *, int line, bool); - int (*pwm_get)(struct nouveau_therm *, int line, u32 *, u32 *); - int (*pwm_set)(struct nouveau_therm *, int line, u32, u32); - int (*pwm_clock)(struct nouveau_therm *); - int (*fan_get)(struct nouveau_therm *); int (*fan_set)(struct nouveau_therm *, int); int (*fan_sense)(struct nouveau_therm *); @@ -51,29 +46,13 @@ nouveau_therm(void *obj) } #define nouveau_therm_create(p,e,o,d) \ - nouveau_therm_create_((p), (e), (o), sizeof(**d), (void **)d) -#define nouveau_therm_destroy(p) ({ \ - struct nouveau_therm *therm = (p); \ - _nouveau_therm_dtor(nv_object(therm)); \ -}) -#define nouveau_therm_init(p) ({ \ - struct nouveau_therm *therm = (p); \ - _nouveau_therm_init(nv_object(therm)); \ -}) -#define nouveau_therm_fini(p,s) ({ \ - struct nouveau_therm *therm = (p); \ - _nouveau_therm_init(nv_object(therm), (s)); \ -}) + nouveau_subdev_create((p), (e), (o), 0, "THERM", "therm", d) +#define nouveau_therm_destroy(p) \ + nouveau_subdev_destroy(&(p)->base) -int nouveau_therm_create_(struct nouveau_object *, struct nouveau_object *, - struct nouveau_oclass *, int, void **); -void _nouveau_therm_dtor(struct nouveau_object *); -int _nouveau_therm_init(struct nouveau_object *); -int _nouveau_therm_fini(struct nouveau_object *, bool); +#define _nouveau_therm_dtor _nouveau_subdev_dtor extern struct nouveau_oclass nv40_therm_oclass; extern struct nouveau_oclass nv50_therm_oclass; -extern struct nouveau_oclass nva3_therm_oclass; -extern struct nouveau_oclass nvd0_therm_oclass; #endif diff --git a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/timer.h b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/timer.h index e465d158d352..c24ec8ab3db4 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/include/subdev/timer.h +++ b/trunk/drivers/gpu/drm/nouveau/core/include/subdev/timer.h @@ -10,14 +10,6 @@ struct nouveau_alarm { void (*func)(struct nouveau_alarm *); }; -static inline void -nouveau_alarm_init(struct nouveau_alarm *alarm, - void (*func)(struct nouveau_alarm *)) -{ - INIT_LIST_HEAD(&alarm->head); - alarm->func = func; -} - bool nouveau_timer_wait_eq(void *, u64 nsec, u32 addr, u32 mask, u32 data); bool nouveau_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data); bool nouveau_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data); diff --git a/trunk/drivers/gpu/drm/nouveau/core/os.h b/trunk/drivers/gpu/drm/nouveau/core/os.h index eb496033b55c..cfe3b9cad156 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/os.h +++ b/trunk/drivers/gpu/drm/nouveau/core/os.h @@ -16,7 +16,6 @@ #include #include #include -#include #include diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index e816f06637a7..f621f69fa1a2 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -172,7 +172,7 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios) nv_wr32(bios, pcireg, access); } -#if defined(CONFIG_ACPI) && defined(CONFIG_X86) +#if defined(CONFIG_ACPI) int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); bool nouveau_acpi_rom_supported(struct pci_dev *pdev); #else diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c index 2d9b9d7a7992..0fd87df99dd6 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c @@ -107,18 +107,6 @@ dcb_outp(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len) return 0x0000; } -static inline u16 -dcb_outp_hasht(struct dcb_output *outp) -{ - return (outp->extdev << 8) | (outp->location << 4) | outp->type; -} - -static inline u16 -dcb_outp_hashm(struct dcb_output *outp) -{ - return (outp->heads << 8) | (outp->link << 6) | outp->or; -} - u16 dcb_outp_parse(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len, struct dcb_output *outp) @@ -147,28 +135,34 @@ dcb_outp_parse(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len, case DCB_OUTPUT_DP: outp->link = (conf & 0x00000030) >> 4; outp->sorconf.link = outp->link; /*XXX*/ - outp->extdev = 0x00; - if (outp->location != 0) - outp->extdev = (conf & 0x0000ff00) >> 8; break; default: break; } } - - outp->hasht = dcb_outp_hasht(outp); - outp->hashm = dcb_outp_hashm(outp); } return dcb; } +static inline u16 +dcb_outp_hasht(struct dcb_output *outp) +{ + return outp->type; +} + +static inline u16 +dcb_outp_hashm(struct dcb_output *outp) +{ + return (outp->heads << 8) | (outp->link << 6) | outp->or; +} + u16 dcb_outp_match(struct nouveau_bios *bios, u16 type, u16 mask, u8 *ver, u8 *len, struct dcb_output *outp) { u16 dcb, idx = 0; while ((dcb = dcb_outp_parse(bios, idx++, ver, len, outp))) { - if ((dcb_outp_hasht(outp) & 0x00ff) == (type & 0x00ff)) { + if (dcb_outp_hasht(outp) == type) { if ((dcb_outp_hashm(outp) & mask) == mask) break; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/extdev.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/extdev.c index b2a676e53580..5afb568b2d69 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/extdev.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/extdev.c @@ -48,7 +48,7 @@ extdev_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *len, u8 *cnt) return extdev + *hdr; } -static u16 +u16 nvbios_extdev_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len) { u8 hdr, cnt; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c index 172a4f999990..c84e93fa6d95 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c @@ -25,7 +25,6 @@ #include #include #include -#include u16 dcb_gpio_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) @@ -61,14 +60,8 @@ dcb_gpio_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) u16 dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver, u8 *len) { - u8 hdr, cnt, xver; /* use gpio version for xpio entry parsing */ - u16 gpio; - - if (!idx--) - gpio = dcb_gpio_table(bios, ver, &hdr, &cnt, len); - else - gpio = dcb_xpio_table(bios, idx, &xver, &hdr, &cnt, len); - + u8 hdr, cnt; + u16 gpio = !idx ? dcb_gpio_table(bios, ver, &hdr, &cnt, len) : 0x0000; if (gpio && ent < cnt) return gpio + hdr + (ent * *len); return 0x0000; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c index cfb9288c6d28..ad577db83766 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c @@ -70,12 +70,12 @@ dcb_i2c_parse(struct nouveau_bios *bios, u8 idx, struct dcb_i2c_entry *info) u8 ver, len; u16 ent = dcb_i2c_entry(bios, idx, &ver, &len); if (ent) { - info->type = nv_ro08(bios, ent + 3); - info->share = DCB_I2C_UNUSED; + info->data = nv_ro32(bios, ent + 0); + info->type = nv_ro08(bios, ent + 3); if (ver < 0x30) { info->type &= 0x07; if (info->type == 0x07) - info->type = DCB_I2C_UNUSED; + info->type = 0xff; } switch (info->type) { @@ -88,11 +88,7 @@ dcb_i2c_parse(struct nouveau_bios *bios, u8 idx, struct dcb_i2c_entry *info) return 0; case DCB_I2C_NVIO_BIT: case DCB_I2C_NVIO_AUX: - info->drive = nv_ro08(bios, ent + 0) & 0x0f; - if (nv_ro08(bios, ent + 1) & 0x01) { - info->share = nv_ro08(bios, ent + 1) >> 1; - info->share &= 0x0f; - } + info->drive = nv_ro08(bios, ent + 0); return 0; case DCB_I2C_UNUSED: return 0; @@ -125,8 +121,7 @@ dcb_i2c_parse(struct nouveau_bios *bios, u8 idx, struct dcb_i2c_entry *info) if (!info->sense) info->sense = 0x36; } - info->type = DCB_I2C_NV04_BIT; - info->share = DCB_I2C_UNUSED; + info->type = DCB_I2C_NV04_BIT; return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/init.c index 2cc1e6a5eb6a..690ed438b2ad 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/init.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/init.c @@ -231,11 +231,6 @@ init_i2c(struct nvbios_init *init, int index) return NULL; } - if (index == -2 && init->outp->location) { - index = NV_I2C_TYPE_EXTAUX(init->outp->extdev); - return i2c->find_type(i2c, index); - } - index = init->outp->i2c_index; } @@ -263,7 +258,7 @@ init_wri2cr(struct nvbios_init *init, u8 index, u8 addr, u8 reg, u8 val) static int init_rdauxr(struct nvbios_init *init, u32 addr) { - struct nouveau_i2c_port *port = init_i2c(init, -2); + struct nouveau_i2c_port *port = init_i2c(init, -1); u8 data; if (port && init_exec(init)) { @@ -279,7 +274,7 @@ init_rdauxr(struct nvbios_init *init, u32 addr) static int init_wrauxr(struct nvbios_init *init, u32 addr, u8 data) { - struct nouveau_i2c_port *port = init_i2c(init, -2); + struct nouveau_i2c_port *port = init_i2c(init, -1); if (port && init_exec(init)) return nv_wraux(port, addr, &data, 1); return -ENODEV; @@ -1821,7 +1816,7 @@ init_ram_restrict_zm_reg_group(struct nvbios_init *init) u8 i, j; trace("RAM_RESTRICT_ZM_REG_GROUP\t" - "R[0x%08x] 0x%02x 0x%02x\n", addr, incr, num); + "R[%08x] 0x%02x 0x%02x\n", addr, incr, num); init->offset += 7; for (i = 0; i < num; i++) { @@ -1854,7 +1849,7 @@ init_copy_zm_reg(struct nvbios_init *init) u32 sreg = nv_ro32(bios, init->offset + 1); u32 dreg = nv_ro32(bios, init->offset + 5); - trace("COPY_ZM_REG\tR[0x%06x] = R[0x%06x]\n", dreg, sreg); + trace("COPY_ZM_REG\tR[0x%06x] = R[0x%06x]\n", sreg, dreg); init->offset += 9; init_wr32(init, dreg, init_rd32(init, sreg)); @@ -1871,7 +1866,7 @@ init_zm_reg_group(struct nvbios_init *init) u32 addr = nv_ro32(bios, init->offset + 1); u8 count = nv_ro08(bios, init->offset + 5); - trace("ZM_REG_GROUP\tR[0x%06x] =\n", addr); + trace("ZM_REG_GROUP\tR[0x%06x] =\n"); init->offset += 6; while (count--) { diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c index 22a20573ed1b..862a08a2ae27 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c @@ -55,7 +55,7 @@ therm_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *len, u8 *cnt) return therm + nv_ro08(bios, therm + 1); } -static u16 +u16 nvbios_therm_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len) { u8 hdr, cnt; @@ -155,15 +155,10 @@ int nvbios_therm_fan_parse(struct nouveau_bios *bios, struct nvbios_therm_fan *fan) { - struct nouveau_therm_trip_point *cur_trip = NULL; u8 ver, len, i; u16 entry; - uint8_t duty_lut[] = { 0, 0, 25, 0, 40, 0, 50, 0, - 75, 0, 85, 0, 100, 0, 100, 0 }; - i = 0; - fan->nr_fan_trip = 0; while ((entry = nvbios_therm_entry(bios, i++, &ver, &len))) { s16 value = nv_ro16(bios, entry + 1); @@ -172,30 +167,9 @@ nvbios_therm_fan_parse(struct nouveau_bios *bios, fan->min_duty = value & 0xff; fan->max_duty = (value & 0xff00) >> 8; break; - case 0x24: - fan->nr_fan_trip++; - cur_trip = &fan->trip[fan->nr_fan_trip - 1]; - cur_trip->hysteresis = value & 0xf; - cur_trip->temp = (value & 0xff0) >> 4; - cur_trip->fan_duty = duty_lut[(value & 0xf000) >> 12]; - break; - case 0x25: - cur_trip = &fan->trip[fan->nr_fan_trip - 1]; - cur_trip->fan_duty = value; - break; case 0x26: fan->pwm_freq = value; break; - case 0x3b: - fan->bump_period = value; - break; - case 0x3c: - fan->slow_down_period = value; - break; - case 0x46: - fan->linear_min_temp = nv_ro08(bios, entry + 1); - fan->linear_max_temp = nv_ro08(bios, entry + 2); - break; } } diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/xpio.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/xpio.c deleted file mode 100644 index e9b8e5d30a7a..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/bios/xpio.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include -#include -#include - -static u16 -dcb_xpiod_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) -{ - u16 data = dcb_gpio_table(bios, ver, hdr, cnt, len); - if (data && *ver >= 0x40 && *hdr >= 0x06) { - u16 xpio = nv_ro16(bios, data + 0x04); - if (xpio) { - *ver = nv_ro08(bios, data + 0x00); - *hdr = nv_ro08(bios, data + 0x01); - *cnt = nv_ro08(bios, data + 0x02); - *len = nv_ro08(bios, data + 0x03); - return xpio; - } - } - return 0x0000; -} - -u16 -dcb_xpio_table(struct nouveau_bios *bios, u8 idx, - u8 *ver, u8 *hdr, u8 *cnt, u8 *len) -{ - u16 data = dcb_xpiod_table(bios, ver, hdr, cnt, len); - if (data && idx < *cnt) { - u16 xpio = nv_ro16(bios, data + *hdr + (idx * *len)); - if (xpio) { - *ver = nv_ro08(bios, data + 0x00); - *hdr = nv_ro08(bios, data + 0x01); - *cnt = nv_ro08(bios, data + 0x02); - *len = nv_ro08(bios, data + 0x03); - return xpio; - } - } - return 0x0000; -} - -u16 -dcb_xpio_parse(struct nouveau_bios *bios, u8 idx, - u8 *ver, u8 *hdr, u8 *cnt, u8 *len, - struct nvbios_xpio *info) -{ - u16 data = dcb_xpio_table(bios, idx, ver, hdr, cnt, len); - if (data && *len >= 6) { - info->type = nv_ro08(bios, data + 0x04); - info->addr = nv_ro08(bios, data + 0x05); - info->flags = nv_ro08(bios, data + 0x06); - } - return 0x0000; -} diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c deleted file mode 100644 index 8c7f8057a185..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2012 Nouveau Community - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Martin Peres - * Ben Skeggs - */ - -#include - -struct nv04_bus_priv { - struct nouveau_bus base; -}; - -static void -nv04_bus_intr(struct nouveau_subdev *subdev) -{ - struct nouveau_bus *pbus = nouveau_bus(subdev); - u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140); - - if (stat & 0x00000001) { - nv_error(pbus, "BUS ERROR\n"); - stat &= ~0x00000001; - nv_wr32(pbus, 0x001100, 0x00000001); - } - - if (stat & 0x00000110) { - subdev = nouveau_subdev(subdev, NVDEV_SUBDEV_GPIO); - if (subdev && subdev->intr) - subdev->intr(subdev); - stat &= ~0x00000110; - nv_wr32(pbus, 0x001100, 0x00000110); - } - - if (stat) { - nv_error(pbus, "unknown intr 0x%08x\n", stat); - nv_mask(pbus, 0x001140, stat, 0x00000000); - } -} - -static int -nv04_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nv04_bus_priv *priv; - int ret; - - ret = nouveau_bus_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->intr = nv04_bus_intr; - return 0; -} - -static int -nv04_bus_init(struct nouveau_object *object) -{ - struct nv04_bus_priv *priv = (void *)object; - - nv_wr32(priv, 0x001100, 0xffffffff); - nv_wr32(priv, 0x001140, 0x00000111); - - return nouveau_bus_init(&priv->base); -} - -struct nouveau_oclass -nv04_bus_oclass = { - .handle = NV_SUBDEV(BUS, 0x04), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv04_bus_ctor, - .dtor = _nouveau_bus_dtor, - .init = nv04_bus_init, - .fini = _nouveau_bus_fini, - }, -}; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/bus/nv31.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/bus/nv31.c deleted file mode 100644 index 34132aef34e1..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/bus/nv31.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2012 Nouveau Community - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Martin Peres - * Ben Skeggs - */ - -#include - -struct nv31_bus_priv { - struct nouveau_bus base; -}; - -static void -nv31_bus_intr(struct nouveau_subdev *subdev) -{ - struct nouveau_bus *pbus = nouveau_bus(subdev); - u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140); - u32 gpio = nv_rd32(pbus, 0x001104) & nv_rd32(pbus, 0x001144); - - if (gpio) { - subdev = nouveau_subdev(pbus, NVDEV_SUBDEV_GPIO); - if (subdev && subdev->intr) - subdev->intr(subdev); - } - - if (stat & 0x00000008) { /* NV41- */ - u32 addr = nv_rd32(pbus, 0x009084); - u32 data = nv_rd32(pbus, 0x009088); - - nv_error(pbus, "MMIO %s of 0x%08x FAULT at 0x%06x\n", - (addr & 0x00000002) ? "write" : "read", data, - (addr & 0x00fffffc)); - - stat &= ~0x00000008; - nv_wr32(pbus, 0x001100, 0x00000008); - } - - if (stat & 0x00070000) { - subdev = nouveau_subdev(pbus, NVDEV_SUBDEV_THERM); - if (subdev && subdev->intr) - subdev->intr(subdev); - stat &= ~0x00070000; - nv_wr32(pbus, 0x001100, 0x00070000); - } - - if (stat) { - nv_error(pbus, "unknown intr 0x%08x\n", stat); - nv_mask(pbus, 0x001140, stat, 0x00000000); - } -} - -static int -nv31_bus_init(struct nouveau_object *object) -{ - struct nv31_bus_priv *priv = (void *)object; - int ret; - - ret = nouveau_bus_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x001100, 0xffffffff); - nv_wr32(priv, 0x001140, 0x00070008); - return 0; -} - -static int -nv31_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nv31_bus_priv *priv; - int ret; - - ret = nouveau_bus_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->intr = nv31_bus_intr; - return 0; -} - -struct nouveau_oclass -nv31_bus_oclass = { - .handle = NV_SUBDEV(BUS, 0x31), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv31_bus_ctor, - .dtor = _nouveau_bus_dtor, - .init = nv31_bus_init, - .fini = _nouveau_bus_fini, - }, -}; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c deleted file mode 100644 index f5b2117fa8c6..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2012 Nouveau Community - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Martin Peres - * Ben Skeggs - */ - -#include - -struct nv50_bus_priv { - struct nouveau_bus base; -}; - -static void -nv50_bus_intr(struct nouveau_subdev *subdev) -{ - struct nouveau_bus *pbus = nouveau_bus(subdev); - u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140); - - if (stat & 0x00000008) { - u32 addr = nv_rd32(pbus, 0x009084); - u32 data = nv_rd32(pbus, 0x009088); - - nv_error(pbus, "MMIO %s of 0x%08x FAULT at 0x%06x\n", - (addr & 0x00000002) ? "write" : "read", data, - (addr & 0x00fffffc)); - - stat &= ~0x00000008; - nv_wr32(pbus, 0x001100, 0x00000008); - } - - if (stat & 0x00010000) { - subdev = nouveau_subdev(pbus, NVDEV_SUBDEV_THERM); - if (subdev && subdev->intr) - subdev->intr(subdev); - stat &= ~0x00010000; - nv_wr32(pbus, 0x001100, 0x00010000); - } - - if (stat) { - nv_error(pbus, "unknown intr 0x%08x\n", stat); - nv_mask(pbus, 0x001140, stat, 0); - } -} - -static int -nv50_bus_init(struct nouveau_object *object) -{ - struct nv50_bus_priv *priv = (void *)object; - int ret; - - ret = nouveau_bus_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x001100, 0xffffffff); - nv_wr32(priv, 0x001140, 0x00010008); - return 0; -} - -static int -nv50_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nv50_bus_priv *priv; - int ret; - - ret = nouveau_bus_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->intr = nv50_bus_intr; - return 0; -} - -struct nouveau_oclass -nv50_bus_oclass = { - .handle = NV_SUBDEV(BUS, 0x50), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv50_bus_ctor, - .dtor = _nouveau_bus_dtor, - .init = nv50_bus_init, - .fini = _nouveau_bus_fini, - }, -}; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/bus/nvc0.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/bus/nvc0.c deleted file mode 100644 index b192d6246363..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/bus/nvc0.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2012 Nouveau Community - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Martin Peres - * Ben Skeggs - */ - -#include - -struct nvc0_bus_priv { - struct nouveau_bus base; -}; - -static void -nvc0_bus_intr(struct nouveau_subdev *subdev) -{ - struct nouveau_bus *pbus = nouveau_bus(subdev); - u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140); - - if (stat & 0x0000000e) { - u32 addr = nv_rd32(pbus, 0x009084); - u32 data = nv_rd32(pbus, 0x009088); - - nv_error(pbus, "MMIO %s of 0x%08x FAULT at 0x%06x [ %s%s%s]\n", - (addr & 0x00000002) ? "write" : "read", data, - (addr & 0x00fffffc), - (stat & 0x00000002) ? "!ENGINE " : "", - (stat & 0x00000004) ? "IBUS " : "", - (stat & 0x00000008) ? "TIMEOUT " : ""); - - nv_wr32(pbus, 0x009084, 0x00000000); - nv_wr32(pbus, 0x001100, (stat & 0x0000000e)); - stat &= ~0x0000000e; - } - - if (stat) { - nv_error(pbus, "unknown intr 0x%08x\n", stat); - nv_mask(pbus, 0x001140, stat, 0x00000000); - } -} - -static int -nvc0_bus_init(struct nouveau_object *object) -{ - struct nvc0_bus_priv *priv = (void *)object; - int ret; - - ret = nouveau_bus_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0x001100, 0xffffffff); - nv_wr32(priv, 0x001140, 0x0000000e); - return 0; -} - -static int -nvc0_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nvc0_bus_priv *priv; - int ret; - - ret = nouveau_bus_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - nv_subdev(priv)->intr = nvc0_bus_intr; - return 0; -} - -struct nouveau_oclass -nvc0_bus_oclass = { - .handle = NV_SUBDEV(BUS, 0xc0), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nvc0_bus_ctor, - .dtor = _nouveau_bus_dtor, - .init = nvc0_bus_init, - .fini = _nouveau_bus_fini, - }, -}; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/base.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/base.c index 3937ced5c753..f8a7ed4166cf 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/base.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/base.c @@ -66,7 +66,6 @@ static const u64 disable_map[] = { [NVDEV_SUBDEV_CLOCK] = NV_DEVICE_DISABLE_CORE, [NVDEV_SUBDEV_MXM] = NV_DEVICE_DISABLE_CORE, [NVDEV_SUBDEV_MC] = NV_DEVICE_DISABLE_CORE, - [NVDEV_SUBDEV_BUS] = NV_DEVICE_DISABLE_CORE, [NVDEV_SUBDEV_TIMER] = NV_DEVICE_DISABLE_CORE, [NVDEV_SUBDEV_FB] = NV_DEVICE_DISABLE_CORE, [NVDEV_SUBDEV_LTCG] = NV_DEVICE_DISABLE_CORE, @@ -104,8 +103,8 @@ nouveau_devobj_ctor(struct nouveau_object *parent, struct nouveau_device *device; struct nouveau_devobj *devobj; struct nv_device_class *args = data; - u32 boot0, strap; - u64 disable, mmio_base, mmio_size; + u64 disable, boot0, strap; + u64 mmio_base, mmio_size; void __iomem *map; int ret, i, c; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c index 473c5c03d3c9..8626d0d6cbbc 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv04.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -47,11 +46,10 @@ nv04_identify(struct nouveau_device *device) case 0x04: device->cname = "NV04"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; @@ -65,11 +63,10 @@ nv04_identify(struct nouveau_device *device) case 0x05: device->cname = "NV05"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c index d0774f5bebe1..9c40b0fb23f6 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv10.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -49,11 +48,10 @@ nv10_identify(struct nouveau_device *device) device->cname = "NV10"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; @@ -66,11 +64,10 @@ nv10_identify(struct nouveau_device *device) device->cname = "NV15"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; @@ -85,11 +82,10 @@ nv10_identify(struct nouveau_device *device) device->cname = "NV16"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; @@ -104,11 +100,10 @@ nv10_identify(struct nouveau_device *device) device->cname = "nForce"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv1a_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; @@ -123,11 +118,10 @@ nv10_identify(struct nouveau_device *device) device->cname = "NV11"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; @@ -142,11 +136,10 @@ nv10_identify(struct nouveau_device *device) device->cname = "NV17"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; @@ -161,11 +154,10 @@ nv10_identify(struct nouveau_device *device) device->cname = "nForce2"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv1a_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; @@ -180,11 +172,10 @@ nv10_identify(struct nouveau_device *device) device->cname = "NV18"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c index ab920e0dc45b..74f88f48e1c2 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv20.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -50,11 +49,10 @@ nv20_identify(struct nouveau_device *device) device->cname = "NV20"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; @@ -69,11 +67,10 @@ nv20_identify(struct nouveau_device *device) device->cname = "NV25"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv25_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; @@ -88,11 +85,10 @@ nv20_identify(struct nouveau_device *device) device->cname = "NV28"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv25_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; @@ -107,11 +103,10 @@ nv20_identify(struct nouveau_device *device) device->cname = "NV2A"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv25_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c index 5f2110261b04..0ac1b2c4f61d 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv30.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -50,11 +49,10 @@ nv30_identify(struct nouveau_device *device) device->cname = "NV30"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; @@ -69,11 +67,10 @@ nv30_identify(struct nouveau_device *device) device->cname = "NV35"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv35_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; @@ -88,11 +85,10 @@ nv30_identify(struct nouveau_device *device) device->cname = "NV31"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; @@ -108,11 +104,10 @@ nv30_identify(struct nouveau_device *device) device->cname = "NV36"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv36_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; @@ -128,11 +123,10 @@ nv30_identify(struct nouveau_device *device) device->cname = "NV34"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c index f3d55efe9ac9..41d59689a021 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv40.c @@ -24,8 +24,6 @@ #include #include -#include -#include #include #include #include @@ -52,12 +50,11 @@ nv40_identify(struct nouveau_device *device) device->cname = "NV40"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; @@ -73,12 +70,11 @@ nv40_identify(struct nouveau_device *device) device->cname = "NV41"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv41_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; @@ -94,12 +90,11 @@ nv40_identify(struct nouveau_device *device) device->cname = "NV42"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv41_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; @@ -115,12 +110,11 @@ nv40_identify(struct nouveau_device *device) device->cname = "NV43"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv41_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; @@ -136,12 +130,11 @@ nv40_identify(struct nouveau_device *device) device->cname = "NV45"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; @@ -157,12 +150,11 @@ nv40_identify(struct nouveau_device *device) device->cname = "G70"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv47_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; @@ -178,12 +170,11 @@ nv40_identify(struct nouveau_device *device) device->cname = "G71"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv49_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; @@ -199,12 +190,11 @@ nv40_identify(struct nouveau_device *device) device->cname = "G73"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv49_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; @@ -220,12 +210,11 @@ nv40_identify(struct nouveau_device *device) device->cname = "NV44"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv44_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; @@ -241,12 +230,11 @@ nv40_identify(struct nouveau_device *device) device->cname = "G72"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; @@ -262,12 +250,11 @@ nv40_identify(struct nouveau_device *device) device->cname = "NV44A"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv44_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; @@ -283,12 +270,11 @@ nv40_identify(struct nouveau_device *device) device->cname = "C61"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; @@ -304,12 +290,11 @@ nv40_identify(struct nouveau_device *device) device->cname = "C51"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv4e_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv4e_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; @@ -325,12 +310,11 @@ nv40_identify(struct nouveau_device *device) device->cname = "C73"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; @@ -346,12 +330,11 @@ nv40_identify(struct nouveau_device *device) device->cname = "C67"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; @@ -367,12 +350,11 @@ nv40_identify(struct nouveau_device *device) device->cname = "C68"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c index 5ed2fa51ddc2..6ccfd8585ba2 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nv50.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -58,13 +57,12 @@ nv50_identify(struct nouveau_device *device) device->cname = "G80"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; @@ -81,13 +79,12 @@ nv50_identify(struct nouveau_device *device) device->cname = "G84"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; @@ -107,13 +104,12 @@ nv50_identify(struct nouveau_device *device) device->cname = "G86"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; @@ -133,13 +129,12 @@ nv50_identify(struct nouveau_device *device) device->cname = "G92"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; @@ -159,13 +154,12 @@ nv50_identify(struct nouveau_device *device) device->cname = "G94"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; @@ -185,13 +179,12 @@ nv50_identify(struct nouveau_device *device) device->cname = "G96"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; @@ -211,13 +204,12 @@ nv50_identify(struct nouveau_device *device) device->cname = "G98"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; @@ -237,13 +229,12 @@ nv50_identify(struct nouveau_device *device) device->cname = "G200"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; @@ -263,13 +254,12 @@ nv50_identify(struct nouveau_device *device) device->cname = "MCP77/MCP78"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; @@ -289,13 +279,12 @@ nv50_identify(struct nouveau_device *device) device->cname = "MCP79/MCP7A"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; @@ -315,13 +304,12 @@ nv50_identify(struct nouveau_device *device) device->cname = "GT215"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; @@ -342,13 +330,12 @@ nv50_identify(struct nouveau_device *device) device->cname = "GT216"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; @@ -368,13 +355,12 @@ nv50_identify(struct nouveau_device *device) device->cname = "GT218"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; @@ -394,13 +380,12 @@ nv50_identify(struct nouveau_device *device) device->cname = "MCP89"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c index 4393eb4d6564..f0461685a422 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -58,13 +57,12 @@ nvc0_identify(struct nouveau_device *device) device->cname = "GF100"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; @@ -87,13 +85,12 @@ nvc0_identify(struct nouveau_device *device) device->cname = "GF104"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; @@ -116,13 +113,12 @@ nvc0_identify(struct nouveau_device *device) device->cname = "GF106"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; @@ -145,13 +141,12 @@ nvc0_identify(struct nouveau_device *device) device->cname = "GF114"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; @@ -174,13 +169,12 @@ nvc0_identify(struct nouveau_device *device) device->cname = "GF116"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; @@ -203,13 +197,12 @@ nvc0_identify(struct nouveau_device *device) device->cname = "GF108"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; @@ -232,13 +225,12 @@ nvc0_identify(struct nouveau_device *device) device->cname = "GF110"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; @@ -261,13 +253,12 @@ nvc0_identify(struct nouveau_device *device) device->cname = "GF119"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; @@ -291,4 +282,4 @@ nvc0_identify(struct nouveau_device *device) } return 0; - } +} diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c index 5c12391619fd..03a652876e73 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/device/nve0.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -57,14 +56,13 @@ nve0_identify(struct nouveau_device *device) case 0xe4: device->cname = "GK104"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; @@ -86,14 +84,13 @@ nve0_identify(struct nouveau_device *device) case 0xe7: device->cname = "GK107"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; @@ -115,14 +112,13 @@ nve0_identify(struct nouveau_device *device) case 0xe6: device->cname = "GK106"; device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; - device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass; - device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; + device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; + device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; - device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; + device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; - device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c index 4a8577838417..ae7249b09797 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c @@ -78,13 +78,12 @@ nv50_devinit_init(struct nouveau_object *object) if (ret) return ret; - /* if we ran the init tables, we have to execute the first script - * pointer of each dcb entry's display encoder table in order - * to properly initialise each encoder. + /* if we ran the init tables, execute first script pointer for each + * display table output entry that has a matching dcb entry. */ - while (priv->base.post && dcb_outp_parse(bios, i, &ver, &hdr, &outp)) { - if (nvbios_outp_match(bios, outp.hasht, outp.hashm, - &ver, &hdr, &cnt, &len, &info)) { + while (priv->base.post && ver) { + u16 data = nvbios_outp_parse(bios, i++, &ver, &hdr, &cnt, &len, &info); + if (data && dcb_outp_match(bios, info.type, info.mask, &ver, &len, &outp)) { struct nvbios_init init = { .subdev = nv_subdev(priv), .bios = bios, @@ -96,8 +95,7 @@ nv50_devinit_init(struct nouveau_object *object) nvbios_exec(&init); } - i++; - } + }; return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index a4338d92b02e..487cb8c6c204 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -22,10 +22,8 @@ * Authors: Ben Skeggs */ -#include -#include -#include #include +#include #include #include @@ -304,18 +302,17 @@ static const struct nouveau_enum vm_client[] = { }; static const struct nouveau_enum vm_engine[] = { - { 0x00000000, "PGRAPH", NULL, NVDEV_ENGINE_GR }, - { 0x00000001, "PVP", NULL, NVDEV_ENGINE_VP }, + { 0x00000000, "PGRAPH", NULL }, + { 0x00000001, "PVP", NULL }, { 0x00000004, "PEEPHOLE", NULL }, - { 0x00000005, "PFIFO", vm_pfifo_subclients, NVDEV_ENGINE_FIFO }, + { 0x00000005, "PFIFO", vm_pfifo_subclients }, { 0x00000006, "BAR", vm_bar_subclients }, - { 0x00000008, "PPPP", NULL, NVDEV_ENGINE_PPP }, - { 0x00000008, "PMPEG", NULL, NVDEV_ENGINE_MPEG }, - { 0x00000009, "PBSP", NULL, NVDEV_ENGINE_BSP }, - { 0x0000000a, "PCRYPT", NULL, NVDEV_ENGINE_CRYPT }, + { 0x00000008, "PPPP", NULL }, + { 0x00000009, "PBSP", NULL }, + { 0x0000000a, "PCRYPT", NULL }, { 0x0000000b, "PCOUNTER", NULL }, { 0x0000000c, "SEMAPHORE_BG", NULL }, - { 0x0000000d, "PCOPY", NULL, NVDEV_ENGINE_COPY0 }, + { 0x0000000d, "PCOPY", NULL }, { 0x0000000e, "PDAEMON", NULL }, {} }; @@ -337,10 +334,8 @@ static void nv50_fb_intr(struct nouveau_subdev *subdev) { struct nouveau_device *device = nv_device(subdev); - struct nouveau_engine *engine; struct nv50_fb_priv *priv = (void *)subdev; const struct nouveau_enum *en, *cl; - struct nouveau_object *engctx = NULL; u32 trap[6], idx, chan; u8 st0, st1, st2, st3; int i; @@ -371,55 +366,36 @@ nv50_fb_intr(struct nouveau_subdev *subdev) } chan = (trap[2] << 16) | trap[1]; - en = nouveau_enum_find(vm_engine, st0); - - if (en && en->data2) { - const struct nouveau_enum *orig_en = en; - while (en->name && en->value == st0 && en->data2) { - engine = nouveau_engine(subdev, en->data2); - if (engine) { - engctx = nouveau_engctx_get(engine, chan); - if (engctx) - break; - } - en++; - } - if (!engctx) - en = orig_en; - } - - nv_error(priv, "trapped %s at 0x%02x%04x%04x on channel 0x%08x [%s] ", + nv_error(priv, "trapped %s at 0x%02x%04x%04x on channel 0x%08x ", (trap[5] & 0x00000100) ? "read" : "write", - trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, chan, - nouveau_client_name(engctx)); - - nouveau_engctx_put(engctx); + trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, chan); + en = nouveau_enum_find(vm_engine, st0); if (en) - pr_cont("%s/", en->name); + printk("%s/", en->name); else - pr_cont("%02x/", st0); + printk("%02x/", st0); cl = nouveau_enum_find(vm_client, st2); if (cl) - pr_cont("%s/", cl->name); + printk("%s/", cl->name); else - pr_cont("%02x/", st2); + printk("%02x/", st2); if (cl && cl->data) cl = nouveau_enum_find(cl->data, st3); else if (en && en->data) cl = nouveau_enum_find(en->data, st3); else cl = NULL; if (cl) - pr_cont("%s", cl->name); + printk("%s", cl->name); else - pr_cont("%02x", st3); + printk("%02x", st3); - pr_cont(" reason: "); + printk(" reason: "); en = nouveau_enum_find(vm_fault, st1); if (en) - pr_cont("%s\n", en->name); + printk("%s\n", en->name); else - pr_cont("0x%08x\n", st1); + printk("0x%08x\n", st1); } static int diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c index d422acc9af15..9fb0f9b92d49 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/base.c @@ -102,19 +102,135 @@ nouveau_gpio_get(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line) return ret; } -void -_nouveau_gpio_dtor(struct nouveau_object *object) +static int +nouveau_gpio_irq(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, bool on) +{ + struct dcb_gpio_func func; + int ret; + + ret = nouveau_gpio_find(gpio, idx, tag, line, &func); + if (ret == 0) { + if (idx == 0 && gpio->irq_enable) + gpio->irq_enable(gpio, func.line, on); + else + ret = -ENODEV; + } + + return ret; +} + +struct gpio_isr { + struct nouveau_gpio *gpio; + struct list_head head; + struct work_struct work; + int idx; + struct dcb_gpio_func func; + void (*handler)(void *, int); + void *data; + bool inhibit; +}; + +static void +nouveau_gpio_isr_bh(struct work_struct *work) +{ + struct gpio_isr *isr = container_of(work, struct gpio_isr, work); + struct nouveau_gpio *gpio = isr->gpio; + unsigned long flags; + int state; + + state = nouveau_gpio_get(gpio, isr->idx, isr->func.func, + isr->func.line); + if (state >= 0) + isr->handler(isr->data, state); + + spin_lock_irqsave(&gpio->lock, flags); + isr->inhibit = false; + spin_unlock_irqrestore(&gpio->lock, flags); +} + +static void +nouveau_gpio_isr_run(struct nouveau_gpio *gpio, int idx, u32 line_mask) +{ + struct gpio_isr *isr; + + if (idx != 0) + return; + + spin_lock(&gpio->lock); + list_for_each_entry(isr, &gpio->isr, head) { + if (line_mask & (1 << isr->func.line)) { + if (isr->inhibit) + continue; + isr->inhibit = true; + schedule_work(&isr->work); + } + } + spin_unlock(&gpio->lock); +} + +static int +nouveau_gpio_isr_add(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, + void (*handler)(void *, int), void *data) +{ + struct gpio_isr *isr; + unsigned long flags; + int ret; + + isr = kzalloc(sizeof(*isr), GFP_KERNEL); + if (!isr) + return -ENOMEM; + + ret = nouveau_gpio_find(gpio, idx, tag, line, &isr->func); + if (ret) { + kfree(isr); + return ret; + } + + INIT_WORK(&isr->work, nouveau_gpio_isr_bh); + isr->gpio = gpio; + isr->handler = handler; + isr->data = data; + isr->idx = idx; + + spin_lock_irqsave(&gpio->lock, flags); + list_add(&isr->head, &gpio->isr); + spin_unlock_irqrestore(&gpio->lock, flags); + return 0; +} + +static void +nouveau_gpio_isr_del(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, + void (*handler)(void *, int), void *data) { - struct nouveau_gpio *gpio = (void *)object; - nouveau_event_destroy(&gpio->events); - nouveau_subdev_destroy(&gpio->base); + struct gpio_isr *isr, *tmp; + struct dcb_gpio_func func; + unsigned long flags; + LIST_HEAD(tofree); + int ret; + + ret = nouveau_gpio_find(gpio, idx, tag, line, &func); + if (ret == 0) { + spin_lock_irqsave(&gpio->lock, flags); + list_for_each_entry_safe(isr, tmp, &gpio->isr, head) { + if (memcmp(&isr->func, &func, sizeof(func)) || + isr->idx != idx || + isr->handler != handler || isr->data != data) + continue; + list_move_tail(&isr->head, &tofree); + } + spin_unlock_irqrestore(&gpio->lock, flags); + + list_for_each_entry_safe(isr, tmp, &tofree, head) { + flush_work(&isr->work); + kfree(isr); + } + } } int nouveau_gpio_create_(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, int lines, - int length, void **pobject) + struct nouveau_oclass *oclass, int length, void **pobject) { struct nouveau_gpio *gpio; int ret; @@ -125,13 +241,15 @@ nouveau_gpio_create_(struct nouveau_object *parent, if (ret) return ret; - ret = nouveau_event_create(lines, &gpio->events); - if (ret) - return ret; - gpio->find = nouveau_gpio_find; gpio->set = nouveau_gpio_set; gpio->get = nouveau_gpio_get; + gpio->irq = nouveau_gpio_irq; + gpio->isr_run = nouveau_gpio_isr_run; + gpio->isr_add = nouveau_gpio_isr_add; + gpio->isr_del = nouveau_gpio_isr_del; + INIT_LIST_HEAD(&gpio->isr); + spin_lock_init(&gpio->lock); return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c index 76d5d5465ddd..168d16a9a8e9 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c @@ -24,7 +24,7 @@ * */ -#include "priv.h" +#include struct nv10_gpio_priv { struct nouveau_gpio base; @@ -82,6 +82,15 @@ nv10_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out) return 0; } +static void +nv10_gpio_irq_enable(struct nouveau_gpio *gpio, int line, bool on) +{ + u32 mask = 0x00010001 << line; + + nv_wr32(gpio, 0x001104, mask); + nv_mask(gpio, 0x001144, mask, on ? mask : 0); +} + static void nv10_gpio_intr(struct nouveau_subdev *subdev) { @@ -89,30 +98,12 @@ nv10_gpio_intr(struct nouveau_subdev *subdev) u32 intr = nv_rd32(priv, 0x001104); u32 hi = (intr & 0x0000ffff) >> 0; u32 lo = (intr & 0xffff0000) >> 16; - int i; - for (i = 0; (hi | lo) && i < 32; i++) { - if ((hi | lo) & (1 << i)) - nouveau_event_trigger(priv->base.events, i); - } + priv->base.isr_run(&priv->base, 0, hi | lo); nv_wr32(priv, 0x001104, intr); } -static void -nv10_gpio_intr_enable(struct nouveau_event *event, int line) -{ - nv_wr32(event->priv, 0x001104, 0x00010001 << line); - nv_mask(event->priv, 0x001144, 0x00010001 << line, 0x00010001 << line); -} - -static void -nv10_gpio_intr_disable(struct nouveau_event *event, int line) -{ - nv_wr32(event->priv, 0x001104, 0x00010001 << line); - nv_mask(event->priv, 0x001144, 0x00010001 << line, 0x00000000); -} - static int nv10_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -121,16 +112,14 @@ nv10_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nv10_gpio_priv *priv; int ret; - ret = nouveau_gpio_create(parent, engine, oclass, 16, &priv); + ret = nouveau_gpio_create(parent, engine, oclass, &priv); *pobject = nv_object(priv); if (ret) return ret; priv->base.drive = nv10_gpio_drive; priv->base.sense = nv10_gpio_sense; - priv->base.events->priv = priv; - priv->base.events->enable = nv10_gpio_intr_enable; - priv->base.events->disable = nv10_gpio_intr_disable; + priv->base.irq_enable = nv10_gpio_irq_enable; nv_subdev(priv)->intr = nv10_gpio_intr; return 0; } @@ -152,6 +141,8 @@ nv10_gpio_init(struct nouveau_object *object) if (ret) return ret; + nv_wr32(priv, 0x001140, 0x00000000); + nv_wr32(priv, 0x001100, 0xffffffff); nv_wr32(priv, 0x001144, 0x00000000); nv_wr32(priv, 0x001104, 0xffffffff); return 0; @@ -161,6 +152,7 @@ static int nv10_gpio_fini(struct nouveau_object *object, bool suspend) { struct nv10_gpio_priv *priv = (void *)object; + nv_wr32(priv, 0x001140, 0x00000000); nv_wr32(priv, 0x001144, 0x00000000); return nouveau_gpio_fini(&priv->base, suspend); } diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c index bf489dcf46e2..bf13a1200f26 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c @@ -22,7 +22,7 @@ * Authors: Ben Skeggs */ -#include "priv.h" +#include struct nv50_gpio_priv { struct nouveau_gpio base; @@ -94,13 +94,22 @@ nv50_gpio_sense(struct nouveau_gpio *gpio, int line) return !!(nv_rd32(gpio, reg) & (4 << shift)); } +void +nv50_gpio_irq_enable(struct nouveau_gpio *gpio, int line, bool on) +{ + u32 reg = line < 16 ? 0xe050 : 0xe070; + u32 mask = 0x00010001 << (line & 0xf); + + nv_wr32(gpio, reg + 4, mask); + nv_mask(gpio, reg + 0, mask, on ? mask : 0); +} + void nv50_gpio_intr(struct nouveau_subdev *subdev) { struct nv50_gpio_priv *priv = (void *)subdev; u32 intr0, intr1 = 0; u32 hi, lo; - int i; intr0 = nv_rd32(priv, 0xe054) & nv_rd32(priv, 0xe050); if (nv_device(priv)->chipset >= 0x90) @@ -108,35 +117,13 @@ nv50_gpio_intr(struct nouveau_subdev *subdev) hi = (intr0 & 0x0000ffff) | (intr1 << 16); lo = (intr0 >> 16) | (intr1 & 0xffff0000); - - for (i = 0; (hi | lo) && i < 32; i++) { - if ((hi | lo) & (1 << i)) - nouveau_event_trigger(priv->base.events, i); - } + priv->base.isr_run(&priv->base, 0, hi | lo); nv_wr32(priv, 0xe054, intr0); if (nv_device(priv)->chipset >= 0x90) nv_wr32(priv, 0xe074, intr1); } -void -nv50_gpio_intr_enable(struct nouveau_event *event, int line) -{ - const u32 addr = line < 16 ? 0xe050 : 0xe070; - const u32 mask = 0x00010001 << (line & 0xf); - nv_wr32(event->priv, addr + 0x04, mask); - nv_mask(event->priv, addr + 0x00, mask, mask); -} - -void -nv50_gpio_intr_disable(struct nouveau_event *event, int line) -{ - const u32 addr = line < 16 ? 0xe050 : 0xe070; - const u32 mask = 0x00010001 << (line & 0xf); - nv_wr32(event->priv, addr + 0x04, mask); - nv_mask(event->priv, addr + 0x00, mask, 0x00000000); -} - static int nv50_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nouveau_oclass *oclass, void *data, u32 size, @@ -145,9 +132,7 @@ nv50_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nv50_gpio_priv *priv; int ret; - ret = nouveau_gpio_create(parent, engine, oclass, - nv_device(parent)->chipset >= 0x90 ? 32 : 16, - &priv); + ret = nouveau_gpio_create(parent, engine, oclass, &priv); *pobject = nv_object(priv); if (ret) return ret; @@ -155,9 +140,7 @@ nv50_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->base.reset = nv50_gpio_reset; priv->base.drive = nv50_gpio_drive; priv->base.sense = nv50_gpio_sense; - priv->base.events->priv = priv; - priv->base.events->enable = nv50_gpio_intr_enable; - priv->base.events->disable = nv50_gpio_intr_disable; + priv->base.irq_enable = nv50_gpio_irq_enable; nv_subdev(priv)->intr = nv50_gpio_intr; return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c index 010431e3acec..83e8b8f16e6a 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c @@ -22,13 +22,13 @@ * Authors: Ben Skeggs */ -#include "priv.h" +#include struct nvd0_gpio_priv { struct nouveau_gpio base; }; -void +static void nvd0_gpio_reset(struct nouveau_gpio *gpio, u8 match) { struct nouveau_bios *bios = nouveau_bios(gpio); @@ -57,7 +57,7 @@ nvd0_gpio_reset(struct nouveau_gpio *gpio, u8 match) } } -int +static int nvd0_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out) { u32 data = ((dir ^ 1) << 13) | (out << 12); @@ -66,7 +66,7 @@ nvd0_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out) return 0; } -int +static int nvd0_gpio_sense(struct nouveau_gpio *gpio, int line) { return !!(nv_rd32(gpio, 0x00d610 + (line * 4)) & 0x00004000); @@ -80,7 +80,7 @@ nvd0_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, struct nvd0_gpio_priv *priv; int ret; - ret = nouveau_gpio_create(parent, engine, oclass, 32, &priv); + ret = nouveau_gpio_create(parent, engine, oclass, &priv); *pobject = nv_object(priv); if (ret) return ret; @@ -88,9 +88,7 @@ nvd0_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, priv->base.reset = nvd0_gpio_reset; priv->base.drive = nvd0_gpio_drive; priv->base.sense = nvd0_gpio_sense; - priv->base.events->priv = priv; - priv->base.events->enable = nv50_gpio_intr_enable; - priv->base.events->disable = nv50_gpio_intr_disable; + priv->base.irq_enable = nv50_gpio_irq_enable; nv_subdev(priv)->intr = nv50_gpio_intr; return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/nve0.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/nve0.c deleted file mode 100644 index 16b8c5bf5efa..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/nve0.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include "priv.h" - -struct nve0_gpio_priv { - struct nouveau_gpio base; -}; - -void -nve0_gpio_intr(struct nouveau_subdev *subdev) -{ - struct nve0_gpio_priv *priv = (void *)subdev; - u32 intr0 = nv_rd32(priv, 0xdc00) & nv_rd32(priv, 0xdc08); - u32 intr1 = nv_rd32(priv, 0xdc80) & nv_rd32(priv, 0xdc88); - u32 hi = (intr0 & 0x0000ffff) | (intr1 << 16); - u32 lo = (intr0 >> 16) | (intr1 & 0xffff0000); - int i; - - for (i = 0; (hi | lo) && i < 32; i++) { - if ((hi | lo) & (1 << i)) - nouveau_event_trigger(priv->base.events, i); - } - - nv_wr32(priv, 0xdc00, intr0); - nv_wr32(priv, 0xdc88, intr1); -} - -void -nve0_gpio_intr_enable(struct nouveau_event *event, int line) -{ - const u32 addr = line < 16 ? 0xdc00 : 0xdc80; - const u32 mask = 0x00010001 << (line & 0xf); - nv_wr32(event->priv, addr + 0x08, mask); - nv_mask(event->priv, addr + 0x00, mask, mask); -} - -void -nve0_gpio_intr_disable(struct nouveau_event *event, int line) -{ - const u32 addr = line < 16 ? 0xdc00 : 0xdc80; - const u32 mask = 0x00010001 << (line & 0xf); - nv_wr32(event->priv, addr + 0x08, mask); - nv_mask(event->priv, addr + 0x00, mask, 0x00000000); -} - -int -nve0_gpio_fini(struct nouveau_object *object, bool suspend) -{ - struct nve0_gpio_priv *priv = (void *)object; - nv_wr32(priv, 0xdc08, 0x00000000); - nv_wr32(priv, 0xdc88, 0x00000000); - return nouveau_gpio_fini(&priv->base, suspend); -} - -int -nve0_gpio_init(struct nouveau_object *object) -{ - struct nve0_gpio_priv *priv = (void *)object; - int ret; - - ret = nouveau_gpio_init(&priv->base); - if (ret) - return ret; - - nv_wr32(priv, 0xdc00, 0xffffffff); - nv_wr32(priv, 0xdc80, 0xffffffff); - return 0; -} - -void -nve0_gpio_dtor(struct nouveau_object *object) -{ - struct nve0_gpio_priv *priv = (void *)object; - nouveau_gpio_destroy(&priv->base); -} - -static int -nve0_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nve0_gpio_priv *priv; - int ret; - - ret = nouveau_gpio_create(parent, engine, oclass, 32, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.reset = nvd0_gpio_reset; - priv->base.drive = nvd0_gpio_drive; - priv->base.sense = nvd0_gpio_sense; - priv->base.events->priv = priv; - priv->base.events->enable = nve0_gpio_intr_enable; - priv->base.events->disable = nve0_gpio_intr_disable; - nv_subdev(priv)->intr = nve0_gpio_intr; - return 0; -} - -struct nouveau_oclass -nve0_gpio_oclass = { - .handle = NV_SUBDEV(GPIO, 0xe0), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nve0_gpio_ctor, - .dtor = nv50_gpio_dtor, - .init = nve0_gpio_init, - .fini = nve0_gpio_fini, - }, -}; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/priv.h b/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/priv.h deleted file mode 100644 index 2ee1c895c782..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/gpio/priv.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __NVKM_GPIO_H__ -#define __NVKM_GPIO_H__ - -#include - -void nv50_gpio_dtor(struct nouveau_object *); -int nv50_gpio_init(struct nouveau_object *); -int nv50_gpio_fini(struct nouveau_object *, bool); -void nv50_gpio_intr(struct nouveau_subdev *); -void nv50_gpio_intr_enable(struct nouveau_event *, int line); -void nv50_gpio_intr_disable(struct nouveau_event *, int line); - -void nvd0_gpio_reset(struct nouveau_gpio *, u8); -int nvd0_gpio_drive(struct nouveau_gpio *, int, int, int); -int nvd0_gpio_sense(struct nouveau_gpio *, int); - -#endif diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c deleted file mode 100644 index dec94e9d776a..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright 2013 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include - -struct anx9805_i2c_port { - struct nouveau_i2c_port base; - u32 addr; - u32 ctrl; -}; - -static int -anx9805_train(struct nouveau_i2c_port *port, int link_nr, int link_bw, bool enh) -{ - struct anx9805_i2c_port *chan = (void *)port; - struct nouveau_i2c_port *mast = (void *)nv_object(chan)->parent; - u8 tmp, i; - - nv_wri2cr(mast, chan->addr, 0xa0, link_bw); - nv_wri2cr(mast, chan->addr, 0xa1, link_nr | (enh ? 0x80 : 0x00)); - nv_wri2cr(mast, chan->addr, 0xa2, 0x01); - nv_wri2cr(mast, chan->addr, 0xa8, 0x01); - - i = 0; - while ((tmp = nv_rdi2cr(mast, chan->addr, 0xa8)) & 0x01) { - mdelay(5); - if (i++ == 100) { - nv_error(port, "link training timed out\n"); - return -ETIMEDOUT; - } - } - - if (tmp & 0x70) { - nv_error(port, "link training failed: 0x%02x\n", tmp); - return -EIO; - } - - return 1; -} - -static int -anx9805_aux(struct nouveau_i2c_port *port, u8 type, u32 addr, u8 *data, u8 size) -{ - struct anx9805_i2c_port *chan = (void *)port; - struct nouveau_i2c_port *mast = (void *)nv_object(chan)->parent; - int i, ret = -ETIMEDOUT; - u8 tmp; - - tmp = nv_rdi2cr(mast, chan->ctrl, 0x07) & ~0x04; - nv_wri2cr(mast, chan->ctrl, 0x07, tmp | 0x04); - nv_wri2cr(mast, chan->ctrl, 0x07, tmp); - nv_wri2cr(mast, chan->ctrl, 0xf7, 0x01); - - nv_wri2cr(mast, chan->addr, 0xe4, 0x80); - for (i = 0; !(type & 1) && i < size; i++) - nv_wri2cr(mast, chan->addr, 0xf0 + i, data[i]); - nv_wri2cr(mast, chan->addr, 0xe5, ((size - 1) << 4) | type); - nv_wri2cr(mast, chan->addr, 0xe6, (addr & 0x000ff) >> 0); - nv_wri2cr(mast, chan->addr, 0xe7, (addr & 0x0ff00) >> 8); - nv_wri2cr(mast, chan->addr, 0xe8, (addr & 0xf0000) >> 16); - nv_wri2cr(mast, chan->addr, 0xe9, 0x01); - - i = 0; - while ((tmp = nv_rdi2cr(mast, chan->addr, 0xe9)) & 0x01) { - mdelay(5); - if (i++ == 32) - goto done; - } - - if ((tmp = nv_rdi2cr(mast, chan->ctrl, 0xf7)) & 0x01) { - ret = -EIO; - goto done; - } - - for (i = 0; (type & 1) && i < size; i++) - data[i] = nv_rdi2cr(mast, chan->addr, 0xf0 + i); - ret = 0; -done: - nv_wri2cr(mast, chan->ctrl, 0xf7, 0x01); - return ret; -} - -static const struct nouveau_i2c_func -anx9805_aux_func = { - .aux = anx9805_aux, - .lnk_ctl = anx9805_train, -}; - -static int -anx9805_aux_chan_ctor(struct nouveau_object *parent, - struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 index, - struct nouveau_object **pobject) -{ - struct nouveau_i2c_port *mast = (void *)parent; - struct anx9805_i2c_port *chan; - int ret; - - ret = nouveau_i2c_port_create(parent, engine, oclass, index, - &nouveau_i2c_aux_algo, &chan); - *pobject = nv_object(chan); - if (ret) - return ret; - - switch ((oclass->handle & 0xff00) >> 8) { - case 0x0d: - chan->addr = 0x38; - chan->ctrl = 0x39; - break; - case 0x0e: - chan->addr = 0x3c; - chan->ctrl = 0x3b; - break; - default: - BUG_ON(1); - } - - if (mast->adapter.algo == &i2c_bit_algo) { - struct i2c_algo_bit_data *algo = mast->adapter.algo_data; - algo->udelay = max(algo->udelay, 40); - } - - chan->base.func = &anx9805_aux_func; - return 0; -} - -static struct nouveau_ofuncs -anx9805_aux_ofuncs = { - .ctor = anx9805_aux_chan_ctor, - .dtor = _nouveau_i2c_port_dtor, - .init = _nouveau_i2c_port_init, - .fini = _nouveau_i2c_port_fini, -}; - -static int -anx9805_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) -{ - struct anx9805_i2c_port *port = adap->algo_data; - struct nouveau_i2c_port *mast = (void *)nv_object(port)->parent; - struct i2c_msg *msg = msgs; - int ret = -ETIMEDOUT; - int i, j, cnt = num; - u8 seg = 0x00, off = 0x00, tmp; - - tmp = nv_rdi2cr(mast, port->ctrl, 0x07) & ~0x10; - nv_wri2cr(mast, port->ctrl, 0x07, tmp | 0x10); - nv_wri2cr(mast, port->ctrl, 0x07, tmp); - nv_wri2cr(mast, port->addr, 0x43, 0x05); - mdelay(5); - - while (cnt--) { - if ( (msg->flags & I2C_M_RD) && msg->addr == 0x50) { - nv_wri2cr(mast, port->addr, 0x40, msg->addr << 1); - nv_wri2cr(mast, port->addr, 0x41, seg); - nv_wri2cr(mast, port->addr, 0x42, off); - nv_wri2cr(mast, port->addr, 0x44, msg->len); - nv_wri2cr(mast, port->addr, 0x45, 0x00); - nv_wri2cr(mast, port->addr, 0x43, 0x01); - for (i = 0; i < msg->len; i++) { - j = 0; - while (nv_rdi2cr(mast, port->addr, 0x46) & 0x10) { - mdelay(5); - if (j++ == 32) - goto done; - } - msg->buf[i] = nv_rdi2cr(mast, port->addr, 0x47); - } - } else - if (!(msg->flags & I2C_M_RD)) { - if (msg->addr == 0x50 && msg->len == 0x01) { - off = msg->buf[0]; - } else - if (msg->addr == 0x30 && msg->len == 0x01) { - seg = msg->buf[0]; - } else - goto done; - } else { - goto done; - } - msg++; - } - - ret = num; -done: - nv_wri2cr(mast, port->addr, 0x43, 0x00); - return ret; -} - -static u32 -anx9805_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm -anx9805_i2c_algo = { - .master_xfer = anx9805_xfer, - .functionality = anx9805_func -}; - -static const struct nouveau_i2c_func -anx9805_i2c_func = { -}; - -static int -anx9805_ddc_port_ctor(struct nouveau_object *parent, - struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 index, - struct nouveau_object **pobject) -{ - struct nouveau_i2c_port *mast = (void *)parent; - struct anx9805_i2c_port *port; - int ret; - - ret = nouveau_i2c_port_create(parent, engine, oclass, index, - &anx9805_i2c_algo, &port); - *pobject = nv_object(port); - if (ret) - return ret; - - switch ((oclass->handle & 0xff00) >> 8) { - case 0x0d: - port->addr = 0x3d; - port->ctrl = 0x39; - break; - case 0x0e: - port->addr = 0x3f; - port->ctrl = 0x3b; - break; - default: - BUG_ON(1); - } - - if (mast->adapter.algo == &i2c_bit_algo) { - struct i2c_algo_bit_data *algo = mast->adapter.algo_data; - algo->udelay = max(algo->udelay, 40); - } - - port->base.func = &anx9805_i2c_func; - return 0; -} - -static struct nouveau_ofuncs -anx9805_ddc_ofuncs = { - .ctor = anx9805_ddc_port_ctor, - .dtor = _nouveau_i2c_port_dtor, - .init = _nouveau_i2c_port_init, - .fini = _nouveau_i2c_port_fini, -}; - -struct nouveau_oclass -nouveau_anx9805_sclass[] = { - { .handle = NV_I2C_TYPE_EXTDDC(0x0d), .ofuncs = &anx9805_ddc_ofuncs }, - { .handle = NV_I2C_TYPE_EXTAUX(0x0d), .ofuncs = &anx9805_aux_ofuncs }, - { .handle = NV_I2C_TYPE_EXTDDC(0x0e), .ofuncs = &anx9805_ddc_ofuncs }, - { .handle = NV_I2C_TYPE_EXTAUX(0x0e), .ofuncs = &anx9805_aux_ofuncs }, - {} -}; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c index 5de074ad170b..dc27e794a851 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c @@ -24,40 +24,151 @@ #include -int -nv_rdaux(struct nouveau_i2c_port *port, u32 addr, u8 *data, u8 size) +/****************************************************************************** + * aux channel util functions + *****************************************************************************/ +#define AUX_DBG(fmt, args...) nv_debug(aux, "AUXCH(%d): " fmt, ch, ##args) +#define AUX_ERR(fmt, args...) nv_error(aux, "AUXCH(%d): " fmt, ch, ##args) + +static void +auxch_fini(struct nouveau_i2c *aux, int ch) +{ + nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); +} + +static int +auxch_init(struct nouveau_i2c *aux, int ch) +{ + const u32 unksel = 1; /* nfi which to use, or if it matters.. */ + const u32 ureq = unksel ? 0x00100000 : 0x00200000; + const u32 urep = unksel ? 0x01000000 : 0x02000000; + u32 ctrl, timeout; + + /* wait up to 1ms for any previous transaction to be done... */ + timeout = 1000; + do { + ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); + udelay(1); + if (!timeout--) { + AUX_ERR("begin idle timeout 0x%08x\n", ctrl); + return -EBUSY; + } + } while (ctrl & 0x03010000); + + /* set some magic, and wait up to 1ms for it to appear */ + nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq); + timeout = 1000; + do { + ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); + udelay(1); + if (!timeout--) { + AUX_ERR("magic wait 0x%08x\n", ctrl); + auxch_fini(aux, ch); + return -EBUSY; + } + } while ((ctrl & 0x03000000) != urep); + + return 0; +} + +static int +auxch_tx(struct nouveau_i2c *aux, int ch, u8 type, u32 addr, u8 *data, u8 size) { - if (port->func->aux) { - if (port->func->acquire) - port->func->acquire(port); - return port->func->aux(port, 9, addr, data, size); + u32 ctrl, stat, timeout, retries; + u32 xbuf[4] = {}; + int ret, i; + + AUX_DBG("%d: 0x%08x %d\n", type, addr, size); + + ret = auxch_init(aux, ch); + if (ret) + goto out; + + stat = nv_rd32(aux, 0x00e4e8 + (ch * 0x50)); + if (!(stat & 0x10000000)) { + AUX_DBG("sink not detected\n"); + ret = -ENXIO; + goto out; } - return -ENODEV; + + if (!(type & 1)) { + memcpy(xbuf, data, size); + for (i = 0; i < 16; i += 4) { + AUX_DBG("wr 0x%08x\n", xbuf[i / 4]); + nv_wr32(aux, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]); + } + } + + ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); + ctrl &= ~0x0001f0ff; + ctrl |= type << 12; + ctrl |= size - 1; + nv_wr32(aux, 0x00e4e0 + (ch * 0x50), addr); + + /* retry transaction a number of times on failure... */ + ret = -EREMOTEIO; + for (retries = 0; retries < 32; retries++) { + /* reset, and delay a while if this is a retry */ + nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); + nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); + if (retries) + udelay(400); + + /* transaction request, wait up to 1ms for it to complete */ + nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); + + timeout = 1000; + do { + ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); + udelay(1); + if (!timeout--) { + AUX_ERR("tx req timeout 0x%08x\n", ctrl); + goto out; + } + } while (ctrl & 0x00010000); + + /* read status, and check if transaction completed ok */ + stat = nv_mask(aux, 0x00e4e8 + (ch * 0x50), 0, 0); + if (!(stat & 0x000f0f00)) { + ret = 0; + break; + } + + AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); + } + + if (type & 1) { + for (i = 0; i < 16; i += 4) { + xbuf[i / 4] = nv_rd32(aux, 0x00e4d0 + (ch * 0x50) + i); + AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); + } + memcpy(data, xbuf, size); + } + +out: + auxch_fini(aux, ch); + return ret; } int -nv_wraux(struct nouveau_i2c_port *port, u32 addr, u8 *data, u8 size) +nv_rdaux(struct nouveau_i2c_port *auxch, u32 addr, u8 *data, u8 size) { - if (port->func->aux) { - if (port->func->acquire) - port->func->acquire(port); - return port->func->aux(port, 8, addr, data, size); - } - return -ENODEV; + return auxch_tx(auxch->i2c, auxch->drive, 9, addr, data, size); +} + +int +nv_wraux(struct nouveau_i2c_port *auxch, u32 addr, u8 *data, u8 size) +{ + return auxch_tx(auxch->i2c, auxch->drive, 8, addr, data, size); } static int aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { - struct nouveau_i2c_port *port = adap->algo_data; + struct nouveau_i2c_port *auxch = (struct nouveau_i2c_port *)adap; struct i2c_msg *msg = msgs; int ret, mcnt = num; - if (!port->func->aux) - return -ENODEV; - if ( port->func->acquire) - port->func->acquire(port); - while (mcnt--) { u8 remaining = msg->len; u8 *ptr = msg->buf; @@ -74,7 +185,8 @@ aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) if (mcnt || remaining > 16) cmd |= 4; /* MOT */ - ret = port->func->aux(port, cmd, msg->addr, ptr, cnt); + ret = auxch_tx(auxch->i2c, auxch->drive, cmd, + msg->addr, ptr, cnt); if (ret < 0) return ret; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index a114a0ed7e98..dbfc2abf0cfe 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -1,5 +1,5 @@ /* - * Copyright 2013 Red Hat Inc. + * Copyright 2012 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -22,136 +22,64 @@ * Authors: Ben Skeggs */ -#include +#include "core/option.h" -#include -#include -#include -#include -#include +#include "subdev/i2c.h" +#include "subdev/vga.h" -/****************************************************************************** - * interface to linux i2c bit-banging algorithm - *****************************************************************************/ - -#ifdef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT -#define CSTMSEL true -#else -#define CSTMSEL false -#endif - -static int -nouveau_i2c_pre_xfer(struct i2c_adapter *adap) +int +nv_rdi2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg) { - struct i2c_algo_bit_data *bit = adap->algo_data; - struct nouveau_i2c_port *port = bit->data; - if (port->func->acquire) - port->func->acquire(port); - return 0; -} + u8 val; + struct i2c_msg msgs[] = { + { .addr = addr, .flags = 0, .len = 1, .buf = ® }, + { .addr = addr, .flags = I2C_M_RD, .len = 1, .buf = &val }, + }; -static void -nouveau_i2c_setscl(void *data, int state) -{ - struct nouveau_i2c_port *port = data; - port->func->drive_scl(port, state); -} + int ret = i2c_transfer(&port->adapter, msgs, 2); + if (ret != 2) + return -EIO; -static void -nouveau_i2c_setsda(void *data, int state) -{ - struct nouveau_i2c_port *port = data; - port->func->drive_sda(port, state); + return val; } -static int -nouveau_i2c_getscl(void *data) -{ - struct nouveau_i2c_port *port = data; - return port->func->sense_scl(port); -} - -static int -nouveau_i2c_getsda(void *data) +int +nv_wri2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg, u8 val) { - struct nouveau_i2c_port *port = data; - return port->func->sense_sda(port); -} + struct i2c_msg msgs[] = { + { .addr = addr, .flags = 0, .len = 1, .buf = ® }, + { .addr = addr, .flags = 0, .len = 1, .buf = &val }, + }; -/****************************************************************************** - * base i2c "port" class implementation - *****************************************************************************/ + int ret = i2c_transfer(&port->adapter, msgs, 2); + if (ret != 2) + return -EIO; -void -_nouveau_i2c_port_dtor(struct nouveau_object *object) -{ - struct nouveau_i2c_port *port = (void *)object; - i2c_del_adapter(&port->adapter); - nouveau_object_destroy(&port->base); + return 0; } -int -nouveau_i2c_port_create_(struct nouveau_object *parent, - struct nouveau_object *engine, - struct nouveau_oclass *oclass, u8 index, - const struct i2c_algorithm *algo, - int size, void **pobject) +bool +nv_probe_i2c(struct nouveau_i2c_port *port, u8 addr) { - struct nouveau_device *device = nv_device(parent); - struct nouveau_i2c *i2c = (void *)engine; - struct nouveau_i2c_port *port; - int ret; - - ret = nouveau_object_create_(parent, engine, oclass, 0, size, pobject); - port = *pobject; - if (ret) - return ret; - - snprintf(port->adapter.name, sizeof(port->adapter.name), - "nouveau-%s-%d", device->name, index); - port->adapter.owner = THIS_MODULE; - port->adapter.dev.parent = &device->pdev->dev; - port->index = index; - i2c_set_adapdata(&port->adapter, i2c); - - if ( algo == &nouveau_i2c_bit_algo && - !nouveau_boolopt(device->cfgopt, "NvI2C", CSTMSEL)) { - struct i2c_algo_bit_data *bit; - - bit = kzalloc(sizeof(*bit), GFP_KERNEL); - if (!bit) - return -ENOMEM; - - bit->udelay = 10; - bit->timeout = usecs_to_jiffies(2200); - bit->data = port; - bit->pre_xfer = nouveau_i2c_pre_xfer; - bit->setsda = nouveau_i2c_setsda; - bit->setscl = nouveau_i2c_setscl; - bit->getsda = nouveau_i2c_getsda; - bit->getscl = nouveau_i2c_getscl; - - port->adapter.algo_data = bit; - ret = i2c_bit_add_bus(&port->adapter); - } else { - port->adapter.algo_data = port; - port->adapter.algo = algo; - ret = i2c_add_adapter(&port->adapter); - } - - /* drop port's i2c subdev refcount, i2c handles this itself */ - if (ret == 0) { - list_add_tail(&port->head, &i2c->ports); - atomic_dec(&engine->refcount); - } + u8 buf[] = { 0 }; + struct i2c_msg msgs[] = { + { + .addr = addr, + .flags = 0, + .len = 1, + .buf = buf, + }, + { + .addr = addr, + .flags = I2C_M_RD, + .len = 1, + .buf = buf, + } + }; - return ret; + return i2c_transfer(&port->adapter, msgs, 2) == 2; } -/****************************************************************************** - * base i2c subdev class implementation - *****************************************************************************/ - static struct nouveau_i2c_port * nouveau_i2c_find(struct nouveau_i2c *i2c, u8 index) { @@ -175,23 +103,29 @@ nouveau_i2c_find(struct nouveau_i2c *i2c, u8 index) list_for_each_entry(port, &i2c->ports, head) { if (port->index == index) - return port; + break; } - return NULL; -} + if (&port->head == &i2c->ports) + return NULL; -static struct nouveau_i2c_port * -nouveau_i2c_find_type(struct nouveau_i2c *i2c, u16 type) -{ - struct nouveau_i2c_port *port; + if (nv_device(i2c)->card_type >= NV_50 && (port->dcb & 0x00000100)) { + u32 reg = 0x00e500, val; + if (port->type == 6) { + reg += port->drive * 0x50; + val = 0x2002; + } else { + reg += ((port->dcb & 0x1e00) >> 9) * 0x50; + val = 0xe001; + } - list_for_each_entry(port, &i2c->ports, head) { - if (nv_hclass(port) == type) - return port; + /* nfi, but neither auxch or i2c work if it's 1 */ + nv_mask(i2c, reg + 0x0c, 0x00000001, 0x00000000); + /* nfi, but switches auxch vs normal i2c */ + nv_mask(i2c, reg + 0x00, 0x0000f003, val); } - return NULL; + return port; } static int @@ -221,86 +155,109 @@ nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, return -ENODEV; } -int -_nouveau_i2c_fini(struct nouveau_object *object, bool suspend) +void +nouveau_i2c_drive_scl(void *data, int state) { - struct nouveau_i2c *i2c = (void *)object; - struct nouveau_i2c_port *port; - int ret; + struct nouveau_i2c_port *port = data; - list_for_each_entry(port, &i2c->ports, head) { - ret = nv_ofuncs(port)->fini(nv_object(port), suspend); - if (ret && suspend) - goto fail; + if (port->type == DCB_I2C_NV04_BIT) { + u8 val = nv_rdvgac(port->i2c, 0, port->drive); + if (state) val |= 0x20; + else val &= 0xdf; + nv_wrvgac(port->i2c, 0, port->drive, val | 0x01); + } else + if (port->type == DCB_I2C_NV4E_BIT) { + nv_mask(port->i2c, port->drive, 0x2f, state ? 0x21 : 0x01); + } else + if (port->type == DCB_I2C_NVIO_BIT) { + if (state) port->state |= 0x01; + else port->state &= 0xfe; + nv_wr32(port->i2c, port->drive, 4 | port->state); } +} - return nouveau_subdev_fini(&i2c->base, suspend); -fail: - list_for_each_entry_continue_reverse(port, &i2c->ports, head) { - nv_ofuncs(port)->init(nv_object(port)); - } +void +nouveau_i2c_drive_sda(void *data, int state) +{ + struct nouveau_i2c_port *port = data; - return ret; + if (port->type == DCB_I2C_NV04_BIT) { + u8 val = nv_rdvgac(port->i2c, 0, port->drive); + if (state) val |= 0x10; + else val &= 0xef; + nv_wrvgac(port->i2c, 0, port->drive, val | 0x01); + } else + if (port->type == DCB_I2C_NV4E_BIT) { + nv_mask(port->i2c, port->drive, 0x1f, state ? 0x11 : 0x01); + } else + if (port->type == DCB_I2C_NVIO_BIT) { + if (state) port->state |= 0x02; + else port->state &= 0xfd; + nv_wr32(port->i2c, port->drive, 4 | port->state); + } } int -_nouveau_i2c_init(struct nouveau_object *object) +nouveau_i2c_sense_scl(void *data) { - struct nouveau_i2c *i2c = (void *)object; - struct nouveau_i2c_port *port; - int ret; - - ret = nouveau_subdev_init(&i2c->base); - if (ret == 0) { - list_for_each_entry(port, &i2c->ports, head) { - ret = nv_ofuncs(port)->init(nv_object(port)); - if (ret) - goto fail; - } - } - - return ret; -fail: - list_for_each_entry_continue_reverse(port, &i2c->ports, head) { - nv_ofuncs(port)->fini(nv_object(port), false); + struct nouveau_i2c_port *port = data; + struct nouveau_device *device = nv_device(port->i2c); + + if (port->type == DCB_I2C_NV04_BIT) { + return !!(nv_rdvgac(port->i2c, 0, port->sense) & 0x04); + } else + if (port->type == DCB_I2C_NV4E_BIT) { + return !!(nv_rd32(port->i2c, port->sense) & 0x00040000); + } else + if (port->type == DCB_I2C_NVIO_BIT) { + if (device->card_type < NV_D0) + return !!(nv_rd32(port->i2c, port->sense) & 0x01); + else + return !!(nv_rd32(port->i2c, port->sense) & 0x10); } - return ret; + return 0; } -void -_nouveau_i2c_dtor(struct nouveau_object *object) +int +nouveau_i2c_sense_sda(void *data) { - struct nouveau_i2c *i2c = (void *)object; - struct nouveau_i2c_port *port, *temp; - - list_for_each_entry_safe(port, temp, &i2c->ports, head) { - nouveau_object_ref(NULL, (struct nouveau_object **)&port); + struct nouveau_i2c_port *port = data; + struct nouveau_device *device = nv_device(port->i2c); + + if (port->type == DCB_I2C_NV04_BIT) { + return !!(nv_rdvgac(port->i2c, 0, port->sense) & 0x08); + } else + if (port->type == DCB_I2C_NV4E_BIT) { + return !!(nv_rd32(port->i2c, port->sense) & 0x00080000); + } else + if (port->type == DCB_I2C_NVIO_BIT) { + if (device->card_type < NV_D0) + return !!(nv_rd32(port->i2c, port->sense) & 0x02); + else + return !!(nv_rd32(port->i2c, port->sense) & 0x20); } - nouveau_subdev_destroy(&i2c->base); + return 0; } -static struct nouveau_oclass * -nouveau_i2c_extdev_sclass[] = { - nouveau_anx9805_sclass, +static const u32 nv50_i2c_port[] = { + 0x00e138, 0x00e150, 0x00e168, 0x00e180, + 0x00e254, 0x00e274, 0x00e764, 0x00e780, + 0x00e79c, 0x00e7b8 }; -int -nouveau_i2c_create_(struct nouveau_object *parent, - struct nouveau_object *engine, - struct nouveau_oclass *oclass, - struct nouveau_oclass *sclass, - int length, void **pobject) +static int +nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { + struct nouveau_device *device = nv_device(parent); struct nouveau_bios *bios = nouveau_bios(parent); + struct nouveau_i2c_port *port; struct nouveau_i2c *i2c; - struct nouveau_object *object; struct dcb_i2c_entry info; - int ret, i, j, index = -1; - struct dcb_output outp; - u8 ver, hdr; - u32 data; + int ret, i = -1; ret = nouveau_subdev_create(parent, engine, oclass, 0, "I2C", "i2c", &i2c); @@ -309,60 +266,142 @@ nouveau_i2c_create_(struct nouveau_object *parent, return ret; i2c->find = nouveau_i2c_find; - i2c->find_type = nouveau_i2c_find_type; i2c->identify = nouveau_i2c_identify; INIT_LIST_HEAD(&i2c->ports); - while (!dcb_i2c_parse(bios, ++index, &info)) { + while (!dcb_i2c_parse(bios, ++i, &info)) { if (info.type == DCB_I2C_UNUSED) continue; - oclass = sclass; - do { - ret = -EINVAL; - if (oclass->handle == info.type) { - ret = nouveau_object_ctor(*pobject, *pobject, - oclass, &info, - index, &object); - } - } while (ret && (++oclass)->handle); - } - - /* in addition to the busses specified in the i2c table, there - * may be ddc/aux channels hiding behind external tmds/dp/etc - * transmitters. - */ - index = ((index + 0x0f) / 0x10) * 0x10; - i = -1; - while ((data = dcb_outp_parse(bios, ++i, &ver, &hdr, &outp))) { - if (!outp.location || !outp.extdev) - continue; + port = kzalloc(sizeof(*port), GFP_KERNEL); + if (!port) { + nv_error(i2c, "failed port memory alloc at %d\n", i); + break; + } - switch (outp.type) { - case DCB_OUTPUT_TMDS: - info.type = NV_I2C_TYPE_EXTDDC(outp.extdev); + port->type = info.type; + switch (port->type) { + case DCB_I2C_NV04_BIT: + port->drive = info.drive; + port->sense = info.sense; + break; + case DCB_I2C_NV4E_BIT: + port->drive = 0x600800 + info.drive; + port->sense = port->drive; + break; + case DCB_I2C_NVIO_BIT: + port->drive = info.drive & 0x0f; + if (device->card_type < NV_D0) { + if (port->drive >= ARRAY_SIZE(nv50_i2c_port)) + break; + port->drive = nv50_i2c_port[port->drive]; + port->sense = port->drive; + } else { + port->drive = 0x00d014 + (port->drive * 0x20); + port->sense = port->drive; + } break; - case DCB_OUTPUT_DP: - info.type = NV_I2C_TYPE_EXTAUX(outp.extdev); + case DCB_I2C_NVIO_AUX: + port->drive = info.drive & 0x0f; + port->sense = port->drive; + port->adapter.algo = &nouveau_i2c_aux_algo; break; default: + break; + } + + if (!port->adapter.algo && !port->drive) { + nv_error(i2c, "I2C%d: type %d index %x/%x unknown\n", + i, port->type, port->drive, port->sense); + kfree(port); continue; } - ret = -ENODEV; - j = -1; - while (ret && ++j < ARRAY_SIZE(nouveau_i2c_extdev_sclass)) { - parent = nv_object(i2c->find(i2c, outp.i2c_index)); - oclass = nouveau_i2c_extdev_sclass[j]; - do { - if (oclass->handle != info.type) - continue; - ret = nouveau_object_ctor(parent, *pobject, - oclass, NULL, - index++, &object); - } while (ret && (++oclass)->handle); + snprintf(port->adapter.name, sizeof(port->adapter.name), + "nouveau-%s-%d", device->name, i); + port->adapter.owner = THIS_MODULE; + port->adapter.dev.parent = &device->pdev->dev; + port->i2c = i2c; + port->index = i; + port->dcb = info.data; + i2c_set_adapdata(&port->adapter, i2c); + + if (port->adapter.algo != &nouveau_i2c_aux_algo) { + nouveau_i2c_drive_scl(port, 0); + nouveau_i2c_drive_sda(port, 1); + nouveau_i2c_drive_scl(port, 1); + +#ifdef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT + if (nouveau_boolopt(device->cfgopt, "NvI2C", true)) { +#else + if (nouveau_boolopt(device->cfgopt, "NvI2C", false)) { +#endif + port->adapter.algo = &nouveau_i2c_bit_algo; + ret = i2c_add_adapter(&port->adapter); + } else { + port->adapter.algo_data = &port->bit; + port->bit.udelay = 10; + port->bit.timeout = usecs_to_jiffies(2200); + port->bit.data = port; + port->bit.setsda = nouveau_i2c_drive_sda; + port->bit.setscl = nouveau_i2c_drive_scl; + port->bit.getsda = nouveau_i2c_sense_sda; + port->bit.getscl = nouveau_i2c_sense_scl; + ret = i2c_bit_add_bus(&port->adapter); + } + } else { + port->adapter.algo = &nouveau_i2c_aux_algo; + ret = i2c_add_adapter(&port->adapter); + } + + if (ret) { + nv_error(i2c, "I2C%d: failed register: %d\n", i, ret); + kfree(port); + continue; } + + list_add_tail(&port->head, &i2c->ports); } return 0; } + +static void +nouveau_i2c_dtor(struct nouveau_object *object) +{ + struct nouveau_i2c *i2c = (void *)object; + struct nouveau_i2c_port *port, *temp; + + list_for_each_entry_safe(port, temp, &i2c->ports, head) { + i2c_del_adapter(&port->adapter); + list_del(&port->head); + kfree(port); + } + + nouveau_subdev_destroy(&i2c->base); +} + +static int +nouveau_i2c_init(struct nouveau_object *object) +{ + struct nouveau_i2c *i2c = (void *)object; + return nouveau_subdev_init(&i2c->base); +} + +static int +nouveau_i2c_fini(struct nouveau_object *object, bool suspend) +{ + struct nouveau_i2c *i2c = (void *)object; + return nouveau_subdev_fini(&i2c->base, suspend); +} + +struct nouveau_oclass +nouveau_i2c_oclass = { + .handle = NV_SUBDEV(I2C, 0x00), + .ofuncs = &(struct nouveau_ofuncs) { + .ctor = nouveau_i2c_ctor, + .dtor = nouveau_i2c_dtor, + .init = nouveau_i2c_init, + .fini = nouveau_i2c_fini, + }, +}; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c index a6e72d3b06b5..1c4c9a5c8e2e 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c @@ -32,25 +32,25 @@ static inline void i2c_drive_scl(struct nouveau_i2c_port *port, int state) { - port->func->drive_scl(port, state); + nouveau_i2c_drive_scl(port, state); } static inline void i2c_drive_sda(struct nouveau_i2c_port *port, int state) { - port->func->drive_sda(port, state); + nouveau_i2c_drive_sda(port, state); } static inline int i2c_sense_scl(struct nouveau_i2c_port *port) { - return port->func->sense_scl(port); + return nouveau_i2c_sense_scl(port); } static inline int i2c_sense_sda(struct nouveau_i2c_port *port) { - return port->func->sense_sda(port); + return nouveau_i2c_sense_sda(port); } static void @@ -77,8 +77,9 @@ i2c_start(struct nouveau_i2c_port *port) { int ret = 0; - if (!i2c_sense_scl(port) || - !i2c_sense_sda(port)) { + port->state = i2c_sense_scl(port); + port->state |= i2c_sense_sda(port) << 1; + if (port->state != 3) { i2c_drive_scl(port, 0); i2c_drive_sda(port, 1); if (!i2c_raise_scl(port)) @@ -183,13 +184,10 @@ i2c_addr(struct nouveau_i2c_port *port, struct i2c_msg *msg) static int i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) { - struct nouveau_i2c_port *port = adap->algo_data; + struct nouveau_i2c_port *port = (struct nouveau_i2c_port *)adap; struct i2c_msg *msg = msgs; int ret = 0, mcnt = num; - if (port->func->acquire) - port->func->acquire(port); - while (!ret && mcnt--) { u8 remaining = msg->len; u8 *ptr = msg->buf; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c deleted file mode 100644 index 2ad18840fe63..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include -#include - -struct nv04_i2c_priv { - struct nouveau_i2c base; -}; - -struct nv04_i2c_port { - struct nouveau_i2c_port base; - u8 drive; - u8 sense; -}; - -static void -nv04_i2c_drive_scl(struct nouveau_i2c_port *base, int state) -{ - struct nv04_i2c_priv *priv = (void *)nv_object(base)->engine; - struct nv04_i2c_port *port = (void *)base; - u8 val = nv_rdvgac(priv, 0, port->drive); - if (state) val |= 0x20; - else val &= 0xdf; - nv_wrvgac(priv, 0, port->drive, val | 0x01); -} - -static void -nv04_i2c_drive_sda(struct nouveau_i2c_port *base, int state) -{ - struct nv04_i2c_priv *priv = (void *)nv_object(base)->engine; - struct nv04_i2c_port *port = (void *)base; - u8 val = nv_rdvgac(priv, 0, port->drive); - if (state) val |= 0x10; - else val &= 0xef; - nv_wrvgac(priv, 0, port->drive, val | 0x01); -} - -static int -nv04_i2c_sense_scl(struct nouveau_i2c_port *base) -{ - struct nv04_i2c_priv *priv = (void *)nv_object(base)->engine; - struct nv04_i2c_port *port = (void *)base; - return !!(nv_rdvgac(priv, 0, port->sense) & 0x04); -} - -static int -nv04_i2c_sense_sda(struct nouveau_i2c_port *base) -{ - struct nv04_i2c_priv *priv = (void *)nv_object(base)->engine; - struct nv04_i2c_port *port = (void *)base; - return !!(nv_rdvgac(priv, 0, port->sense) & 0x08); -} - -static const struct nouveau_i2c_func -nv04_i2c_func = { - .drive_scl = nv04_i2c_drive_scl, - .drive_sda = nv04_i2c_drive_sda, - .sense_scl = nv04_i2c_sense_scl, - .sense_sda = nv04_i2c_sense_sda, -}; - -static int -nv04_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 index, - struct nouveau_object **pobject) -{ - struct dcb_i2c_entry *info = data; - struct nv04_i2c_port *port; - int ret; - - ret = nouveau_i2c_port_create(parent, engine, oclass, index, - &nouveau_i2c_bit_algo, &port); - *pobject = nv_object(port); - if (ret) - return ret; - - port->base.func = &nv04_i2c_func; - port->drive = info->drive; - port->sense = info->sense; - return 0; -} - -static struct nouveau_oclass -nv04_i2c_sclass[] = { - { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NV04_BIT), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv04_i2c_port_ctor, - .dtor = _nouveau_i2c_port_dtor, - .init = _nouveau_i2c_port_init, - .fini = _nouveau_i2c_port_fini, - }, - }, - {} -}; - -static int -nv04_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nv04_i2c_priv *priv; - int ret; - - ret = nouveau_i2c_create(parent, engine, oclass, nv04_i2c_sclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - return 0; -} - -struct nouveau_oclass -nv04_i2c_oclass = { - .handle = NV_SUBDEV(I2C, 0x04), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv04_i2c_ctor, - .dtor = _nouveau_i2c_dtor, - .init = _nouveau_i2c_init, - .fini = _nouveau_i2c_fini, - }, -}; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c deleted file mode 100644 index f501ae25dbb3..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include -#include - -struct nv4e_i2c_priv { - struct nouveau_i2c base; -}; - -struct nv4e_i2c_port { - struct nouveau_i2c_port base; - u32 addr; -}; - -static void -nv4e_i2c_drive_scl(struct nouveau_i2c_port *base, int state) -{ - struct nv4e_i2c_priv *priv = (void *)nv_object(base)->engine; - struct nv4e_i2c_port *port = (void *)base; - nv_mask(priv, port->addr, 0x2f, state ? 0x21 : 0x01); -} - -static void -nv4e_i2c_drive_sda(struct nouveau_i2c_port *base, int state) -{ - struct nv4e_i2c_priv *priv = (void *)nv_object(base)->engine; - struct nv4e_i2c_port *port = (void *)base; - nv_mask(priv, port->addr, 0x1f, state ? 0x11 : 0x01); -} - -static int -nv4e_i2c_sense_scl(struct nouveau_i2c_port *base) -{ - struct nv4e_i2c_priv *priv = (void *)nv_object(base)->engine; - struct nv4e_i2c_port *port = (void *)base; - return !!(nv_rd32(priv, port->addr) & 0x00040000); -} - -static int -nv4e_i2c_sense_sda(struct nouveau_i2c_port *base) -{ - struct nv4e_i2c_priv *priv = (void *)nv_object(base)->engine; - struct nv4e_i2c_port *port = (void *)base; - return !!(nv_rd32(priv, port->addr) & 0x00080000); -} - -static const struct nouveau_i2c_func -nv4e_i2c_func = { - .drive_scl = nv4e_i2c_drive_scl, - .drive_sda = nv4e_i2c_drive_sda, - .sense_scl = nv4e_i2c_sense_scl, - .sense_sda = nv4e_i2c_sense_sda, -}; - -static int -nv4e_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 index, - struct nouveau_object **pobject) -{ - struct dcb_i2c_entry *info = data; - struct nv4e_i2c_port *port; - int ret; - - ret = nouveau_i2c_port_create(parent, engine, oclass, index, - &nouveau_i2c_bit_algo, &port); - *pobject = nv_object(port); - if (ret) - return ret; - - port->base.func = &nv4e_i2c_func; - port->addr = 0x600800 + info->drive; - return 0; -} - -static struct nouveau_oclass -nv4e_i2c_sclass[] = { - { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NV4E_BIT), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv4e_i2c_port_ctor, - .dtor = _nouveau_i2c_port_dtor, - .init = _nouveau_i2c_port_init, - .fini = _nouveau_i2c_port_fini, - }, - }, - {} -}; - -static int -nv4e_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nv4e_i2c_priv *priv; - int ret; - - ret = nouveau_i2c_create(parent, engine, oclass, nv4e_i2c_sclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - return 0; -} - -struct nouveau_oclass -nv4e_i2c_oclass = { - .handle = NV_SUBDEV(I2C, 0x4e), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv4e_i2c_ctor, - .dtor = _nouveau_i2c_dtor, - .init = _nouveau_i2c_init, - .fini = _nouveau_i2c_fini, - }, -}; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c deleted file mode 100644 index 378dfa324e5f..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include "nv50.h" - -void -nv50_i2c_drive_scl(struct nouveau_i2c_port *base, int state) -{ - struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine; - struct nv50_i2c_port *port = (void *)base; - if (state) port->state |= 0x01; - else port->state &= 0xfe; - nv_wr32(priv, port->addr, port->state); -} - -void -nv50_i2c_drive_sda(struct nouveau_i2c_port *base, int state) -{ - struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine; - struct nv50_i2c_port *port = (void *)base; - if (state) port->state |= 0x02; - else port->state &= 0xfd; - nv_wr32(priv, port->addr, port->state); -} - -int -nv50_i2c_sense_scl(struct nouveau_i2c_port *base) -{ - struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine; - struct nv50_i2c_port *port = (void *)base; - return !!(nv_rd32(priv, port->addr) & 0x00000001); -} - -int -nv50_i2c_sense_sda(struct nouveau_i2c_port *base) -{ - struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine; - struct nv50_i2c_port *port = (void *)base; - return !!(nv_rd32(priv, port->addr) & 0x00000002); -} - -static const struct nouveau_i2c_func -nv50_i2c_func = { - .drive_scl = nv50_i2c_drive_scl, - .drive_sda = nv50_i2c_drive_sda, - .sense_scl = nv50_i2c_sense_scl, - .sense_sda = nv50_i2c_sense_sda, -}; - -const u32 nv50_i2c_addr[] = { - 0x00e138, 0x00e150, 0x00e168, 0x00e180, - 0x00e254, 0x00e274, 0x00e764, 0x00e780, - 0x00e79c, 0x00e7b8 -}; -const int nv50_i2c_addr_nr = ARRAY_SIZE(nv50_i2c_addr); - -static int -nv50_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 index, - struct nouveau_object **pobject) -{ - struct dcb_i2c_entry *info = data; - struct nv50_i2c_port *port; - int ret; - - ret = nouveau_i2c_port_create(parent, engine, oclass, index, - &nouveau_i2c_bit_algo, &port); - *pobject = nv_object(port); - if (ret) - return ret; - - if (info->drive >= nv50_i2c_addr_nr) - return -EINVAL; - - port->base.func = &nv50_i2c_func; - port->state = 0x00000007; - port->addr = nv50_i2c_addr[info->drive]; - return 0; -} - -int -nv50_i2c_port_init(struct nouveau_object *object) -{ - struct nv50_i2c_priv *priv = (void *)object->engine; - struct nv50_i2c_port *port = (void *)object; - nv_wr32(priv, port->addr, port->state); - return nouveau_i2c_port_init(&port->base); -} - -static struct nouveau_oclass -nv50_i2c_sclass[] = { - { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv50_i2c_port_ctor, - .dtor = _nouveau_i2c_port_dtor, - .init = nv50_i2c_port_init, - .fini = _nouveau_i2c_port_fini, - }, - }, - {} -}; - -static int -nv50_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nv50_i2c_priv *priv; - int ret; - - ret = nouveau_i2c_create(parent, engine, oclass, nv50_i2c_sclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - return 0; -} - -struct nouveau_oclass -nv50_i2c_oclass = { - .handle = NV_SUBDEV(I2C, 0x50), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv50_i2c_ctor, - .dtor = _nouveau_i2c_dtor, - .init = _nouveau_i2c_init, - .fini = _nouveau_i2c_fini, - }, -}; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h b/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h deleted file mode 100644 index 4e5ba48ebf5a..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef __NV50_I2C_H__ -#define __NV50_I2C_H__ - -#include - -struct nv50_i2c_priv { - struct nouveau_i2c base; -}; - -struct nv50_i2c_port { - struct nouveau_i2c_port base; - u32 addr; - u32 ctrl; - u32 data; - u32 state; -}; - -extern const u32 nv50_i2c_addr[]; -extern const int nv50_i2c_addr_nr; -int nv50_i2c_port_init(struct nouveau_object *); -int nv50_i2c_sense_scl(struct nouveau_i2c_port *); -int nv50_i2c_sense_sda(struct nouveau_i2c_port *); -void nv50_i2c_drive_scl(struct nouveau_i2c_port *, int state); -void nv50_i2c_drive_sda(struct nouveau_i2c_port *, int state); - -int nv94_aux_port_ctor(struct nouveau_object *, struct nouveau_object *, - struct nouveau_oclass *, void *, u32, - struct nouveau_object **); -void nv94_i2c_acquire(struct nouveau_i2c_port *); -void nv94_i2c_release(struct nouveau_i2c_port *); - -#endif diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c deleted file mode 100644 index 61b771670bfe..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include "nv50.h" - -#define AUX_DBG(fmt, args...) nv_debug(aux, "AUXCH(%d): " fmt, ch, ##args) -#define AUX_ERR(fmt, args...) nv_error(aux, "AUXCH(%d): " fmt, ch, ##args) - -static void -auxch_fini(struct nouveau_i2c *aux, int ch) -{ - nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); -} - -static int -auxch_init(struct nouveau_i2c *aux, int ch) -{ - const u32 unksel = 1; /* nfi which to use, or if it matters.. */ - const u32 ureq = unksel ? 0x00100000 : 0x00200000; - const u32 urep = unksel ? 0x01000000 : 0x02000000; - u32 ctrl, timeout; - - /* wait up to 1ms for any previous transaction to be done... */ - timeout = 1000; - do { - ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); - udelay(1); - if (!timeout--) { - AUX_ERR("begin idle timeout 0x%08x\n", ctrl); - return -EBUSY; - } - } while (ctrl & 0x03010000); - - /* set some magic, and wait up to 1ms for it to appear */ - nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq); - timeout = 1000; - do { - ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); - udelay(1); - if (!timeout--) { - AUX_ERR("magic wait 0x%08x\n", ctrl); - auxch_fini(aux, ch); - return -EBUSY; - } - } while ((ctrl & 0x03000000) != urep); - - return 0; -} - -int -nv94_aux(struct nouveau_i2c_port *base, u8 type, u32 addr, u8 *data, u8 size) -{ - struct nouveau_i2c *aux = nouveau_i2c(base); - struct nv50_i2c_port *port = (void *)base; - u32 ctrl, stat, timeout, retries; - u32 xbuf[4] = {}; - int ch = port->addr; - int ret, i; - - AUX_DBG("%d: 0x%08x %d\n", type, addr, size); - - ret = auxch_init(aux, ch); - if (ret) - goto out; - - stat = nv_rd32(aux, 0x00e4e8 + (ch * 0x50)); - if (!(stat & 0x10000000)) { - AUX_DBG("sink not detected\n"); - ret = -ENXIO; - goto out; - } - - if (!(type & 1)) { - memcpy(xbuf, data, size); - for (i = 0; i < 16; i += 4) { - AUX_DBG("wr 0x%08x\n", xbuf[i / 4]); - nv_wr32(aux, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]); - } - } - - ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); - ctrl &= ~0x0001f0ff; - ctrl |= type << 12; - ctrl |= size - 1; - nv_wr32(aux, 0x00e4e0 + (ch * 0x50), addr); - - /* retry transaction a number of times on failure... */ - ret = -EREMOTEIO; - for (retries = 0; retries < 32; retries++) { - /* reset, and delay a while if this is a retry */ - nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); - nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); - if (retries) - udelay(400); - - /* transaction request, wait up to 1ms for it to complete */ - nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); - - timeout = 1000; - do { - ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); - udelay(1); - if (!timeout--) { - AUX_ERR("tx req timeout 0x%08x\n", ctrl); - goto out; - } - } while (ctrl & 0x00010000); - - /* read status, and check if transaction completed ok */ - stat = nv_mask(aux, 0x00e4e8 + (ch * 0x50), 0, 0); - if (!(stat & 0x000f0f00)) { - ret = 0; - break; - } - - AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); - } - - if (type & 1) { - for (i = 0; i < 16; i += 4) { - xbuf[i / 4] = nv_rd32(aux, 0x00e4d0 + (ch * 0x50) + i); - AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); - } - memcpy(data, xbuf, size); - } - -out: - auxch_fini(aux, ch); - return ret; -} - -void -nv94_i2c_acquire(struct nouveau_i2c_port *base) -{ - struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine; - struct nv50_i2c_port *port = (void *)base; - if (port->ctrl) { - nv_mask(priv, port->ctrl + 0x0c, 0x00000001, 0x00000000); - nv_mask(priv, port->ctrl + 0x00, 0x0000f003, port->data); - } -} - -void -nv94_i2c_release(struct nouveau_i2c_port *base) -{ -} - -static const struct nouveau_i2c_func -nv94_i2c_func = { - .acquire = nv94_i2c_acquire, - .release = nv94_i2c_release, - .drive_scl = nv50_i2c_drive_scl, - .drive_sda = nv50_i2c_drive_sda, - .sense_scl = nv50_i2c_sense_scl, - .sense_sda = nv50_i2c_sense_sda, -}; - -static int -nv94_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 index, - struct nouveau_object **pobject) -{ - struct dcb_i2c_entry *info = data; - struct nv50_i2c_port *port; - int ret; - - ret = nouveau_i2c_port_create(parent, engine, oclass, index, - &nouveau_i2c_bit_algo, &port); - *pobject = nv_object(port); - if (ret) - return ret; - - if (info->drive >= nv50_i2c_addr_nr) - return -EINVAL; - - port->base.func = &nv94_i2c_func; - port->state = 7; - port->addr = nv50_i2c_addr[info->drive]; - if (info->share != DCB_I2C_UNUSED) { - port->ctrl = 0x00e500 + (info->share * 0x50); - port->data = 0x0000e001; - } - return 0; -} - -static const struct nouveau_i2c_func -nv94_aux_func = { - .acquire = nv94_i2c_acquire, - .release = nv94_i2c_release, - .aux = nv94_aux, -}; - -int -nv94_aux_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 index, - struct nouveau_object **pobject) -{ - struct dcb_i2c_entry *info = data; - struct nv50_i2c_port *port; - int ret; - - ret = nouveau_i2c_port_create(parent, engine, oclass, index, - &nouveau_i2c_aux_algo, &port); - *pobject = nv_object(port); - if (ret) - return ret; - - port->base.func = &nv94_aux_func; - port->addr = info->drive; - if (info->share != DCB_I2C_UNUSED) { - port->ctrl = 0x00e500 + (info->drive * 0x50); - port->data = 0x00002002; - } - - return 0; -} - -static struct nouveau_oclass -nv94_i2c_sclass[] = { - { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv94_i2c_port_ctor, - .dtor = _nouveau_i2c_port_dtor, - .init = nv50_i2c_port_init, - .fini = _nouveau_i2c_port_fini, - }, - }, - { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv94_aux_port_ctor, - .dtor = _nouveau_i2c_port_dtor, - .init = _nouveau_i2c_port_init, - .fini = _nouveau_i2c_port_fini, - }, - }, - {} -}; - -static int -nv94_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nv50_i2c_priv *priv; - int ret; - - ret = nouveau_i2c_create(parent, engine, oclass, nv94_i2c_sclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - return 0; -} - -struct nouveau_oclass -nv94_i2c_oclass = { - .handle = NV_SUBDEV(I2C, 0x94), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv94_i2c_ctor, - .dtor = _nouveau_i2c_dtor, - .init = _nouveau_i2c_init, - .fini = _nouveau_i2c_fini, - }, -}; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c deleted file mode 100644 index f761b8a610f1..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include "nv50.h" - -static int -nvd0_i2c_sense_scl(struct nouveau_i2c_port *base) -{ - struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine; - struct nv50_i2c_port *port = (void *)base; - return !!(nv_rd32(priv, port->addr) & 0x00000010); -} - -static int -nvd0_i2c_sense_sda(struct nouveau_i2c_port *base) -{ - struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine; - struct nv50_i2c_port *port = (void *)base; - return !!(nv_rd32(priv, port->addr) & 0x00000020); -} - -static const struct nouveau_i2c_func -nvd0_i2c_func = { - .acquire = nv94_i2c_acquire, - .release = nv94_i2c_release, - .drive_scl = nv50_i2c_drive_scl, - .drive_sda = nv50_i2c_drive_sda, - .sense_scl = nvd0_i2c_sense_scl, - .sense_sda = nvd0_i2c_sense_sda, -}; - -static int -nvd0_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 index, - struct nouveau_object **pobject) -{ - struct dcb_i2c_entry *info = data; - struct nv50_i2c_port *port; - int ret; - - ret = nouveau_i2c_port_create(parent, engine, oclass, index, - &nouveau_i2c_bit_algo, &port); - *pobject = nv_object(port); - if (ret) - return ret; - - port->base.func = &nvd0_i2c_func; - port->state = 0x00000007; - port->addr = 0x00d014 + (info->drive * 0x20); - if (info->share != DCB_I2C_UNUSED) { - port->ctrl = 0x00e500 + (info->share * 0x50); - port->data = 0x0000e001; - } - return 0; -} - -static struct nouveau_oclass -nvd0_i2c_sclass[] = { - { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nvd0_i2c_port_ctor, - .dtor = _nouveau_i2c_port_dtor, - .init = nv50_i2c_port_init, - .fini = _nouveau_i2c_port_fini, - }, - }, - { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nv94_aux_port_ctor, - .dtor = _nouveau_i2c_port_dtor, - .init = _nouveau_i2c_port_init, - .fini = _nouveau_i2c_port_fini, - }, - }, - {} -}; - -static int -nvd0_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nv50_i2c_priv *priv; - int ret; - - ret = nouveau_i2c_create(parent, engine, oclass, nvd0_i2c_sclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - return 0; -} - -struct nouveau_oclass -nvd0_i2c_oclass = { - .handle = NV_SUBDEV(I2C, 0xd0), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nvd0_i2c_ctor, - .dtor = _nouveau_i2c_dtor, - .init = _nouveau_i2c_init, - .fini = _nouveau_i2c_fini, - }, -}; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c index 89da8fa7ea0f..23ebe477a6f0 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c @@ -37,7 +37,7 @@ nv04_mc_intr[] = { { 0x00100000, NVDEV_SUBDEV_TIMER }, { 0x01000000, NVDEV_ENGINE_DISP }, /* NV04- PCRTC0 */ { 0x02000000, NVDEV_ENGINE_DISP }, /* NV11- PCRTC1 */ - { 0x10000000, NVDEV_SUBDEV_BUS }, + { 0x10000000, NVDEV_SUBDEV_GPIO }, /* PBUS */ { 0x80000000, NVDEV_ENGINE_SW }, {} }; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c index 5965add6daee..8d759f830323 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c @@ -38,7 +38,6 @@ nv50_mc_intr[] = { { 0x00100000, NVDEV_SUBDEV_TIMER }, { 0x00200000, NVDEV_SUBDEV_GPIO }, { 0x04000000, NVDEV_ENGINE_DISP }, - { 0x10000000, NVDEV_SUBDEV_BUS }, { 0x80000000, NVDEV_ENGINE_SW }, { 0x0000d101, NVDEV_SUBDEV_FB }, {}, diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c index 3a80b29dce0f..ceb5c83f9459 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c @@ -35,12 +35,10 @@ nv98_mc_intr[] = { { 0x00001000, NVDEV_ENGINE_GR }, { 0x00004000, NVDEV_ENGINE_CRYPT }, /* NV84:NVA3 */ { 0x00008000, NVDEV_ENGINE_BSP }, - { 0x00080000, NVDEV_SUBDEV_THERM }, /* NVA3:NVC0 */ { 0x00100000, NVDEV_SUBDEV_TIMER }, { 0x00200000, NVDEV_SUBDEV_GPIO }, { 0x00400000, NVDEV_ENGINE_COPY0 }, /* NVA3- */ { 0x04000000, NVDEV_ENGINE_DISP }, - { 0x10000000, NVDEV_SUBDEV_BUS }, { 0x80000000, NVDEV_ENGINE_SW }, { 0x0040d101, NVDEV_SUBDEV_FB }, {}, diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c index 42bbf72023a8..92796682722d 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c @@ -36,13 +36,11 @@ nvc0_mc_intr[] = { { 0x00000100, NVDEV_ENGINE_FIFO }, { 0x00001000, NVDEV_ENGINE_GR }, { 0x00008000, NVDEV_ENGINE_BSP }, - { 0x00040000, NVDEV_SUBDEV_THERM }, { 0x00020000, NVDEV_ENGINE_VP }, { 0x00100000, NVDEV_SUBDEV_TIMER }, { 0x00200000, NVDEV_SUBDEV_GPIO }, { 0x02000000, NVDEV_SUBDEV_LTCG }, { 0x04000000, NVDEV_ENGINE_DISP }, - { 0x10000000, NVDEV_SUBDEV_BUS }, { 0x40000000, NVDEV_SUBDEV_IBUS }, { 0x80000000, NVDEV_ENGINE_SW }, {}, diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.c index 4bde7f7f7b81..839ca1edc132 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.c @@ -156,15 +156,15 @@ mxms_foreach(struct nouveau_mxm *mxm, u8 types, nv_debug(mxm, "%4s: ", mxms_desc_name[type]); for (j = headerlen - 1; j >= 0; j--) - pr_cont("%02x", dump[j]); - pr_cont("\n"); + printk("%02x", dump[j]); + printk("\n"); dump += headerlen; for (i = 0; i < entries; i++, dump += recordlen) { nv_debug(mxm, " "); for (j = recordlen - 1; j >= 0; j--) - pr_cont("%02x", dump[j]); - pr_cont("\n"); + printk("%02x", dump[j]); + printk("\n"); } } diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/base.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/base.c index f794dc89a3b2..1674c74a76c8 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/base.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/base.c @@ -29,134 +29,6 @@ #include "priv.h" -static int -nouveau_therm_update_trip(struct nouveau_therm *therm) -{ - struct nouveau_therm_priv *priv = (void *)therm; - struct nouveau_therm_trip_point *trip = priv->fan->bios.trip, - *cur_trip = NULL, - *last_trip = priv->last_trip; - u8 temp = therm->temp_get(therm); - u16 duty, i; - - /* look for the trip point corresponding to the current temperature */ - cur_trip = NULL; - for (i = 0; i < priv->fan->bios.nr_fan_trip; i++) { - if (temp >= trip[i].temp) - cur_trip = &trip[i]; - } - - /* account for the hysteresis cycle */ - if (last_trip && temp <= (last_trip->temp) && - temp > (last_trip->temp - last_trip->hysteresis)) - cur_trip = last_trip; - - if (cur_trip) { - duty = cur_trip->fan_duty; - priv->last_trip = cur_trip; - } else { - duty = 0; - priv->last_trip = NULL; - } - - return duty; -} - -static int -nouveau_therm_update_linear(struct nouveau_therm *therm) -{ - struct nouveau_therm_priv *priv = (void *)therm; - u8 linear_min_temp = priv->fan->bios.linear_min_temp; - u8 linear_max_temp = priv->fan->bios.linear_max_temp; - u8 temp = therm->temp_get(therm); - u16 duty; - - /* handle the non-linear part first */ - if (temp < linear_min_temp) - return priv->fan->bios.min_duty; - else if (temp > linear_max_temp) - return priv->fan->bios.max_duty; - - /* we are in the linear zone */ - duty = (temp - linear_min_temp); - duty *= (priv->fan->bios.max_duty - priv->fan->bios.min_duty); - duty /= (linear_max_temp - linear_min_temp); - duty += priv->fan->bios.min_duty; - - return duty; -} - -static void -nouveau_therm_update(struct nouveau_therm *therm, int mode) -{ - struct nouveau_timer *ptimer = nouveau_timer(therm); - struct nouveau_therm_priv *priv = (void *)therm; - unsigned long flags; - int duty; - - spin_lock_irqsave(&priv->lock, flags); - if (mode < 0) - mode = priv->mode; - priv->mode = mode; - - switch (mode) { - case NOUVEAU_THERM_CTRL_MANUAL: - duty = nouveau_therm_fan_get(therm); - if (duty < 0) - duty = 100; - break; - case NOUVEAU_THERM_CTRL_AUTO: - if (priv->fan->bios.nr_fan_trip) - duty = nouveau_therm_update_trip(therm); - else - duty = nouveau_therm_update_linear(therm); - break; - case NOUVEAU_THERM_CTRL_NONE: - default: - goto done; - } - - nv_debug(therm, "FAN target request: %d%%\n", duty); - nouveau_therm_fan_set(therm, (mode != NOUVEAU_THERM_CTRL_AUTO), duty); - -done: - if (list_empty(&priv->alarm.head) && (mode == NOUVEAU_THERM_CTRL_AUTO)) - ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm); - spin_unlock_irqrestore(&priv->lock, flags); -} - -static void -nouveau_therm_alarm(struct nouveau_alarm *alarm) -{ - struct nouveau_therm_priv *priv = - container_of(alarm, struct nouveau_therm_priv, alarm); - nouveau_therm_update(&priv->base, -1); -} - -int -nouveau_therm_mode(struct nouveau_therm *therm, int mode) -{ - struct nouveau_therm_priv *priv = (void *)therm; - struct nouveau_device *device = nv_device(therm); - static const char *name[] = { - "disabled", - "manual", - "automatic" - }; - - /* The default PDAEMON ucode interferes with fan management */ - if ((mode >= ARRAY_SIZE(name)) || - (mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0)) - return -EINVAL; - - if (priv->mode == mode) - return 0; - - nv_info(therm, "Thermal management: %s\n", name[mode]); - nouveau_therm_update(therm, mode); - return 0; -} - int nouveau_therm_attr_get(struct nouveau_therm *therm, enum nouveau_therm_attr_type type) @@ -165,11 +37,11 @@ nouveau_therm_attr_get(struct nouveau_therm *therm, switch (type) { case NOUVEAU_THERM_ATTR_FAN_MIN_DUTY: - return priv->fan->bios.min_duty; + return priv->bios_fan.min_duty; case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY: - return priv->fan->bios.max_duty; + return priv->bios_fan.max_duty; case NOUVEAU_THERM_ATTR_FAN_MODE: - return priv->mode; + return priv->fan.mode; case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: return priv->bios_sensor.thrs_fan_boost.temp; case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST: @@ -201,50 +73,42 @@ nouveau_therm_attr_set(struct nouveau_therm *therm, case NOUVEAU_THERM_ATTR_FAN_MIN_DUTY: if (value < 0) value = 0; - if (value > priv->fan->bios.max_duty) - value = priv->fan->bios.max_duty; - priv->fan->bios.min_duty = value; + if (value > priv->bios_fan.max_duty) + value = priv->bios_fan.max_duty; + priv->bios_fan.min_duty = value; return 0; case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY: if (value < 0) value = 0; - if (value < priv->fan->bios.min_duty) - value = priv->fan->bios.min_duty; - priv->fan->bios.max_duty = value; + if (value < priv->bios_fan.min_duty) + value = priv->bios_fan.min_duty; + priv->bios_fan.max_duty = value; return 0; case NOUVEAU_THERM_ATTR_FAN_MODE: - return nouveau_therm_mode(therm, value); + return nouveau_therm_fan_set_mode(therm, value); case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: priv->bios_sensor.thrs_fan_boost.temp = value; - priv->sensor.program_alarms(therm); return 0; case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST: priv->bios_sensor.thrs_fan_boost.hysteresis = value; - priv->sensor.program_alarms(therm); return 0; case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK: priv->bios_sensor.thrs_down_clock.temp = value; - priv->sensor.program_alarms(therm); return 0; case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST: priv->bios_sensor.thrs_down_clock.hysteresis = value; - priv->sensor.program_alarms(therm); return 0; case NOUVEAU_THERM_ATTR_THRS_CRITICAL: priv->bios_sensor.thrs_critical.temp = value; - priv->sensor.program_alarms(therm); return 0; case NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST: priv->bios_sensor.thrs_critical.hysteresis = value; - priv->sensor.program_alarms(therm); return 0; case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN: priv->bios_sensor.thrs_shutdown.temp = value; - priv->sensor.program_alarms(therm); return 0; case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST: priv->bios_sensor.thrs_shutdown.hysteresis = value; - priv->sensor.program_alarms(therm); return 0; } @@ -252,7 +116,7 @@ nouveau_therm_attr_set(struct nouveau_therm *therm, } int -_nouveau_therm_init(struct nouveau_object *object) +nouveau_therm_init(struct nouveau_object *object) { struct nouveau_therm *therm = (void *)object; struct nouveau_therm_priv *priv = (void *)therm; @@ -262,69 +126,19 @@ _nouveau_therm_init(struct nouveau_object *object) if (ret) return ret; - if (priv->suspend >= 0) - nouveau_therm_mode(therm, priv->mode); - priv->sensor.program_alarms(therm); + if (priv->fan.percent >= 0) + therm->fan_set(therm, priv->fan.percent); + return 0; } int -_nouveau_therm_fini(struct nouveau_object *object, bool suspend) +nouveau_therm_fini(struct nouveau_object *object, bool suspend) { struct nouveau_therm *therm = (void *)object; struct nouveau_therm_priv *priv = (void *)therm; - if (suspend) { - priv->suspend = priv->mode; - priv->mode = NOUVEAU_THERM_CTRL_NONE; - } + priv->fan.percent = therm->fan_get(therm); return nouveau_subdev_fini(&therm->base, suspend); } - -int -nouveau_therm_create_(struct nouveau_object *parent, - struct nouveau_object *engine, - struct nouveau_oclass *oclass, - int length, void **pobject) -{ - struct nouveau_therm_priv *priv; - int ret; - - ret = nouveau_subdev_create_(parent, engine, oclass, 0, "PTHERM", - "therm", length, pobject); - priv = *pobject; - if (ret) - return ret; - - nouveau_alarm_init(&priv->alarm, nouveau_therm_alarm); - spin_lock_init(&priv->lock); - spin_lock_init(&priv->sensor.alarm_program_lock); - - priv->base.fan_get = nouveau_therm_fan_user_get; - priv->base.fan_set = nouveau_therm_fan_user_set; - priv->base.fan_sense = nouveau_therm_fan_sense; - priv->base.attr_get = nouveau_therm_attr_get; - priv->base.attr_set = nouveau_therm_attr_set; - priv->mode = priv->suspend = -1; /* undefined */ - return 0; -} - -int -nouveau_therm_preinit(struct nouveau_therm *therm) -{ - nouveau_therm_ic_ctor(therm); - nouveau_therm_sensor_ctor(therm); - nouveau_therm_fan_ctor(therm); - - nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_NONE); - return 0; -} - -void -_nouveau_therm_dtor(struct nouveau_object *object) -{ - struct nouveau_therm_priv *priv = (void *)object; - kfree(priv->fan); - nouveau_subdev_destroy(&priv->base.base); -} diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c index c728380d3d62..523178685180 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c @@ -27,107 +27,90 @@ #include #include - #include #include -static int -nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target) +int +nouveau_therm_fan_get(struct nouveau_therm *therm) { - struct nouveau_therm *therm = fan->parent; struct nouveau_therm_priv *priv = (void *)therm; - struct nouveau_timer *ptimer = nouveau_timer(priv); - unsigned long flags; - int ret = 0; - int duty; - - /* update target fan speed, restricting to allowed range */ - spin_lock_irqsave(&fan->lock, flags); - if (target < 0) - target = fan->percent; - target = max_t(u8, target, fan->bios.min_duty); - target = min_t(u8, target, fan->bios.max_duty); - if (fan->percent != target) { - nv_debug(therm, "FAN target: %d\n", target); - fan->percent = target; - } + struct nouveau_gpio *gpio = nouveau_gpio(therm); + struct dcb_gpio_func func; + int card_type = nv_device(therm)->card_type; + u32 divs, duty; + int ret; - /* check that we're not already at the target duty cycle */ - duty = fan->get(therm); - if (duty == target) - goto done; - - /* smooth out the fanspeed increase/decrease */ - if (!immediate && duty >= 0) { - /* the constant "3" is a rough approximation taken from - * nvidia's behaviour. - * it is meant to bump the fan speed more incrementally - */ - if (duty < target) - duty = min(duty + 3, target); - else if (duty > target) - duty = max(duty - 3, target); - } else { - duty = target; - } + if (!priv->fan.pwm_get) + return -ENODEV; - nv_debug(therm, "FAN update: %d\n", duty); - ret = fan->set(therm, duty); - if (ret) - goto done; - - /* schedule next fan update, if not at target speed already */ - if (list_empty(&fan->alarm.head) && target != duty) { - u16 bump_period = fan->bios.bump_period; - u16 slow_down_period = fan->bios.slow_down_period; - u64 delay; - - if (duty > target) - delay = slow_down_period; - else if (duty == target) - delay = min(bump_period, slow_down_period) ; - else - delay = bump_period; - - ptimer->alarm(ptimer, delay * 1000 * 1000, &fan->alarm); + ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func); + if (ret == 0) { + ret = priv->fan.pwm_get(therm, func.line, &divs, &duty); + if (ret == 0 && divs) { + divs = max(divs, duty); + if (card_type <= NV_40 || (func.log[0] & 1)) + duty = divs - duty; + return (duty * 100) / divs; + } + + return gpio->get(gpio, 0, func.func, func.line) * 100; } -done: - spin_unlock_irqrestore(&fan->lock, flags); - return ret; -} - -static void -nouveau_fan_alarm(struct nouveau_alarm *alarm) -{ - struct nouveau_fan *fan = container_of(alarm, struct nouveau_fan, alarm); - nouveau_fan_update(fan, false, -1); + return -ENODEV; } int -nouveau_therm_fan_get(struct nouveau_therm *therm) +nouveau_therm_fan_set(struct nouveau_therm *therm, int percent) { struct nouveau_therm_priv *priv = (void *)therm; - return priv->fan->get(therm); -} + struct nouveau_gpio *gpio = nouveau_gpio(therm); + struct dcb_gpio_func func; + int card_type = nv_device(therm)->card_type; + u32 divs, duty; + int ret; -int -nouveau_therm_fan_set(struct nouveau_therm *therm, bool immediate, int percent) -{ - struct nouveau_therm_priv *priv = (void *)therm; - return nouveau_fan_update(priv->fan, immediate, percent); + if (priv->fan.mode == FAN_CONTROL_NONE) + return -EINVAL; + + if (!priv->fan.pwm_set) + return -ENODEV; + + if (percent < priv->bios_fan.min_duty) + percent = priv->bios_fan.min_duty; + if (percent > priv->bios_fan.max_duty) + percent = priv->bios_fan.max_duty; + + ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func); + if (ret == 0) { + divs = priv->bios_perf_fan.pwm_divisor; + if (priv->bios_fan.pwm_freq) { + divs = 1; + if (priv->fan.pwm_clock) + divs = priv->fan.pwm_clock(therm); + divs /= priv->bios_fan.pwm_freq; + } + + duty = ((divs * percent) + 99) / 100; + if (card_type <= NV_40 || (func.log[0] & 1)) + duty = divs - duty; + + ret = priv->fan.pwm_set(therm, func.line, divs, duty); + return ret; + } + + return -ENODEV; } int nouveau_therm_fan_sense(struct nouveau_therm *therm) { - struct nouveau_therm_priv *priv = (void *)therm; struct nouveau_timer *ptimer = nouveau_timer(therm); struct nouveau_gpio *gpio = nouveau_gpio(therm); + struct dcb_gpio_func func; u32 cycles, cur, prev; u64 start, end, tach; - if (priv->fan->tach.func == DCB_GPIO_UNUSED) + if (gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &func)) return -ENODEV; /* Time a complete rotation and extrapolate to RPM: @@ -135,12 +118,12 @@ nouveau_therm_fan_sense(struct nouveau_therm *therm) * We get 4 changes (0 -> 1 -> 0 -> 1) per complete rotation. */ start = ptimer->read(ptimer); - prev = gpio->get(gpio, 0, priv->fan->tach.func, priv->fan->tach.line); + prev = gpio->get(gpio, 0, func.func, func.line); cycles = 0; do { usleep_range(500, 1000); /* supports 0 < rpm < 7500 */ - cur = gpio->get(gpio, 0, priv->fan->tach.func, priv->fan->tach.line); + cur = gpio->get(gpio, 0, func.func, func.line); if (prev != cur) { if (!start) start = ptimer->read(ptimer); @@ -158,6 +141,34 @@ nouveau_therm_fan_sense(struct nouveau_therm *therm) return 0; } +int +nouveau_therm_fan_set_mode(struct nouveau_therm *therm, + enum nouveau_therm_fan_mode mode) +{ + struct nouveau_therm_priv *priv = (void *)therm; + + if (priv->fan.mode == mode) + return 0; + + if (mode < FAN_CONTROL_NONE || mode >= FAN_CONTROL_NR) + return -EINVAL; + + switch (mode) + { + case FAN_CONTROL_NONE: + nv_info(therm, "switch fan to no-control mode\n"); + break; + case FAN_CONTROL_MANUAL: + nv_info(therm, "switch fan to manual mode\n"); + break; + case FAN_CONTROL_NR: + break; + } + + priv->fan.mode = mode; + return 0; +} + int nouveau_therm_fan_user_get(struct nouveau_therm *therm) { @@ -169,86 +180,55 @@ nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent) { struct nouveau_therm_priv *priv = (void *)therm; - if (priv->mode != NOUVEAU_THERM_CTRL_MANUAL) + if (priv->fan.mode != FAN_CONTROL_MANUAL) return -EINVAL; - return nouveau_therm_fan_set(therm, true, percent); + return nouveau_therm_fan_set(therm, percent); } -static void +void nouveau_therm_fan_set_defaults(struct nouveau_therm *therm) { struct nouveau_therm_priv *priv = (void *)therm; - priv->fan->bios.pwm_freq = 0; - priv->fan->bios.min_duty = 0; - priv->fan->bios.max_duty = 100; - priv->fan->bios.bump_period = 500; - priv->fan->bios.slow_down_period = 2000; - priv->fan->bios.linear_min_temp = 40; - priv->fan->bios.linear_max_temp = 85; + priv->bios_fan.pwm_freq = 0; + priv->bios_fan.min_duty = 0; + priv->bios_fan.max_duty = 100; } + static void nouveau_therm_fan_safety_checks(struct nouveau_therm *therm) { struct nouveau_therm_priv *priv = (void *)therm; - if (priv->fan->bios.min_duty > 100) - priv->fan->bios.min_duty = 100; - if (priv->fan->bios.max_duty > 100) - priv->fan->bios.max_duty = 100; + if (priv->bios_fan.min_duty > 100) + priv->bios_fan.min_duty = 100; + if (priv->bios_fan.max_duty > 100) + priv->bios_fan.max_duty = 100; - if (priv->fan->bios.min_duty > priv->fan->bios.max_duty) - priv->fan->bios.min_duty = priv->fan->bios.max_duty; + if (priv->bios_fan.min_duty > priv->bios_fan.max_duty) + priv->bios_fan.min_duty = priv->bios_fan.max_duty; +} + +int nouveau_fan_pwm_clock_dummy(struct nouveau_therm *therm) +{ + return 1; } int nouveau_therm_fan_ctor(struct nouveau_therm *therm) { struct nouveau_therm_priv *priv = (void *)therm; - struct nouveau_gpio *gpio = nouveau_gpio(therm); struct nouveau_bios *bios = nouveau_bios(therm); - struct dcb_gpio_func func; - int ret; - /* attempt to locate a drivable fan, and determine control method */ - ret = gpio->find(gpio, 0, DCB_GPIO_FAN, 0xff, &func); - if (ret == 0) { - if (func.log[0] & DCB_GPIO_LOG_DIR_IN) { - nv_debug(therm, "GPIO_FAN is in input mode\n"); - ret = -EINVAL; - } else { - ret = nouveau_fanpwm_create(therm, &func); - if (ret != 0) - ret = nouveau_fantog_create(therm, &func); - } - } - - /* no controllable fan found, create a dummy fan module */ - if (ret != 0) { - ret = nouveau_fannil_create(therm); - if (ret) - return ret; - } - - nv_info(therm, "FAN control: %s\n", priv->fan->type); - - /* attempt to detect a tachometer connection */ - ret = gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &priv->fan->tach); - if (ret) - priv->fan->tach.func = DCB_GPIO_UNUSED; - - /* initialise fan bump/slow update handling */ - priv->fan->parent = therm; - nouveau_alarm_init(&priv->fan->alarm, nouveau_fan_alarm); - spin_lock_init(&priv->fan->lock); - - /* other random init... */ nouveau_therm_fan_set_defaults(therm); - nvbios_perf_fan_parse(bios, &priv->fan->perf); - if (nvbios_therm_fan_parse(bios, &priv->fan->bios)) + nvbios_perf_fan_parse(bios, &priv->bios_perf_fan); + if (nvbios_therm_fan_parse(bios, &priv->bios_fan)) nv_error(therm, "parsing the thermal table failed\n"); nouveau_therm_fan_safety_checks(therm); + + nouveau_therm_fan_set_mode(therm, FAN_CONTROL_NONE); + return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/fannil.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/fannil.c deleted file mode 100644 index b78c182e1d51..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/fannil.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include "priv.h" - -static int -nouveau_fannil_get(struct nouveau_therm *therm) -{ - return -ENODEV; -} - -static int -nouveau_fannil_set(struct nouveau_therm *therm, int percent) -{ - return -ENODEV; -} - -int -nouveau_fannil_create(struct nouveau_therm *therm) -{ - struct nouveau_therm_priv *tpriv = (void *)therm; - struct nouveau_fan *priv; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - tpriv->fan = priv; - if (!priv) - return -ENOMEM; - - priv->type = "none / external"; - priv->get = nouveau_fannil_get; - priv->set = nouveau_fannil_set; - return 0; -} diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c deleted file mode 100644 index 5f71db8e8992..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - * Martin Peres - */ - -#include -#include - -#include "priv.h" - -struct nouveau_fanpwm_priv { - struct nouveau_fan base; - struct dcb_gpio_func func; -}; - -static int -nouveau_fanpwm_get(struct nouveau_therm *therm) -{ - struct nouveau_therm_priv *tpriv = (void *)therm; - struct nouveau_fanpwm_priv *priv = (void *)tpriv->fan; - struct nouveau_gpio *gpio = nouveau_gpio(therm); - int card_type = nv_device(therm)->card_type; - u32 divs, duty; - int ret; - - ret = therm->pwm_get(therm, priv->func.line, &divs, &duty); - if (ret == 0 && divs) { - divs = max(divs, duty); - if (card_type <= NV_40 || (priv->func.log[0] & 1)) - duty = divs - duty; - return (duty * 100) / divs; - } - - return gpio->get(gpio, 0, priv->func.func, priv->func.line) * 100; -} - -static int -nouveau_fanpwm_set(struct nouveau_therm *therm, int percent) -{ - struct nouveau_therm_priv *tpriv = (void *)therm; - struct nouveau_fanpwm_priv *priv = (void *)tpriv->fan; - int card_type = nv_device(therm)->card_type; - u32 divs, duty; - int ret; - - divs = priv->base.perf.pwm_divisor; - if (priv->base.bios.pwm_freq) { - divs = 1; - if (therm->pwm_clock) - divs = therm->pwm_clock(therm); - divs /= priv->base.bios.pwm_freq; - } - - duty = ((divs * percent) + 99) / 100; - if (card_type <= NV_40 || (priv->func.log[0] & 1)) - duty = divs - duty; - - ret = therm->pwm_set(therm, priv->func.line, divs, duty); - if (ret == 0) - ret = therm->pwm_ctrl(therm, priv->func.line, true); - return ret; -} - -int -nouveau_fanpwm_create(struct nouveau_therm *therm, struct dcb_gpio_func *func) -{ - struct nouveau_device *device = nv_device(therm); - struct nouveau_therm_priv *tpriv = (void *)therm; - struct nouveau_fanpwm_priv *priv; - u32 divs, duty; - - if (!nouveau_boolopt(device->cfgopt, "NvFanPWM", func->param) || - !therm->pwm_ctrl || - therm->pwm_get(therm, func->line, &divs, &duty) == -ENODEV) - return -ENODEV; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - tpriv->fan = &priv->base; - if (!priv) - return -ENOMEM; - - priv->base.type = "PWM"; - priv->base.get = nouveau_fanpwm_get; - priv->base.set = nouveau_fanpwm_set; - priv->func = *func; - return 0; -} diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/fantog.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/fantog.c deleted file mode 100644 index e601773ee475..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/fantog.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2012 The Nouveau community - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Martin Peres - */ - -#include "priv.h" - -#include -#include - -#include -#include - -struct nouveau_fantog_priv { - struct nouveau_fan base; - struct nouveau_alarm alarm; - spinlock_t lock; - u32 period_us; - u32 percent; - struct dcb_gpio_func func; -}; - -static void -nouveau_fantog_update(struct nouveau_fantog_priv *priv, int percent) -{ - struct nouveau_therm_priv *tpriv = (void *)priv->base.parent; - struct nouveau_timer *ptimer = nouveau_timer(tpriv); - struct nouveau_gpio *gpio = nouveau_gpio(tpriv); - unsigned long flags; - int duty; - - spin_lock_irqsave(&priv->lock, flags); - if (percent < 0) - percent = priv->percent; - priv->percent = percent; - - duty = !gpio->get(gpio, 0, DCB_GPIO_FAN, 0xff); - gpio->set(gpio, 0, DCB_GPIO_FAN, 0xff, duty); - - if (list_empty(&priv->alarm.head) && percent != (duty * 100)) { - u64 next_change = (percent * priv->period_us) / 100; - if (!duty) - next_change = priv->period_us - next_change; - ptimer->alarm(ptimer, next_change * 1000, &priv->alarm); - } - spin_unlock_irqrestore(&priv->lock, flags); -} - -static void -nouveau_fantog_alarm(struct nouveau_alarm *alarm) -{ - struct nouveau_fantog_priv *priv = - container_of(alarm, struct nouveau_fantog_priv, alarm); - nouveau_fantog_update(priv, -1); -} - -static int -nouveau_fantog_get(struct nouveau_therm *therm) -{ - struct nouveau_therm_priv *tpriv = (void *)therm; - struct nouveau_fantog_priv *priv = (void *)tpriv->fan; - return priv->percent; -} - -static int -nouveau_fantog_set(struct nouveau_therm *therm, int percent) -{ - struct nouveau_therm_priv *tpriv = (void *)therm; - struct nouveau_fantog_priv *priv = (void *)tpriv->fan; - if (therm->pwm_ctrl) - therm->pwm_ctrl(therm, priv->func.line, false); - nouveau_fantog_update(priv, percent); - return 0; -} - -int -nouveau_fantog_create(struct nouveau_therm *therm, struct dcb_gpio_func *func) -{ - struct nouveau_therm_priv *tpriv = (void *)therm; - struct nouveau_fantog_priv *priv; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - tpriv->fan = &priv->base; - if (!priv) - return -ENOMEM; - - priv->base.type = "toggle"; - priv->base.get = nouveau_fantog_get; - priv->base.set = nouveau_fantog_set; - nouveau_alarm_init(&priv->alarm, nouveau_fantog_alarm); - priv->period_us = 100000; /* 10Hz */ - priv->percent = 100; - priv->func = *func; - spin_lock_init(&priv->lock); - return 0; -} diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c index e24090bac195..e512ff0aae60 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c @@ -31,7 +31,7 @@ static bool probe_monitoring_device(struct nouveau_i2c_port *i2c, struct i2c_board_info *info) { - struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c); + struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c->i2c); struct i2c_client *client; request_module("%s%s", I2C_MODULE_PREFIX, info->type); @@ -53,31 +53,6 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c, return true; } -static struct i2c_board_info -nv_board_infos[] = { - { I2C_BOARD_INFO("w83l785ts", 0x2d) }, - { I2C_BOARD_INFO("w83781d", 0x2d) }, - { I2C_BOARD_INFO("adt7473", 0x2e) }, - { I2C_BOARD_INFO("adt7473", 0x2d) }, - { I2C_BOARD_INFO("adt7473", 0x2c) }, - { I2C_BOARD_INFO("f75375", 0x2e) }, - { I2C_BOARD_INFO("lm99", 0x4c) }, - { I2C_BOARD_INFO("lm90", 0x4c) }, - { I2C_BOARD_INFO("lm90", 0x4d) }, - { I2C_BOARD_INFO("adm1021", 0x18) }, - { I2C_BOARD_INFO("adm1021", 0x19) }, - { I2C_BOARD_INFO("adm1021", 0x1a) }, - { I2C_BOARD_INFO("adm1021", 0x29) }, - { I2C_BOARD_INFO("adm1021", 0x2a) }, - { I2C_BOARD_INFO("adm1021", 0x2b) }, - { I2C_BOARD_INFO("adm1021", 0x4c) }, - { I2C_BOARD_INFO("adm1021", 0x4d) }, - { I2C_BOARD_INFO("adm1021", 0x4e) }, - { I2C_BOARD_INFO("lm63", 0x18) }, - { I2C_BOARD_INFO("lm63", 0x4e) }, - { } -}; - void nouveau_therm_ic_ctor(struct nouveau_therm *therm) { @@ -85,6 +60,29 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) struct nouveau_bios *bios = nouveau_bios(therm); struct nouveau_i2c *i2c = nouveau_i2c(therm); struct nvbios_extdev_func extdev_entry; + struct i2c_board_info info[] = { + { I2C_BOARD_INFO("w83l785ts", 0x2d) }, + { I2C_BOARD_INFO("w83781d", 0x2d) }, + { I2C_BOARD_INFO("adt7473", 0x2e) }, + { I2C_BOARD_INFO("adt7473", 0x2d) }, + { I2C_BOARD_INFO("adt7473", 0x2c) }, + { I2C_BOARD_INFO("f75375", 0x2e) }, + { I2C_BOARD_INFO("lm99", 0x4c) }, + { I2C_BOARD_INFO("lm90", 0x4c) }, + { I2C_BOARD_INFO("lm90", 0x4d) }, + { I2C_BOARD_INFO("adm1021", 0x18) }, + { I2C_BOARD_INFO("adm1021", 0x19) }, + { I2C_BOARD_INFO("adm1021", 0x1a) }, + { I2C_BOARD_INFO("adm1021", 0x29) }, + { I2C_BOARD_INFO("adm1021", 0x2a) }, + { I2C_BOARD_INFO("adm1021", 0x2b) }, + { I2C_BOARD_INFO("adm1021", 0x4c) }, + { I2C_BOARD_INFO("adm1021", 0x4d) }, + { I2C_BOARD_INFO("adm1021", 0x4e) }, + { I2C_BOARD_INFO("lm63", 0x18) }, + { I2C_BOARD_INFO("lm63", 0x4e) }, + { } + }; if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_LM89, &extdev_entry)) { struct i2c_board_info board[] = { @@ -113,6 +111,6 @@ nouveau_therm_ic_ctor(struct nouveau_therm *therm) /* The vbios doesn't provide the address of an exisiting monitoring device. Let's try our static list. */ - i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", - nv_board_infos, probe_monitoring_device); + i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", info, + probe_monitoring_device); } diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c index 0f5363edb964..fcf2cfe731d6 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c @@ -25,10 +25,6 @@ #include "priv.h" -struct nv40_therm_priv { - struct nouveau_therm_priv base; -}; - static int nv40_sensor_setup(struct nouveau_therm *therm) { @@ -38,7 +34,6 @@ nv40_sensor_setup(struct nouveau_therm *therm) if (device->chipset >= 0x46) { nv_mask(therm, 0x15b8, 0x80000000, 0); nv_wr32(therm, 0x15b0, 0x80003fff); - mdelay(10); /* wait for the temperature to stabilize */ return nv_rd32(therm, 0x15b4) & 0x3fff; } else { nv_wr32(therm, 0x15b0, 0xff); @@ -80,20 +75,7 @@ nv40_temp_get(struct nouveau_therm *therm) return core_temp; } -static int -nv40_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable) -{ - u32 mask = enable ? 0x80000000 : 0x0000000; - if (line == 2) nv_mask(therm, 0x0010f0, 0x80000000, mask); - else if (line == 9) nv_mask(therm, 0x0015f4, 0x80000000, mask); - else { - nv_error(therm, "unknown pwm ctrl for gpio %d\n", line); - return -ENODEV; - } - return 0; -} - -static int +int nv40_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) { if (line == 2) { @@ -119,15 +101,15 @@ nv40_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) return -EINVAL; } -static int +int nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) { if (line == 2) { - nv_mask(therm, 0x0010f0, 0x7fff7fff, (duty << 16) | divs); + nv_wr32(therm, 0x0010f0, 0x80000000 | (duty << 16) | divs); } else if (line == 9) { nv_wr32(therm, 0x0015f8, divs); - nv_mask(therm, 0x0015f4, 0x7fffffff, duty); + nv_wr32(therm, 0x0015f4, duty | 0x80000000); } else { nv_error(therm, "unknown pwm ctrl for gpio %d\n", line); return -ENODEV; @@ -136,51 +118,37 @@ nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) return 0; } -static void -nv40_therm_intr(struct nouveau_subdev *subdev) -{ - struct nouveau_therm *therm = nouveau_therm(subdev); - uint32_t stat = nv_rd32(therm, 0x1100); - - /* traitement */ - - /* ack all IRQs */ - nv_wr32(therm, 0x1100, 0x70000); - - nv_error(therm, "THERM received an IRQ: stat = %x\n", stat); -} - static int nv40_therm_ctor(struct nouveau_object *parent, - struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nv40_therm_priv *priv; + struct nouveau_therm_priv *priv; + struct nouveau_therm *therm; int ret; ret = nouveau_therm_create(parent, engine, oclass, &priv); *pobject = nv_object(priv); + therm = (void *) priv; if (ret) return ret; - priv->base.base.pwm_ctrl = nv40_fan_pwm_ctrl; - priv->base.base.pwm_get = nv40_fan_pwm_get; - priv->base.base.pwm_set = nv40_fan_pwm_set; - priv->base.base.temp_get = nv40_temp_get; - priv->base.sensor.program_alarms = nouveau_therm_program_alarms_polling; - nv_subdev(priv)->intr = nv40_therm_intr; - return nouveau_therm_preinit(&priv->base.base); -} + nouveau_therm_ic_ctor(therm); + nouveau_therm_sensor_ctor(therm); + nouveau_therm_fan_ctor(therm); -static int -nv40_therm_init(struct nouveau_object *object) -{ - struct nouveau_therm *therm = (void *)object; + priv->fan.pwm_get = nv40_fan_pwm_get; + priv->fan.pwm_set = nv40_fan_pwm_set; - nv40_sensor_setup(therm); + therm->temp_get = nv40_temp_get; + therm->fan_get = nouveau_therm_fan_user_get; + therm->fan_set = nouveau_therm_fan_user_set; + therm->fan_sense = nouveau_therm_fan_sense; + therm->attr_get = nouveau_therm_attr_get; + therm->attr_set = nouveau_therm_attr_set; - return _nouveau_therm_init(object); + return 0; } struct nouveau_oclass @@ -189,7 +157,7 @@ nv40_therm_oclass = { .ofuncs = &(struct nouveau_ofuncs) { .ctor = nv40_therm_ctor, .dtor = _nouveau_therm_dtor, - .init = nv40_therm_init, - .fini = _nouveau_therm_fini, + .init = nouveau_therm_init, + .fini = nouveau_therm_fini, }, -}; +}; \ No newline at end of file diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c index 86632cbd65ce..9360ddd469e7 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c @@ -25,10 +25,6 @@ #include "priv.h" -struct nv50_therm_priv { - struct nouveau_therm_priv base; -}; - static int pwm_info(struct nouveau_therm *therm, int *line, int *ctrl, int *indx) { @@ -54,16 +50,6 @@ pwm_info(struct nouveau_therm *therm, int *line, int *ctrl, int *indx) return 0; } -int -nv50_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable) -{ - u32 data = enable ? 0x00000001 : 0x00000000; - int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id); - if (ret == 0) - nv_mask(therm, ctrl, 0x00010001 << line, data << line); - return ret; -} - int nv50_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) { @@ -87,6 +73,7 @@ nv50_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) if (ret) return ret; + nv_mask(therm, ctrl, 0x00010001 << line, 0x00000001 << line); nv_wr32(therm, 0x00e114 + (id * 8), divs); nv_wr32(therm, 0x00e118 + (id * 8), duty | 0x80000000); return 0; @@ -124,178 +111,38 @@ nv50_temp_get(struct nouveau_therm *therm) return nv_rd32(therm, 0x20400); } -static void -nv50_therm_program_alarms(struct nouveau_therm *therm) -{ - struct nouveau_therm_priv *priv = (void *)therm; - struct nvbios_therm_sensor *sensor = &priv->bios_sensor; - unsigned long flags; - - spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags); - - /* enable RISING and FALLING IRQs for shutdown, THRS 0, 1, 2 and 4 */ - nv_wr32(therm, 0x20000, 0x000003ff); - - /* shutdown: The computer should be shutdown when reached */ - nv_wr32(therm, 0x20484, sensor->thrs_shutdown.hysteresis); - nv_wr32(therm, 0x20480, sensor->thrs_shutdown.temp); - - /* THRS_1 : fan boost*/ - nv_wr32(therm, 0x204c4, sensor->thrs_fan_boost.temp); - - /* THRS_2 : critical */ - nv_wr32(therm, 0x204c0, sensor->thrs_critical.temp); - - /* THRS_4 : down clock */ - nv_wr32(therm, 0x20414, sensor->thrs_down_clock.temp); - spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags); - - nv_info(therm, - "Programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n", - sensor->thrs_fan_boost.temp, sensor->thrs_fan_boost.hysteresis, - sensor->thrs_down_clock.temp, - sensor->thrs_down_clock.hysteresis, - sensor->thrs_critical.temp, sensor->thrs_critical.hysteresis, - sensor->thrs_shutdown.temp, sensor->thrs_shutdown.hysteresis); - -} - -/* must be called with alarm_program_lock taken ! */ -static void -nv50_therm_threshold_hyst_emulation(struct nouveau_therm *therm, - uint32_t thrs_reg, u8 status_bit, - const struct nvbios_therm_threshold *thrs, - enum nouveau_therm_thrs thrs_name) -{ - enum nouveau_therm_thrs_direction direction; - enum nouveau_therm_thrs_state prev_state, new_state; - int temp, cur; - - prev_state = nouveau_therm_sensor_get_threshold_state(therm, thrs_name); - temp = nv_rd32(therm, thrs_reg); - - /* program the next threshold */ - if (temp == thrs->temp) { - nv_wr32(therm, thrs_reg, thrs->temp - thrs->hysteresis); - new_state = NOUVEAU_THERM_THRS_HIGHER; - } else { - nv_wr32(therm, thrs_reg, thrs->temp); - new_state = NOUVEAU_THERM_THRS_LOWER; - } - - /* fix the state (in case someone reprogrammed the alarms) */ - cur = therm->temp_get(therm); - if (new_state == NOUVEAU_THERM_THRS_LOWER && cur > thrs->temp) - new_state = NOUVEAU_THERM_THRS_HIGHER; - else if (new_state == NOUVEAU_THERM_THRS_HIGHER && - cur < thrs->temp - thrs->hysteresis) - new_state = NOUVEAU_THERM_THRS_LOWER; - nouveau_therm_sensor_set_threshold_state(therm, thrs_name, new_state); - - /* find the direction */ - if (prev_state < new_state) - direction = NOUVEAU_THERM_THRS_RISING; - else if (prev_state > new_state) - direction = NOUVEAU_THERM_THRS_FALLING; - else - return; - - /* advertise a change in direction */ - nouveau_therm_sensor_event(therm, thrs_name, direction); -} - -static void -nv50_therm_intr(struct nouveau_subdev *subdev) -{ - struct nouveau_therm *therm = nouveau_therm(subdev); - struct nouveau_therm_priv *priv = (void *)therm; - struct nvbios_therm_sensor *sensor = &priv->bios_sensor; - unsigned long flags; - uint32_t intr; - - spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags); - - intr = nv_rd32(therm, 0x20100); - - /* THRS_4: downclock */ - if (intr & 0x002) { - nv50_therm_threshold_hyst_emulation(therm, 0x20414, 24, - &sensor->thrs_down_clock, - NOUVEAU_THERM_THRS_DOWNCLOCK); - intr &= ~0x002; - } - - /* shutdown */ - if (intr & 0x004) { - nv50_therm_threshold_hyst_emulation(therm, 0x20480, 20, - &sensor->thrs_shutdown, - NOUVEAU_THERM_THRS_SHUTDOWN); - intr &= ~0x004; - } - - /* THRS_1 : fan boost */ - if (intr & 0x008) { - nv50_therm_threshold_hyst_emulation(therm, 0x204c4, 21, - &sensor->thrs_fan_boost, - NOUVEAU_THERM_THRS_FANBOOST); - intr &= ~0x008; - } - - /* THRS_2 : critical */ - if (intr & 0x010) { - nv50_therm_threshold_hyst_emulation(therm, 0x204c0, 22, - &sensor->thrs_critical, - NOUVEAU_THERM_THRS_CRITICAL); - intr &= ~0x010; - } - - if (intr) - nv_error(therm, "unhandled intr 0x%08x\n", intr); - - /* ACK everything */ - nv_wr32(therm, 0x20100, 0xffffffff); - nv_wr32(therm, 0x1100, 0x10000); /* PBUS */ - - spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags); -} - static int nv50_therm_ctor(struct nouveau_object *parent, - struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) + struct nouveau_object *engine, + struct nouveau_oclass *oclass, void *data, u32 size, + struct nouveau_object **pobject) { - struct nv50_therm_priv *priv; + struct nouveau_therm_priv *priv; + struct nouveau_therm *therm; int ret; ret = nouveau_therm_create(parent, engine, oclass, &priv); *pobject = nv_object(priv); + therm = (void *) priv; if (ret) return ret; - priv->base.base.pwm_ctrl = nv50_fan_pwm_ctrl; - priv->base.base.pwm_get = nv50_fan_pwm_get; - priv->base.base.pwm_set = nv50_fan_pwm_set; - priv->base.base.pwm_clock = nv50_fan_pwm_clock; - priv->base.base.temp_get = nv50_temp_get; - priv->base.sensor.program_alarms = nv50_therm_program_alarms; - nv_subdev(priv)->intr = nv50_therm_intr; + nouveau_therm_ic_ctor(therm); + nouveau_therm_sensor_ctor(therm); + nouveau_therm_fan_ctor(therm); - /* init the thresholds */ - nouveau_therm_sensor_set_threshold_state(&priv->base.base, - NOUVEAU_THERM_THRS_SHUTDOWN, - NOUVEAU_THERM_THRS_LOWER); - nouveau_therm_sensor_set_threshold_state(&priv->base.base, - NOUVEAU_THERM_THRS_FANBOOST, - NOUVEAU_THERM_THRS_LOWER); - nouveau_therm_sensor_set_threshold_state(&priv->base.base, - NOUVEAU_THERM_THRS_CRITICAL, - NOUVEAU_THERM_THRS_LOWER); - nouveau_therm_sensor_set_threshold_state(&priv->base.base, - NOUVEAU_THERM_THRS_DOWNCLOCK, - NOUVEAU_THERM_THRS_LOWER); + priv->fan.pwm_get = nv50_fan_pwm_get; + priv->fan.pwm_set = nv50_fan_pwm_set; + priv->fan.pwm_clock = nv50_fan_pwm_clock; - return nouveau_therm_preinit(&priv->base.base); + therm->temp_get = nv50_temp_get; + therm->fan_get = nouveau_therm_fan_user_get; + therm->fan_set = nouveau_therm_fan_user_set; + therm->fan_sense = nouveau_therm_fan_sense; + therm->attr_get = nouveau_therm_attr_get; + therm->attr_set = nouveau_therm_attr_set; + + return 0; } struct nouveau_oclass @@ -304,7 +151,7 @@ nv50_therm_oclass = { .ofuncs = &(struct nouveau_ofuncs) { .ctor = nv50_therm_ctor, .dtor = _nouveau_therm_dtor, - .init = _nouveau_therm_init, - .fini = _nouveau_therm_fini, + .init = nouveau_therm_init, + .fini = nouveau_therm_fini, }, }; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c deleted file mode 100644 index 2dcc5437116a..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include - -#include "priv.h" - -struct nva3_therm_priv { - struct nouveau_therm_priv base; -}; - -int -nva3_therm_fan_sense(struct nouveau_therm *therm) -{ - u32 tach = nv_rd32(therm, 0x00e728) & 0x0000ffff; - u32 ctrl = nv_rd32(therm, 0x00e720); - if (ctrl & 0x00000001) - return tach * 60; - return -ENODEV; -} - -static int -nva3_therm_init(struct nouveau_object *object) -{ - struct nva3_therm_priv *priv = (void *)object; - struct dcb_gpio_func *tach = &priv->base.fan->tach; - int ret; - - ret = nouveau_therm_init(&priv->base.base); - if (ret) - return ret; - - /* enable fan tach, count revolutions per-second */ - nv_mask(priv, 0x00e720, 0x00000003, 0x00000002); - if (tach->func != DCB_GPIO_UNUSED) { - nv_wr32(priv, 0x00e724, nv_device(priv)->crystal * 1000); - nv_mask(priv, 0x00e720, 0x001f0000, tach->line << 16); - nv_mask(priv, 0x00e720, 0x00000001, 0x00000001); - } - nv_mask(priv, 0x00e720, 0x00000002, 0x00000000); - - return 0; -} - -static int -nva3_therm_ctor(struct nouveau_object *parent, - struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nva3_therm_priv *priv; - int ret; - - ret = nouveau_therm_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.base.pwm_ctrl = nv50_fan_pwm_ctrl; - priv->base.base.pwm_get = nv50_fan_pwm_get; - priv->base.base.pwm_set = nv50_fan_pwm_set; - priv->base.base.pwm_clock = nv50_fan_pwm_clock; - priv->base.base.temp_get = nv50_temp_get; - priv->base.base.fan_sense = nva3_therm_fan_sense; - priv->base.sensor.program_alarms = nouveau_therm_program_alarms_polling; - return nouveau_therm_preinit(&priv->base.base); -} - -struct nouveau_oclass -nva3_therm_oclass = { - .handle = NV_SUBDEV(THERM, 0xa3), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nva3_therm_ctor, - .dtor = _nouveau_therm_dtor, - .init = nva3_therm_init, - .fini = _nouveau_therm_fini, - }, -}; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c deleted file mode 100644 index d7d30ee8332e..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include "priv.h" - -struct nvd0_therm_priv { - struct nouveau_therm_priv base; -}; - -static int -pwm_info(struct nouveau_therm *therm, int line) -{ - u32 gpio = nv_rd32(therm, 0x00d610 + (line * 0x04)); - switch (gpio & 0x000000c0) { - case 0x00000000: /* normal mode, possibly pwm forced off by us */ - case 0x00000040: /* nvio special */ - switch (gpio & 0x0000001f) { - case 0x19: return 1; - case 0x1c: return 0; - default: - break; - } - default: - break; - } - - nv_error(therm, "GPIO %d unknown PWM: 0x%08x\n", line, gpio); - return -ENODEV; -} - -static int -nvd0_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable) -{ - u32 data = enable ? 0x00000040 : 0x00000000; - int indx = pwm_info(therm, line); - if (indx < 0) - return indx; - - nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data); - return 0; -} - -static int -nvd0_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) -{ - int indx = pwm_info(therm, line); - if (indx < 0) - return indx; - - if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) { - *divs = nv_rd32(therm, 0x00e114 + (indx * 8)); - *duty = nv_rd32(therm, 0x00e118 + (indx * 8)); - return 0; - } - - return -EINVAL; -} - -static int -nvd0_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) -{ - int indx = pwm_info(therm, line); - if (indx < 0) - return indx; - - nv_wr32(therm, 0x00e114 + (indx * 8), divs); - nv_wr32(therm, 0x00e118 + (indx * 8), duty | 0x80000000); - return 0; -} - -static int -nvd0_fan_pwm_clock(struct nouveau_therm *therm) -{ - return (nv_device(therm)->crystal * 1000) / 20; -} - -static int -nvd0_therm_init(struct nouveau_object *object) -{ - struct nvd0_therm_priv *priv = (void *)object; - int ret; - - ret = nouveau_therm_init(&priv->base.base); - if (ret) - return ret; - - /* enable fan tach, count revolutions per-second */ - nv_mask(priv, 0x00e720, 0x00000003, 0x00000002); - if (priv->base.fan->tach.func != DCB_GPIO_UNUSED) { - nv_mask(priv, 0x00d79c, 0x000000ff, priv->base.fan->tach.line); - nv_wr32(priv, 0x00e724, nv_device(priv)->crystal * 1000); - nv_mask(priv, 0x00e720, 0x00000001, 0x00000001); - } - nv_mask(priv, 0x00e720, 0x00000002, 0x00000000); - - return 0; -} - -static int -nvd0_therm_ctor(struct nouveau_object *parent, - struct nouveau_object *engine, - struct nouveau_oclass *oclass, void *data, u32 size, - struct nouveau_object **pobject) -{ - struct nvd0_therm_priv *priv; - int ret; - - ret = nouveau_therm_create(parent, engine, oclass, &priv); - *pobject = nv_object(priv); - if (ret) - return ret; - - priv->base.base.pwm_ctrl = nvd0_fan_pwm_ctrl; - priv->base.base.pwm_get = nvd0_fan_pwm_get; - priv->base.base.pwm_set = nvd0_fan_pwm_set; - priv->base.base.pwm_clock = nvd0_fan_pwm_clock; - priv->base.base.temp_get = nv50_temp_get; - priv->base.base.fan_sense = nva3_therm_fan_sense; - priv->base.sensor.program_alarms = nouveau_therm_program_alarms_polling; - return nouveau_therm_preinit(&priv->base.base); -} - -struct nouveau_oclass -nvd0_therm_oclass = { - .handle = NV_SUBDEV(THERM, 0xd0), - .ofuncs = &(struct nouveau_ofuncs) { - .ctor = nvd0_therm_ctor, - .dtor = _nouveau_therm_dtor, - .init = nvd0_therm_init, - .fini = _nouveau_therm_fini, - }, -}; diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h index 06b98706b3fc..1c3cd6abc36e 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h @@ -1,6 +1,3 @@ -#ifndef __NVTHERM_PRIV_H__ -#define __NVTHERM_PRIV_H__ - /* * Copyright 2012 The Nouveau community * @@ -28,81 +25,33 @@ #include #include -#include #include #include -#include - -struct nouveau_fan { - struct nouveau_therm *parent; - const char *type; - - struct nvbios_therm_fan bios; - struct nvbios_perf_fan perf; - - struct nouveau_alarm alarm; - spinlock_t lock; - int percent; - - int (*get)(struct nouveau_therm *therm); - int (*set)(struct nouveau_therm *therm, int percent); - - struct dcb_gpio_func tach; -}; - -enum nouveau_therm_thrs_direction { - NOUVEAU_THERM_THRS_FALLING = 0, - NOUVEAU_THERM_THRS_RISING = 1 -}; - -enum nouveau_therm_thrs_state { - NOUVEAU_THERM_THRS_LOWER = 0, - NOUVEAU_THERM_THRS_HIGHER = 1 -}; - -enum nouveau_therm_thrs { - NOUVEAU_THERM_THRS_FANBOOST = 0, - NOUVEAU_THERM_THRS_DOWNCLOCK = 1, - NOUVEAU_THERM_THRS_CRITICAL = 2, - NOUVEAU_THERM_THRS_SHUTDOWN = 3, - NOUVEAU_THERM_THRS_NR -}; struct nouveau_therm_priv { struct nouveau_therm base; - /* automatic thermal management */ - struct nouveau_alarm alarm; - spinlock_t lock; - struct nouveau_therm_trip_point *last_trip; - int mode; - int suspend; - /* bios */ struct nvbios_therm_sensor bios_sensor; + struct nvbios_therm_fan bios_fan; + struct nvbios_perf_fan bios_perf_fan; /* fan priv */ - struct nouveau_fan *fan; - - /* alarms priv */ struct { - spinlock_t alarm_program_lock; - struct nouveau_alarm therm_poll_alarm; - enum nouveau_therm_thrs_state alarm_state[NOUVEAU_THERM_THRS_NR]; - void (*program_alarms)(struct nouveau_therm *); - } sensor; + enum nouveau_therm_fan_mode mode; + int percent; - /* what should be done if the card overheats */ - struct { - void (*downclock)(struct nouveau_therm *, bool active); - void (*pause)(struct nouveau_therm *, bool active); - } emergency; + int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*); + int (*pwm_set)(struct nouveau_therm *, int line, u32, u32); + int (*pwm_clock)(struct nouveau_therm *); + } fan; /* ic */ struct i2c_client *ic; }; -int nouveau_therm_mode(struct nouveau_therm *therm, int mode); +int nouveau_therm_init(struct nouveau_object *object); +int nouveau_therm_fini(struct nouveau_object *object, bool suspend); int nouveau_therm_attr_get(struct nouveau_therm *therm, enum nouveau_therm_attr_type type); int nouveau_therm_attr_set(struct nouveau_therm *therm, @@ -114,35 +63,11 @@ int nouveau_therm_sensor_ctor(struct nouveau_therm *therm); int nouveau_therm_fan_ctor(struct nouveau_therm *therm); int nouveau_therm_fan_get(struct nouveau_therm *therm); -int nouveau_therm_fan_set(struct nouveau_therm *therm, bool now, int percent); +int nouveau_therm_fan_set(struct nouveau_therm *therm, int percent); int nouveau_therm_fan_user_get(struct nouveau_therm *therm); int nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent); +int nouveau_therm_fan_set_mode(struct nouveau_therm *therm, + enum nouveau_therm_fan_mode mode); -int nouveau_therm_fan_sense(struct nouveau_therm *therm); - -int nouveau_therm_preinit(struct nouveau_therm *); -void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm, - enum nouveau_therm_thrs thrs, - enum nouveau_therm_thrs_state st); -enum nouveau_therm_thrs_state -nouveau_therm_sensor_get_threshold_state(struct nouveau_therm *therm, - enum nouveau_therm_thrs thrs); -void nouveau_therm_sensor_event(struct nouveau_therm *therm, - enum nouveau_therm_thrs thrs, - enum nouveau_therm_thrs_direction dir); -void nouveau_therm_program_alarms_polling(struct nouveau_therm *therm); - -int nv50_fan_pwm_ctrl(struct nouveau_therm *, int, bool); -int nv50_fan_pwm_get(struct nouveau_therm *, int, u32 *, u32 *); -int nv50_fan_pwm_set(struct nouveau_therm *, int, u32, u32); -int nv50_fan_pwm_clock(struct nouveau_therm *); -int nv50_temp_get(struct nouveau_therm *therm); - -int nva3_therm_fan_sense(struct nouveau_therm *); - -int nouveau_fanpwm_create(struct nouveau_therm *, struct dcb_gpio_func *); -int nouveau_fantog_create(struct nouveau_therm *, struct dcb_gpio_func *); -int nouveau_fannil_create(struct nouveau_therm *); - -#endif +int nouveau_therm_fan_sense(struct nouveau_therm *therm); diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c index b37624af8297..204282301fb1 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c @@ -58,171 +58,11 @@ static void nouveau_therm_temp_safety_checks(struct nouveau_therm *therm) { struct nouveau_therm_priv *priv = (void *)therm; - struct nvbios_therm_sensor *s = &priv->bios_sensor; if (!priv->bios_sensor.slope_div) priv->bios_sensor.slope_div = 1; if (!priv->bios_sensor.offset_den) priv->bios_sensor.offset_den = 1; - - /* enforce a minimum hysteresis on thresholds */ - s->thrs_fan_boost.hysteresis = max_t(u8, s->thrs_fan_boost.hysteresis, 2); - s->thrs_down_clock.hysteresis = max_t(u8, s->thrs_down_clock.hysteresis, 2); - s->thrs_critical.hysteresis = max_t(u8, s->thrs_critical.hysteresis, 2); - s->thrs_shutdown.hysteresis = max_t(u8, s->thrs_shutdown.hysteresis, 2); -} - -/* must be called with alarm_program_lock taken ! */ -void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm, - enum nouveau_therm_thrs thrs, - enum nouveau_therm_thrs_state st) -{ - struct nouveau_therm_priv *priv = (void *)therm; - priv->sensor.alarm_state[thrs] = st; -} - -/* must be called with alarm_program_lock taken ! */ -enum nouveau_therm_thrs_state -nouveau_therm_sensor_get_threshold_state(struct nouveau_therm *therm, - enum nouveau_therm_thrs thrs) -{ - struct nouveau_therm_priv *priv = (void *)therm; - return priv->sensor.alarm_state[thrs]; -} - -static void -nv_poweroff_work(struct work_struct *work) -{ - orderly_poweroff(true); - kfree(work); -} - -void nouveau_therm_sensor_event(struct nouveau_therm *therm, - enum nouveau_therm_thrs thrs, - enum nouveau_therm_thrs_direction dir) -{ - struct nouveau_therm_priv *priv = (void *)therm; - bool active; - const char *thresolds[] = { - "fanboost", "downclock", "critical", "shutdown" - }; - uint8_t temperature = therm->temp_get(therm); - - if (thrs < 0 || thrs > 3) - return; - - if (dir == NOUVEAU_THERM_THRS_FALLING) - nv_info(therm, "temperature (%u C) went below the '%s' threshold\n", - temperature, thresolds[thrs]); - else - nv_info(therm, "temperature (%u C) hit the '%s' threshold\n", - temperature, thresolds[thrs]); - - active = (dir == NOUVEAU_THERM_THRS_RISING); - switch (thrs) { - case NOUVEAU_THERM_THRS_FANBOOST: - if (active) { - nouveau_therm_fan_set(therm, true, 100); - nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_AUTO); - } - break; - case NOUVEAU_THERM_THRS_DOWNCLOCK: - if (priv->emergency.downclock) - priv->emergency.downclock(therm, active); - break; - case NOUVEAU_THERM_THRS_CRITICAL: - if (priv->emergency.pause) - priv->emergency.pause(therm, active); - break; - case NOUVEAU_THERM_THRS_SHUTDOWN: - if (active) { - struct work_struct *work; - - work = kmalloc(sizeof(*work), GFP_ATOMIC); - if (work) { - INIT_WORK(work, nv_poweroff_work); - schedule_work(work); - } - } - break; - case NOUVEAU_THERM_THRS_NR: - break; - } - -} - -/* must be called with alarm_program_lock taken ! */ -static void -nouveau_therm_threshold_hyst_polling(struct nouveau_therm *therm, - const struct nvbios_therm_threshold *thrs, - enum nouveau_therm_thrs thrs_name) -{ - enum nouveau_therm_thrs_direction direction; - enum nouveau_therm_thrs_state prev_state, new_state; - int temp = therm->temp_get(therm); - - prev_state = nouveau_therm_sensor_get_threshold_state(therm, thrs_name); - - if (temp >= thrs->temp && prev_state == NOUVEAU_THERM_THRS_LOWER) { - direction = NOUVEAU_THERM_THRS_RISING; - new_state = NOUVEAU_THERM_THRS_HIGHER; - } else if (temp <= thrs->temp - thrs->hysteresis && - prev_state == NOUVEAU_THERM_THRS_HIGHER) { - direction = NOUVEAU_THERM_THRS_FALLING; - new_state = NOUVEAU_THERM_THRS_LOWER; - } else - return; /* nothing to do */ - - nouveau_therm_sensor_set_threshold_state(therm, thrs_name, new_state); - nouveau_therm_sensor_event(therm, thrs_name, direction); -} - -static void -alarm_timer_callback(struct nouveau_alarm *alarm) -{ - struct nouveau_therm_priv *priv = - container_of(alarm, struct nouveau_therm_priv, sensor.therm_poll_alarm); - struct nvbios_therm_sensor *sensor = &priv->bios_sensor; - struct nouveau_timer *ptimer = nouveau_timer(priv); - struct nouveau_therm *therm = &priv->base; - unsigned long flags; - - spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags); - - nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_fan_boost, - NOUVEAU_THERM_THRS_FANBOOST); - - nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_down_clock, - NOUVEAU_THERM_THRS_DOWNCLOCK); - - nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_critical, - NOUVEAU_THERM_THRS_CRITICAL); - - nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_shutdown, - NOUVEAU_THERM_THRS_SHUTDOWN); - - /* schedule the next poll in one second */ - if (list_empty(&alarm->head)) - ptimer->alarm(ptimer, 1000 * 1000 * 1000, alarm); - - spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags); -} - -void -nouveau_therm_program_alarms_polling(struct nouveau_therm *therm) -{ - struct nouveau_therm_priv *priv = (void *)therm; - struct nvbios_therm_sensor *sensor = &priv->bios_sensor; - - nv_info(therm, - "programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n", - sensor->thrs_fan_boost.temp, sensor->thrs_fan_boost.hysteresis, - sensor->thrs_down_clock.temp, - sensor->thrs_down_clock.hysteresis, - sensor->thrs_critical.temp, sensor->thrs_critical.hysteresis, - sensor->thrs_shutdown.temp, sensor->thrs_shutdown.hysteresis); - - alarm_timer_callback(&priv->sensor.therm_poll_alarm); } int @@ -231,8 +71,6 @@ nouveau_therm_sensor_ctor(struct nouveau_therm *therm) struct nouveau_therm_priv *priv = (void *)therm; struct nouveau_bios *bios = nouveau_bios(therm); - nouveau_alarm_init(&priv->sensor.therm_poll_alarm, alarm_timer_callback); - nouveau_therm_temp_set_defaults(therm); if (nvbios_therm_sensor_parse(bios, NVBIOS_THERM_DOMAIN_CORE, &priv->bios_sensor)) diff --git a/trunk/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c b/trunk/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c index 8e1bae4f12e8..c26ca9bef671 100644 --- a/trunk/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c +++ b/trunk/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c @@ -79,7 +79,7 @@ nv04_timer_alarm_trigger(struct nouveau_timer *ptimer) /* execute any pending alarm handlers */ list_for_each_entry_safe(alarm, atemp, &exec, head) { - list_del_init(&alarm->head); + list_del(&alarm->head); alarm->func(alarm); } } diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_acpi.h b/trunk/drivers/gpu/drm/nouveau/nouveau_acpi.h index 74acf0f87785..d0da230d7706 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_acpi.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_acpi.h @@ -3,7 +3,7 @@ #define ROM_BIOS_PAGE 4096 -#if defined(CONFIG_ACPI) && defined(CONFIG_X86) +#if defined(CONFIG_ACPI) bool nouveau_is_optimus(void); bool nouveau_is_v1_dsm(void); void nouveau_register_dsm_handler(void); diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_backlight.c b/trunk/drivers/gpu/drm/nouveau/nouveau_backlight.c index 5d940302d2aa..f65b20a375f6 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -84,8 +84,6 @@ nv40_backlight_init(struct drm_connector *connector) props.max_brightness = 31; bd = backlight_device_register("nv_backlight", &connector->kdev, drm, &nv40_bl_ops, &props); - if (IS_ERR(bd)) - return PTR_ERR(bd); drm->backlight = bd; bd->props.brightness = nv40_get_intensity(bd); backlight_update_status(bd); diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_bios.c b/trunk/drivers/gpu/drm/nouveau/nouveau_bios.c index 50a6dd02f7c5..865eddfa30a7 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -678,6 +678,23 @@ int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, return 0; } +static void parse_bios_version(struct drm_device *dev, struct nvbios *bios, uint16_t offset) +{ + /* + * offset + 0 (8 bits): Micro version + * offset + 1 (8 bits): Minor version + * offset + 2 (8 bits): Chip version + * offset + 3 (8 bits): Major version + */ + struct nouveau_drm *drm = nouveau_drm(dev); + + bios->major_version = bios->data[offset + 3]; + bios->chip_version = bios->data[offset + 2]; + NV_INFO(drm, "Bios version %02x.%02x.%02x.%02x\n", + bios->data[offset + 3], bios->data[offset + 2], + bios->data[offset + 1], bios->data[offset]); +} + static void parse_script_table_pointers(struct nvbios *bios, uint16_t offset) { /* @@ -693,6 +710,12 @@ static void parse_script_table_pointers(struct nvbios *bios, uint16_t offset) */ bios->init_script_tbls_ptr = ROM16(bios->data[offset]); + bios->macro_index_tbl_ptr = ROM16(bios->data[offset + 2]); + bios->macro_tbl_ptr = ROM16(bios->data[offset + 4]); + bios->condition_tbl_ptr = ROM16(bios->data[offset + 6]); + bios->io_condition_tbl_ptr = ROM16(bios->data[offset + 8]); + bios->io_flag_condition_tbl_ptr = ROM16(bios->data[offset + 10]); + bios->init_function_tbl_ptr = ROM16(bios->data[offset + 12]); } static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) @@ -742,6 +765,25 @@ static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, st return 0; } +static int parse_bit_C_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) +{ + /* + * offset + 8 (16 bits): PLL limits table pointer + * + * There's more in here, but that's unknown. + */ + struct nouveau_drm *drm = nouveau_drm(dev); + + if (bitentry->length < 10) { + NV_ERROR(drm, "Do not understand BIT C table\n"); + return -EINVAL; + } + + bios->pll_limit_tbl_ptr = ROM16(bios->data[bitentry->offset + 8]); + + return 0; +} + static int parse_bit_display_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) { /* @@ -779,6 +821,12 @@ static int parse_bit_init_tbl_entry(struct drm_device *dev, struct nvbios *bios, } parse_script_table_pointers(bios, bitentry->offset); + + if (bitentry->length >= 16) + bios->some_script_ptr = ROM16(bios->data[bitentry->offset + 14]); + if (bitentry->length >= 18) + bios->init96_tbl_ptr = ROM16(bios->data[bitentry->offset + 16]); + return 0; } @@ -804,6 +852,8 @@ static int parse_bit_i_tbl_entry(struct drm_device *dev, struct nvbios *bios, st return -EINVAL; } + parse_bios_version(dev, bios, bitentry->offset); + /* * bit 4 seems to indicate a mobile bios (doesn't suffer from BMP's * Quadro identity crisis), other bits possibly as for BMP feature byte @@ -1028,6 +1078,9 @@ parse_bit_structure(struct nvbios *bios, const uint16_t bitoffset) return ret; if (bios->major_version >= 0x60) /* g80+ */ parse_bit_table(bios, bitoffset, &BIT_TABLE('A', A)); + ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('C', C)); + if (ret) + return ret; parse_bit_table(bios, bitoffset, &BIT_TABLE('D', display)); ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('I', init)); if (ret) @@ -1175,6 +1228,8 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi */ bios->feature_byte = bmp[9]; + parse_bios_version(dev, bios, offset + 10); + if (bmp_version_major < 5 || bmp_version_minor < 0x10) bios->old_style_init = true; legacy_scripts_offset = 18; @@ -1221,10 +1276,8 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi bios->fp.lvdsmanufacturerpointer = ROM16(bmp[117]); bios->fp.fpxlatemanufacturertableptr = ROM16(bmp[119]); } -#if 0 if (bmplength > 143) bios->pll_limit_tbl_ptr = ROM16(bmp[142]); -#endif if (bmplength > 157) bios->fp.duallink_transition_clk = ROM16(bmp[156]) * 10; @@ -1469,7 +1522,6 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, } case DCB_OUTPUT_DP: entry->dpconf.sor.link = (conf & 0x00000030) >> 4; - entry->extdev = (conf & 0x0000ff00) >> 8; switch ((conf & 0x00e00000) >> 21) { case 0: entry->dpconf.link_bw = 162000; @@ -1491,10 +1543,8 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, } break; case DCB_OUTPUT_TMDS: - if (dcb->version >= 0x40) { + if (dcb->version >= 0x40) entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4; - entry->extdev = (conf & 0x0000ff00) >> 8; - } else if (dcb->version >= 0x30) entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8; else if (dcb->version >= 0x22) @@ -1887,9 +1937,9 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios) if (conn[0] != 0xff) { NV_INFO(drm, "DCB conn %02d: ", idx); if (olddcb_conntab(dev)[3] < 4) - pr_cont("%04x\n", ROM16(conn[0])); + printk("%04x\n", ROM16(conn[0])); else - pr_cont("%08x\n", ROM32(conn[0])); + printk("%08x\n", ROM32(conn[0])); } } dcb_fake_connectors(bios); @@ -2002,29 +2052,45 @@ uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev) static bool NVInitVBIOS(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_bios *bios = nouveau_bios(drm->device); - struct nvbios *legacy = &drm->vbios; - - memset(legacy, 0, sizeof(struct nvbios)); - spin_lock_init(&legacy->lock); - legacy->dev = dev; - - legacy->data = bios->data; - legacy->length = bios->size; - legacy->major_version = bios->version.major; - legacy->chip_version = bios->version.chip; - if (bios->bit_offset) { - legacy->type = NVBIOS_BIT; - legacy->offset = bios->bit_offset; - return !parse_bit_structure(legacy, legacy->offset + 6); - } else - if (bios->bmp_offset) { - legacy->type = NVBIOS_BMP; - legacy->offset = bios->bmp_offset; - return !parse_bmp_structure(dev, legacy, legacy->offset); - } + struct nvbios *bios = &drm->vbios; - return false; + memset(bios, 0, sizeof(struct nvbios)); + spin_lock_init(&bios->lock); + bios->dev = dev; + + bios->data = nouveau_bios(drm->device)->data; + bios->length = nouveau_bios(drm->device)->size; + return true; +} + +static int nouveau_parse_vbios_struct(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_drm(dev); + struct nvbios *bios = &drm->vbios; + const uint8_t bit_signature[] = { 0xff, 0xb8, 'B', 'I', 'T' }; + const uint8_t bmp_signature[] = { 0xff, 0x7f, 'N', 'V', 0x0 }; + int offset; + + offset = findstr(bios->data, bios->length, + bit_signature, sizeof(bit_signature)); + if (offset) { + NV_INFO(drm, "BIT BIOS found\n"); + bios->type = NVBIOS_BIT; + bios->offset = offset; + return parse_bit_structure(bios, offset + 6); + } + + offset = findstr(bios->data, bios->length, + bmp_signature, sizeof(bmp_signature)); + if (offset) { + NV_INFO(drm, "BMP BIOS found\n"); + bios->type = NVBIOS_BMP; + bios->offset = offset; + return parse_bmp_structure(dev, bios, offset); + } + + NV_ERROR(drm, "No known BIOS signature found\n"); + return -ENODEV; } int @@ -2080,6 +2146,10 @@ nouveau_bios_init(struct drm_device *dev) if (!NVInitVBIOS(dev)) return -ENODEV; + ret = nouveau_parse_vbios_struct(dev); + if (ret) + return ret; + ret = parse_dcb_table(dev, bios); if (ret) return ret; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_bios.h b/trunk/drivers/gpu/drm/nouveau/nouveau_bios.h index 7ccd28f11adf..f68c54ca422f 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -107,10 +107,20 @@ struct nvbios { bool old_style_init; uint16_t init_script_tbls_ptr; uint16_t extra_init_script_tbl_ptr; - + uint16_t macro_index_tbl_ptr; + uint16_t macro_tbl_ptr; + uint16_t condition_tbl_ptr; + uint16_t io_condition_tbl_ptr; + uint16_t io_flag_condition_tbl_ptr; + uint16_t init_function_tbl_ptr; + + uint16_t pll_limit_tbl_ptr; uint16_t ram_restrict_tbl_ptr; uint8_t ram_restrict_group_count; + uint16_t some_script_ptr; /* BIT I + 14 */ + uint16_t init96_tbl_ptr; /* BIT I + 16 */ + struct dcb_table dcb; struct { diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_bo.c b/trunk/drivers/gpu/drm/nouveau/nouveau_bo.c index 11ca82148edc..64d6e3047dee 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -28,7 +28,6 @@ */ #include -#include #include #include @@ -562,7 +561,7 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, struct nouveau_fence *fence = NULL; int ret; - ret = nouveau_fence_new(chan, false, &fence); + ret = nouveau_fence_new(chan, &fence); if (ret) return ret; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_chan.c b/trunk/drivers/gpu/drm/nouveau/nouveau_chan.c index eaa80a2b81ee..174300b6a02e 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -51,15 +51,14 @@ nouveau_channel_idle(struct nouveau_channel *chan) struct nouveau_fence *fence = NULL; int ret; - ret = nouveau_fence_new(chan, false, &fence); + ret = nouveau_fence_new(chan, &fence); if (!ret) { ret = nouveau_fence_wait(fence, false, false); nouveau_fence_unref(&fence); } if (ret) - NV_ERROR(cli, "failed to idle channel 0x%08x [%s]\n", - chan->handle, cli->base.name); + NV_ERROR(cli, "failed to idle channel 0x%08x\n", chan->handle); return ret; } diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_connector.c b/trunk/drivers/gpu/drm/nouveau/nouveau_connector.c index 4dd7ae2ac6c6..e620ba8271b4 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -55,6 +55,8 @@ MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (default: enabled)"); static int nouveau_duallink = 1; module_param_named(duallink, nouveau_duallink, int, 0400); +static void nouveau_connector_hotplug(void *, int); + struct nouveau_encoder * find_encoder(struct drm_connector *connector, int type) { @@ -98,6 +100,22 @@ static void nouveau_connector_destroy(struct drm_connector *connector) { struct nouveau_connector *nv_connector = nouveau_connector(connector); + struct nouveau_gpio *gpio; + struct nouveau_drm *drm; + struct drm_device *dev; + + if (!nv_connector) + return; + + dev = nv_connector->base.dev; + drm = nouveau_drm(dev); + gpio = nouveau_gpio(drm->device); + + if (gpio && nv_connector->hpd != DCB_GPIO_UNUSED) { + gpio->isr_del(gpio, 0, nv_connector->hpd, 0xff, + nouveau_connector_hotplug, connector); + } + kfree(nv_connector->edid); drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); @@ -112,6 +130,7 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_gpio *gpio = nouveau_gpio(drm->device); + struct nouveau_i2c *i2c = nouveau_i2c(drm->device); struct nouveau_i2c_port *port = NULL; int i, panel = -ENODEV; @@ -141,7 +160,8 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, continue; nv_encoder = nouveau_encoder(obj_to_encoder(obj)); - port = nv_encoder->i2c; + if (nv_encoder->dcb->i2c_index < 0xf) + port = i2c->find(i2c, nv_encoder->dcb->i2c_index); if (port && nv_probe_i2c(port, 0x50)) { *pnv_encoder = nv_encoder; break; @@ -379,10 +399,9 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) struct edid *edid = (struct edid *)nouveau_bios_embedded_edid(dev); if (edid) { - nv_connector->edid = - kmemdup(edid, EDID_LENGTH, GFP_KERNEL); - if (nv_connector->edid) - status = connector_status_connected; + nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL); + *(nv_connector->edid) = *edid; + status = connector_status_connected; } } @@ -892,37 +911,6 @@ nouveau_connector_funcs_lvds = { .force = nouveau_connector_force }; -static void -nouveau_connector_hotplug_work(struct work_struct *work) -{ - struct nouveau_connector *nv_connector = - container_of(work, struct nouveau_connector, hpd_work); - struct drm_connector *connector = &nv_connector->base; - struct drm_device *dev = connector->dev; - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_gpio *gpio = nouveau_gpio(drm->device); - bool plugged = gpio->get(gpio, 0, nv_connector->hpd.func, 0xff); - - NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", - drm_get_connector_name(connector)); - - if (plugged) - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); - else - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); - - drm_helper_hpd_irq_event(dev); -} - -static int -nouveau_connector_hotplug(struct nouveau_eventh *event, int index) -{ - struct nouveau_connector *nv_connector = - container_of(event, struct nouveau_connector, hpd_func); - schedule_work(&nv_connector->hpd_work); - return NVKM_EVENT_KEEP; -} - static int drm_conntype_from_dcb(enum dcb_connector_type dcb) { @@ -973,7 +961,6 @@ nouveau_connector_create(struct drm_device *dev, int index) return ERR_PTR(-ENOMEM); connector = &nv_connector->base; - INIT_WORK(&nv_connector->hpd_work, nouveau_connector_hotplug_work); nv_connector->index = index; /* attempt to parse vbios connector type and hotplug gpio */ @@ -988,11 +975,8 @@ nouveau_connector_create(struct drm_device *dev, int index) if (olddcb_conntab(dev)[3] >= 4) entry |= (u32)ROM16(nv_connector->dcb[2]) << 16; - ret = gpio->find(gpio, 0, hpd[ffs((entry & 0x07033000) >> 12)], - DCB_GPIO_UNUSED, &nv_connector->hpd); - nv_connector->hpd_func.func = nouveau_connector_hotplug; - if (ret) - nv_connector->hpd.func = DCB_GPIO_UNUSED; + nv_connector->hpd = ffs((entry & 0x07033000) >> 12); + nv_connector->hpd = hpd[nv_connector->hpd]; nv_connector->type = nv_connector->dcb[0]; if (drm_conntype_from_dcb(nv_connector->type) == @@ -1015,7 +999,7 @@ nouveau_connector_create(struct drm_device *dev, int index) } } else { nv_connector->type = DCB_CONNECTOR_NONE; - nv_connector->hpd.func = DCB_GPIO_UNUSED; + nv_connector->hpd = DCB_GPIO_UNUSED; } /* no vbios data, or an unknown dcb connector type - attempt to @@ -1142,9 +1126,31 @@ nouveau_connector_create(struct drm_device *dev, int index) } connector->polled = DRM_CONNECTOR_POLL_CONNECT; - if (nv_connector->hpd.func != DCB_GPIO_UNUSED) - connector->polled = DRM_CONNECTOR_POLL_HPD; + if (gpio && nv_connector->hpd != DCB_GPIO_UNUSED) { + ret = gpio->isr_add(gpio, 0, nv_connector->hpd, 0xff, + nouveau_connector_hotplug, connector); + if (ret == 0) + connector->polled = DRM_CONNECTOR_POLL_HPD; + } drm_sysfs_connector_add(connector); return connector; } + +static void +nouveau_connector_hotplug(void *data, int plugged) +{ + struct drm_connector *connector = data; + struct drm_device *dev = connector->dev; + struct nouveau_drm *drm = nouveau_drm(dev); + + NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", + drm_get_connector_name(connector)); + + if (plugged) + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + else + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + + drm_helper_hpd_irq_event(dev); +} diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_connector.h b/trunk/drivers/gpu/drm/nouveau/nouveau_connector.h index 6e399aad491a..20eb84cce9e6 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -30,11 +30,6 @@ #include #include "nouveau_crtc.h" -#include - -#include -#include - struct nouveau_i2c_port; enum nouveau_underscan_type { @@ -66,10 +61,7 @@ struct nouveau_connector { enum dcb_connector_type type; u8 index; u8 *dcb; - - struct dcb_gpio_func hpd; - struct work_struct hpd_work; - struct nouveau_eventh hpd_func; + u8 hpd; int dithering_mode; int dithering_depth; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/trunk/drivers/gpu/drm/nouveau/nouveau_debugfs.c deleted file mode 100644 index 5392e07edfc6..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_debugfs.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2009 Red Hat - * - * 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 THE COPYRIGHT OWNER(S) 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: - * Ben Skeggs - */ - -#include "nouveau_debugfs.h" -#include "nouveau_drm.h" - -static int -nouveau_debugfs_vbios_image(struct seq_file *m, void *data) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct nouveau_drm *drm = nouveau_drm(node->minor->dev); - int i; - - for (i = 0; i < drm->vbios.length; i++) - seq_printf(m, "%c", drm->vbios.data[i]); - return 0; -} - -static struct drm_info_list nouveau_debugfs_list[] = { - { "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL }, -}; -#define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list) - -int -nouveau_debugfs_init(struct drm_minor *minor) -{ - drm_debugfs_create_files(nouveau_debugfs_list, NOUVEAU_DEBUGFS_ENTRIES, - minor->debugfs_root, minor); - return 0; -} - -void -nouveau_debugfs_takedown(struct drm_minor *minor) -{ - drm_debugfs_remove_files(nouveau_debugfs_list, NOUVEAU_DEBUGFS_ENTRIES, - minor); -} diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_debugfs.h b/trunk/drivers/gpu/drm/nouveau/nouveau_debugfs.h deleted file mode 100644 index a62af6fb5f99..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_debugfs.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __NOUVEAU_DEBUGFS_H__ -#define __NOUVEAU_DEBUGFS_H__ - -#include - -#if defined(CONFIG_DEBUG_FS) -extern int nouveau_debugfs_init(struct drm_minor *); -extern void nouveau_debugfs_takedown(struct drm_minor *); -#else -static inline int -nouveau_debugfs_init(struct drm_minor *minor) -{ - return 0; -} - -static inline void nouveau_debugfs_takedown(struct drm_minor *minor) -{ -} - -#endif - -#endif diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_display.c b/trunk/drivers/gpu/drm/nouveau/nouveau_display.c index 4610c3a29bbe..d42c9e860c16 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_display.c @@ -41,8 +41,6 @@ #include #include -#include - static void nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) { @@ -233,10 +231,8 @@ nouveau_display_init(struct drm_device *dev) /* enable hotplug interrupts */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct nouveau_connector *conn = nouveau_connector(connector); - if (gpio && conn->hpd.func != DCB_GPIO_UNUSED) { - nouveau_event_get(gpio->events, conn->hpd.line, - &conn->hpd_func); - } + if (gpio) + gpio->irq(gpio, 0, conn->hpd, 0xff, true); } return ret; @@ -253,20 +249,37 @@ nouveau_display_fini(struct drm_device *dev) /* disable hotplug interrupts */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct nouveau_connector *conn = nouveau_connector(connector); - if (gpio && conn->hpd.func != DCB_GPIO_UNUSED) { - nouveau_event_put(gpio->events, conn->hpd.line, - &conn->hpd_func); - } + if (gpio) + gpio->irq(gpio, 0, conn->hpd, 0xff, false); } drm_kms_helper_poll_disable(dev); disp->fini(dev); } +static void +nouveau_display_vblank_notify(void *data, int crtc) +{ + drm_handle_vblank(data, crtc); +} + +static void +nouveau_display_vblank_get(void *data, int crtc) +{ + drm_vblank_get(data, crtc); +} + +static void +nouveau_display_vblank_put(void *data, int crtc) +{ + drm_vblank_put(data, crtc); +} + int nouveau_display_create(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_disp *pdisp = nouveau_disp(drm->device); struct nouveau_display *disp; u32 pclass = dev->pdev->class >> 8; int ret, gen; @@ -275,6 +288,11 @@ nouveau_display_create(struct drm_device *dev) if (!disp) return -ENOMEM; + pdisp->vblank.data = dev; + pdisp->vblank.notify = nouveau_display_vblank_notify; + pdisp->vblank.get = nouveau_display_vblank_get; + pdisp->vblank.put = nouveau_display_vblank_put; + drm_mode_config_init(dev); drm_mode_create_scaling_mode_property(dev); drm_mode_create_dvi_i_properties(dev); @@ -298,13 +316,17 @@ nouveau_display_create(struct drm_device *dev) drm_property_create_range(dev, 0, "underscan vborder", 0, 128); if (gen >= 1) { - /* -90..+90 */ disp->vibrant_hue_property = - drm_property_create_range(dev, 0, "vibrant hue", 0, 180); + drm_property_create(dev, DRM_MODE_PROP_RANGE, + "vibrant hue", 2); + disp->vibrant_hue_property->values[0] = 0; + disp->vibrant_hue_property->values[1] = 180; /* -90..+90 */ - /* -100..+100 */ disp->color_vibrance_property = - drm_property_create_range(dev, 0, "color vibrance", 0, 200); + drm_property_create(dev, DRM_MODE_PROP_RANGE, + "color vibrance", 2); + disp->color_vibrance_property->values[0] = 0; + disp->color_vibrance_property->values[1] = 200; /* -100..+100 */ } dev->mode_config.funcs = &nouveau_mode_config_funcs; @@ -456,6 +478,39 @@ nouveau_display_resume(struct drm_device *dev) } } +int +nouveau_vblank_enable(struct drm_device *dev, int crtc) +{ + struct nouveau_device *device = nouveau_dev(dev); + + if (device->card_type >= NV_D0) + nv_mask(device, 0x6100c0 + (crtc * 0x800), 1, 1); + else + if (device->card_type >= NV_50) + nv_mask(device, NV50_PDISPLAY_INTR_EN_1, 0, + NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc)); + else + NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, + NV_PCRTC_INTR_0_VBLANK); + + return 0; +} + +void +nouveau_vblank_disable(struct drm_device *dev, int crtc) +{ + struct nouveau_device *device = nouveau_dev(dev); + + if (device->card_type >= NV_D0) + nv_mask(device, 0x6100c0 + (crtc * 0x800), 1, 0); + else + if (device->card_type >= NV_50) + nv_mask(device, NV50_PDISPLAY_INTR_EN_1, + NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0); + else + NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0); +} + static int nouveau_page_flip_reserve(struct nouveau_bo *old_bo, struct nouveau_bo *new_bo) @@ -540,7 +595,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, } FIRE_RING (chan); - ret = nouveau_fence_new(chan, false, pfence); + ret = nouveau_fence_new(chan, pfence); if (ret) goto fail; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_display.h b/trunk/drivers/gpu/drm/nouveau/nouveau_display.h index 1ea3e4734b62..722548bb3bd3 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_display.h @@ -59,6 +59,9 @@ void nouveau_display_fini(struct drm_device *dev); int nouveau_display_suspend(struct drm_device *dev); void nouveau_display_resume(struct drm_device *dev); +int nouveau_vblank_enable(struct drm_device *dev, int crtc); +void nouveau_vblank_disable(struct drm_device *dev, int crtc); + int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_pending_vblank_event *event); int nouveau_finish_page_flip(struct nouveau_channel *, diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_dma.h b/trunk/drivers/gpu/drm/nouveau/nouveau_dma.h index 690d5930ce32..5c2e22932d1c 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_dma.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_dma.h @@ -191,7 +191,7 @@ WIND_RING(struct nouveau_channel *chan) #define NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG 0x00000002 #define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL 0x00000004 #define NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD 0x00001000 -#define NV84_SUBCHAN_UEVENT 0x00000020 +#define NV84_SUBCHAN_NOTIFY_INTR 0x00000020 #define NV84_SUBCHAN_WRCACHE_FLUSH 0x00000024 #define NV10_SUBCHAN_REF_CNT 0x00000050 #define NVSW_SUBCHAN_PAGE_FLIP 0x00000054 diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_dp.c b/trunk/drivers/gpu/drm/nouveau/nouveau_dp.c index 36fd22500569..59838651ee8f 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -35,6 +35,300 @@ #include #include +/****************************************************************************** + * link training + *****************************************************************************/ +struct dp_state { + struct nouveau_i2c_port *auxch; + struct nouveau_object *core; + struct dcb_output *dcb; + int crtc; + u8 *dpcd; + int link_nr; + u32 link_bw; + u8 stat[6]; + u8 conf[4]; +}; + +static void +dp_set_link_config(struct drm_device *dev, struct dp_state *dp) +{ + struct nouveau_drm *drm = nouveau_drm(dev); + struct dcb_output *dcb = dp->dcb; + const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); + const u32 moff = (dp->crtc << 3) | (link << 2) | or; + u8 sink[2]; + u32 data; + + NV_DEBUG(drm, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); + + /* set desired link configuration on the source */ + data = ((dp->link_bw / 27000) << 8) | dp->link_nr; + if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) + data |= NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH; + + nv_call(dp->core, NV94_DISP_SOR_DP_LNKCTL + moff, data); + + /* inform the sink of the new configuration */ + sink[0] = dp->link_bw / 27000; + sink[1] = dp->link_nr; + if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) + sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + + nv_wraux(dp->auxch, DP_LINK_BW_SET, sink, 2); +} + +static void +dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 pattern) +{ + struct nouveau_drm *drm = nouveau_drm(dev); + struct dcb_output *dcb = dp->dcb; + const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); + const u32 moff = (dp->crtc << 3) | (link << 2) | or; + u8 sink_tp; + + NV_DEBUG(drm, "training pattern %d\n", pattern); + + nv_call(dp->core, NV94_DISP_SOR_DP_TRAIN + moff, pattern); + + nv_rdaux(dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1); + sink_tp &= ~DP_TRAINING_PATTERN_MASK; + sink_tp |= pattern; + nv_wraux(dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1); +} + +static int +dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) +{ + struct nouveau_drm *drm = nouveau_drm(dev); + struct dcb_output *dcb = dp->dcb; + const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); + const u32 moff = (dp->crtc << 3) | (link << 2) | or; + int i; + + for (i = 0; i < dp->link_nr; i++) { + u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; + u8 lpre = (lane & 0x0c) >> 2; + u8 lvsw = (lane & 0x03) >> 0; + + dp->conf[i] = (lpre << 3) | lvsw; + if (lvsw == DP_TRAIN_VOLTAGE_SWING_1200) + dp->conf[i] |= DP_TRAIN_MAX_SWING_REACHED; + if ((lpre << 3) == DP_TRAIN_PRE_EMPHASIS_9_5) + dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + + NV_DEBUG(drm, "config lane %d %02x\n", i, dp->conf[i]); + + nv_call(dp->core, NV94_DISP_SOR_DP_DRVCTL(i) + moff, (lvsw << 8) | lpre); + } + + return nv_wraux(dp->auxch, DP_TRAINING_LANE0_SET, dp->conf, 4); +} + +static int +dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay) +{ + struct nouveau_drm *drm = nouveau_drm(dev); + int ret; + + udelay(delay); + + ret = nv_rdaux(dp->auxch, DP_LANE0_1_STATUS, dp->stat, 6); + if (ret) + return ret; + + NV_DEBUG(drm, "status %*ph\n", 6, dp->stat); + return 0; +} + +static int +dp_link_train_cr(struct drm_device *dev, struct dp_state *dp) +{ + bool cr_done = false, abort = false; + int voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK; + int tries = 0, i; + + dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_1); + + do { + if (dp_link_train_commit(dev, dp) || + dp_link_train_update(dev, dp, 100)) + break; + + cr_done = true; + for (i = 0; i < dp->link_nr; i++) { + u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; + if (!(lane & DP_LANE_CR_DONE)) { + cr_done = false; + if (dp->conf[i] & DP_TRAIN_MAX_SWING_REACHED) + abort = true; + break; + } + } + + if ((dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { + voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK; + tries = 0; + } + } while (!cr_done && !abort && ++tries < 5); + + return cr_done ? 0 : -1; +} + +static int +dp_link_train_eq(struct drm_device *dev, struct dp_state *dp) +{ + bool eq_done, cr_done = true; + int tries = 0, i; + + dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_2); + + do { + if (dp_link_train_update(dev, dp, 400)) + break; + + eq_done = !!(dp->stat[2] & DP_INTERLANE_ALIGN_DONE); + for (i = 0; i < dp->link_nr && eq_done; i++) { + u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; + if (!(lane & DP_LANE_CR_DONE)) + cr_done = false; + if (!(lane & DP_LANE_CHANNEL_EQ_DONE) || + !(lane & DP_LANE_SYMBOL_LOCKED)) + eq_done = false; + } + + if (dp_link_train_commit(dev, dp)) + break; + } while (!eq_done && cr_done && ++tries <= 5); + + return eq_done ? 0 : -1; +} + +static void +dp_link_train_init(struct drm_device *dev, struct dp_state *dp, bool spread) +{ + struct dcb_output *dcb = dp->dcb; + const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); + const u32 moff = (dp->crtc << 3) | (link << 2) | or; + + nv_call(dp->core, NV94_DISP_SOR_DP_TRAIN + moff, (spread ? + NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON : + NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_OFF) | + NV94_DISP_SOR_DP_TRAIN_OP_INIT); +} + +static void +dp_link_train_fini(struct drm_device *dev, struct dp_state *dp) +{ + struct dcb_output *dcb = dp->dcb; + const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); + const u32 moff = (dp->crtc << 3) | (link << 2) | or; + + nv_call(dp->core, NV94_DISP_SOR_DP_TRAIN + moff, + NV94_DISP_SOR_DP_TRAIN_OP_FINI); +} + +static bool +nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate, + struct nouveau_object *core) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); + struct nouveau_connector *nv_connector = + nouveau_encoder_connector_get(nv_encoder); + struct drm_device *dev = encoder->dev; + struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_i2c *i2c = nouveau_i2c(drm->device); + struct nouveau_gpio *gpio = nouveau_gpio(drm->device); + const u32 bw_list[] = { 270000, 162000, 0 }; + const u32 *link_bw = bw_list; + struct dp_state dp; + + dp.auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index); + if (!dp.auxch) + return false; + + dp.core = core; + dp.dcb = nv_encoder->dcb; + dp.crtc = nv_crtc->index; + dp.dpcd = nv_encoder->dp.dpcd; + + /* adjust required bandwidth for 8B/10B coding overhead */ + datarate = (datarate / 8) * 10; + + /* some sinks toggle hotplug in response to some of the actions + * we take during link training (DP_SET_POWER is one), we need + * to ignore them for the moment to avoid races. + */ + gpio->irq(gpio, 0, nv_connector->hpd, 0xff, false); + + /* enable down-spreading and execute pre-train script from vbios */ + dp_link_train_init(dev, &dp, nv_encoder->dp.dpcd[3] & 1); + + /* start off at highest link rate supported by encoder and display */ + while (*link_bw > nv_encoder->dp.link_bw) + link_bw++; + + while (link_bw[0]) { + /* find minimum required lane count at this link rate */ + dp.link_nr = nv_encoder->dp.link_nr; + while ((dp.link_nr >> 1) * link_bw[0] > datarate) + dp.link_nr >>= 1; + + /* drop link rate to minimum with this lane count */ + while ((link_bw[1] * dp.link_nr) > datarate) + link_bw++; + dp.link_bw = link_bw[0]; + + /* program selected link configuration */ + dp_set_link_config(dev, &dp); + + /* attempt to train the link at this configuration */ + memset(dp.stat, 0x00, sizeof(dp.stat)); + if (!dp_link_train_cr(dev, &dp) && + !dp_link_train_eq(dev, &dp)) + break; + + /* retry at lower rate */ + link_bw++; + } + + /* finish link training */ + dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE); + + /* execute post-train script from vbios */ + dp_link_train_fini(dev, &dp); + + /* re-enable hotplug detect */ + gpio->irq(gpio, 0, nv_connector->hpd, 0xff, true); + return true; +} + +void +nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate, + struct nouveau_object *core) +{ + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + struct nouveau_drm *drm = nouveau_drm(encoder->dev); + struct nouveau_i2c *i2c = nouveau_i2c(drm->device); + struct nouveau_i2c_port *auxch; + u8 status; + + auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index); + if (!auxch) + return; + + if (mode == DRM_MODE_DPMS_ON) + status = DP_SET_POWER_D0; + else + status = DP_SET_POWER_D3; + + nv_wraux(auxch, DP_SET_POWER, &status, 1); + + if (mode == DRM_MODE_DPMS_ON) + nouveau_dp_link_train(encoder, datarate, core); +} + static void nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch, u8 *dpcd) @@ -61,11 +355,12 @@ nouveau_dp_detect(struct drm_encoder *encoder) struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct drm_device *dev = encoder->dev; struct nouveau_drm *drm = nouveau_drm(dev); + struct nouveau_i2c *i2c = nouveau_i2c(drm->device); struct nouveau_i2c_port *auxch; u8 *dpcd = nv_encoder->dp.dpcd; int ret; - auxch = nv_encoder->i2c; + auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index); if (!auxch) return false; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_drm.c b/trunk/drivers/gpu/drm/nouveau/nouveau_drm.c index 8a03c58ae988..8e8e8ce75528 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -34,8 +34,6 @@ #include #include -#include - #include "nouveau_drm.h" #include "nouveau_irq.h" #include "nouveau_dma.h" @@ -50,7 +48,6 @@ #include "nouveau_abi16.h" #include "nouveau_fbcon.h" #include "nouveau_fence.h" -#include "nouveau_debugfs.h" MODULE_PARM_DESC(config, "option string to pass to driver core"); static char *nouveau_config; @@ -71,32 +68,6 @@ module_param_named(modeset, nouveau_modeset, int, 0400); static struct drm_driver driver; -static int -nouveau_drm_vblank_enable(struct drm_device *dev, int head) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_disp *pdisp = nouveau_disp(drm->device); - nouveau_event_get(pdisp->vblank, head, &drm->vblank); - return 0; -} - -static void -nouveau_drm_vblank_disable(struct drm_device *dev, int head) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_disp *pdisp = nouveau_disp(drm->device); - nouveau_event_put(pdisp->vblank, head, &drm->vblank); -} - -static int -nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head) -{ - struct nouveau_drm *drm = - container_of(event, struct nouveau_drm, vblank); - drm_handle_vblank(drm->dev, head); - return NVKM_EVENT_KEEP; -} - static u64 nouveau_name(struct pci_dev *pdev) { @@ -161,8 +132,7 @@ nouveau_accel_init(struct nouveau_drm *drm) /* initialise synchronisation routines */ if (device->card_type < NV_10) ret = nv04_fence_create(drm); - else if (device->chipset < 0x17) ret = nv10_fence_create(drm); - else if (device->card_type < NV_50) ret = nv17_fence_create(drm); + else if (device->card_type < NV_50) ret = nv10_fence_create(drm); else if (device->chipset < 0x84) ret = nv50_fence_create(drm); else if (device->card_type < NV_C0) ret = nv84_fence_create(drm); else ret = nvc0_fence_create(drm); @@ -289,7 +259,6 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) dev->dev_private = drm; drm->dev = dev; - drm->vblank.func = nouveau_drm_vblank_handler; INIT_LIST_HEAD(&drm->clients); spin_lock_init(&drm->tile.lock); @@ -429,7 +398,7 @@ nouveau_drm_remove(struct pci_dev *pdev) nouveau_object_debug(); } -static int +int nouveau_do_suspend(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); @@ -500,7 +469,7 @@ int nouveau_pmops_suspend(struct device *dev) return 0; } -static int +int nouveau_do_resume(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); @@ -574,11 +543,10 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) struct pci_dev *pdev = dev->pdev; struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_cli *cli; - char name[32], tmpname[TASK_COMM_LEN]; + char name[16]; int ret; - get_task_comm(tmpname, current); - snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid)); + snprintf(name, sizeof(name), "%d", pid_nr(fpriv->pid)); ret = nouveau_cli_create(pdev, name, sizeof(*cli), (void **)&cli); if (ret) @@ -668,19 +636,14 @@ driver = { .postclose = nouveau_drm_postclose, .lastclose = nouveau_vga_lastclose, -#if defined(CONFIG_DEBUG_FS) - .debugfs_init = nouveau_debugfs_init, - .debugfs_cleanup = nouveau_debugfs_takedown, -#endif - .irq_preinstall = nouveau_irq_preinstall, .irq_postinstall = nouveau_irq_postinstall, .irq_uninstall = nouveau_irq_uninstall, .irq_handler = nouveau_irq_handler, .get_vblank_counter = drm_vblank_count, - .enable_vblank = nouveau_drm_vblank_enable, - .disable_vblank = nouveau_drm_vblank_disable, + .enable_vblank = nouveau_vblank_enable, + .disable_vblank = nouveau_vblank_disable, .ioctls = nouveau_ioctls, .fops = &nouveau_driver_fops, diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_drm.h b/trunk/drivers/gpu/drm/nouveau/nouveau_drm.h index b25df374c901..aa89eb938b47 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -13,7 +13,6 @@ #define DRIVER_PATCHLEVEL 0 #include -#include #include @@ -113,7 +112,6 @@ struct nouveau_drm { struct nvbios vbios; struct nouveau_display *display; struct backlight_device *backlight; - struct nouveau_eventh vblank; /* power management */ struct nouveau_pm *pm; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_encoder.h b/trunk/drivers/gpu/drm/nouveau/nouveau_encoder.h index e24341229d5e..d0d95bd511ab 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -36,12 +36,19 @@ struct nouveau_i2c_port; +struct dp_train_func { + void (*link_set)(struct drm_device *, struct dcb_output *, int crtc, + int nr, u32 bw, bool enhframe); + void (*train_set)(struct drm_device *, struct dcb_output *, u8 pattern); + void (*train_adj)(struct drm_device *, struct dcb_output *, + u8 lane, u8 swing, u8 preem); +}; + struct nouveau_encoder { struct drm_encoder_slave base; struct dcb_output *dcb; int or; - struct nouveau_i2c_port *i2c; /* different to drm_encoder.crtc, this reflects what's * actually programmed on the hw, not the proposed crtc */ diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/trunk/drivers/gpu/drm/nouveau/nouveau_fbcon.c index b03531781580..d4ecb4deb484 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -251,10 +251,9 @@ nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *fbcon) } static int -nouveau_fbcon_create(struct drm_fb_helper *helper, +nouveau_fbcon_create(struct nouveau_fbdev *fbcon, struct drm_fb_helper_surface_size *sizes) { - struct nouveau_fbdev *fbcon = (struct nouveau_fbdev *)helper; struct drm_device *dev = fbcon->dev; struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_device *device = nv_device(drm->device); @@ -389,6 +388,23 @@ nouveau_fbcon_create(struct drm_fb_helper *helper, return ret; } +static int +nouveau_fbcon_find_or_create_single(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + struct nouveau_fbdev *fbcon = (struct nouveau_fbdev *)helper; + int new_fb = 0; + int ret; + + if (!helper->fb) { + ret = nouveau_fbcon_create(fbcon, sizes); + if (ret) + return ret; + new_fb = 1; + } + return new_fb; +} + void nouveau_fbcon_output_poll_changed(struct drm_device *dev) { @@ -434,7 +450,7 @@ void nouveau_fbcon_gpu_lockup(struct fb_info *info) static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = { .gamma_set = nouveau_fbcon_gamma_set, .gamma_get = nouveau_fbcon_gamma_get, - .fb_probe = nouveau_fbcon_create, + .fb_probe = nouveau_fbcon_find_or_create_single, }; @@ -475,9 +491,6 @@ nouveau_fbcon_init(struct drm_device *dev) else preferred_bpp = 32; - /* disable all the possible outputs/crtcs before entering KMS mode */ - drm_helper_disable_unused_functions(dev); - drm_fb_helper_initial_config(&fbcon->helper, preferred_bpp); return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_fence.c b/trunk/drivers/gpu/drm/nouveau/nouveau_fence.c index 6c946837a0aa..1d049be79f74 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -33,14 +33,14 @@ #include "nouveau_dma.h" #include "nouveau_fence.h" -#include - void nouveau_fence_context_del(struct nouveau_fence_chan *fctx) { struct nouveau_fence *fence, *fnext; spin_lock(&fctx->lock); list_for_each_entry_safe(fence, fnext, &fctx->pending, head) { + if (fence->work) + fence->work(fence->priv, false); fence->channel = NULL; list_del(&fence->head); nouveau_fence_unref(&fence); @@ -59,14 +59,17 @@ nouveau_fence_context_new(struct nouveau_fence_chan *fctx) static void nouveau_fence_update(struct nouveau_channel *chan) { + struct nouveau_fence_priv *priv = chan->drm->fence; struct nouveau_fence_chan *fctx = chan->fence; struct nouveau_fence *fence, *fnext; spin_lock(&fctx->lock); list_for_each_entry_safe(fence, fnext, &fctx->pending, head) { - if (fctx->read(chan) < fence->sequence) + if (priv->read(chan) < fence->sequence) break; + if (fence->work) + fence->work(fence->priv, true); fence->channel = NULL; list_del(&fence->head); nouveau_fence_unref(&fence); @@ -77,6 +80,7 @@ nouveau_fence_update(struct nouveau_channel *chan) int nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) { + struct nouveau_fence_priv *priv = chan->drm->fence; struct nouveau_fence_chan *fctx = chan->fence; int ret; @@ -84,7 +88,7 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) fence->timeout = jiffies + (3 * DRM_HZ); fence->sequence = ++fctx->sequence; - ret = fctx->emit(fence); + ret = priv->emit(fence); if (!ret) { kref_get(&fence->kref); spin_lock(&fctx->lock); @@ -103,87 +107,13 @@ nouveau_fence_done(struct nouveau_fence *fence) return !fence->channel; } -struct nouveau_fence_uevent { - struct nouveau_eventh handler; - struct nouveau_fence_priv *priv; -}; - -static int -nouveau_fence_wait_uevent_handler(struct nouveau_eventh *event, int index) -{ - struct nouveau_fence_uevent *uevent = - container_of(event, struct nouveau_fence_uevent, handler); - wake_up_all(&uevent->priv->waiting); - return NVKM_EVENT_KEEP; -} - -static int -nouveau_fence_wait_uevent(struct nouveau_fence *fence, bool intr) - -{ - struct nouveau_channel *chan = fence->channel; - struct nouveau_fifo *pfifo = nouveau_fifo(chan->drm->device); - struct nouveau_fence_priv *priv = chan->drm->fence; - struct nouveau_fence_uevent uevent = { - .handler.func = nouveau_fence_wait_uevent_handler, - .priv = priv, - }; - int ret = 0; - - nouveau_event_get(pfifo->uevent, 0, &uevent.handler); - - if (fence->timeout) { - unsigned long timeout = fence->timeout - jiffies; - - if (time_before(jiffies, fence->timeout)) { - if (intr) { - ret = wait_event_interruptible_timeout( - priv->waiting, - nouveau_fence_done(fence), - timeout); - } else { - ret = wait_event_timeout(priv->waiting, - nouveau_fence_done(fence), - timeout); - } - } - - if (ret >= 0) { - fence->timeout = jiffies + ret; - if (time_after_eq(jiffies, fence->timeout)) - ret = -EBUSY; - } - } else { - if (intr) { - ret = wait_event_interruptible(priv->waiting, - nouveau_fence_done(fence)); - } else { - wait_event(priv->waiting, nouveau_fence_done(fence)); - } - } - - nouveau_event_put(pfifo->uevent, 0, &uevent.handler); - if (unlikely(ret < 0)) - return ret; - - return 0; -} - int nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr) { - struct nouveau_channel *chan = fence->channel; - struct nouveau_fence_priv *priv = chan ? chan->drm->fence : NULL; unsigned long sleep_time = NSEC_PER_MSEC / 1000; ktime_t t; int ret = 0; - while (priv && priv->uevent && lazy && !nouveau_fence_done(fence)) { - ret = nouveau_fence_wait_uevent(fence, intr); - if (ret < 0) - return ret; - } - while (!nouveau_fence_done(fence)) { if (fence->timeout && time_after_eq(jiffies, fence->timeout)) { ret = -EBUSY; @@ -213,14 +143,14 @@ nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr) int nouveau_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *chan) { - struct nouveau_fence_chan *fctx = chan->fence; + struct nouveau_fence_priv *priv = chan->drm->fence; struct nouveau_channel *prev; int ret = 0; prev = fence ? fence->channel : NULL; if (prev) { if (unlikely(prev != chan && !nouveau_fence_done(fence))) { - ret = fctx->sync(fence, prev, chan); + ret = priv->sync(fence, prev, chan); if (unlikely(ret)) ret = nouveau_fence_wait(fence, true, false); } @@ -252,8 +182,7 @@ nouveau_fence_ref(struct nouveau_fence *fence) } int -nouveau_fence_new(struct nouveau_channel *chan, bool sysmem, - struct nouveau_fence **pfence) +nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence) { struct nouveau_fence *fence; int ret = 0; @@ -264,13 +193,13 @@ nouveau_fence_new(struct nouveau_channel *chan, bool sysmem, fence = kzalloc(sizeof(*fence), GFP_KERNEL); if (!fence) return -ENOMEM; - - fence->sysmem = sysmem; kref_init(&fence->kref); - ret = nouveau_fence_emit(fence, chan); - if (ret) - nouveau_fence_unref(&fence); + if (chan) { + ret = nouveau_fence_emit(fence, chan); + if (ret) + nouveau_fence_unref(&fence); + } *pfence = fence; return ret; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_fence.h b/trunk/drivers/gpu/drm/nouveau/nouveau_fence.h index c89943407b52..cdb83acdffe2 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -7,15 +7,15 @@ struct nouveau_fence { struct list_head head; struct kref kref; - bool sysmem; - struct nouveau_channel *channel; unsigned long timeout; u32 sequence; + + void (*work)(void *priv, bool signalled); + void *priv; }; -int nouveau_fence_new(struct nouveau_channel *, bool sysmem, - struct nouveau_fence **); +int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **); struct nouveau_fence * nouveau_fence_ref(struct nouveau_fence *); void nouveau_fence_unref(struct nouveau_fence **); @@ -29,13 +29,6 @@ struct nouveau_fence_chan { struct list_head pending; struct list_head flip; - int (*emit)(struct nouveau_fence *); - int (*sync)(struct nouveau_fence *, struct nouveau_channel *, - struct nouveau_channel *); - u32 (*read)(struct nouveau_channel *); - int (*emit32)(struct nouveau_channel *, u64, u32); - int (*sync32)(struct nouveau_channel *, u64, u32); - spinlock_t lock; u32 sequence; }; @@ -46,9 +39,10 @@ struct nouveau_fence_priv { void (*resume)(struct nouveau_drm *); int (*context_new)(struct nouveau_channel *); void (*context_del)(struct nouveau_channel *); - - wait_queue_head_t waiting; - bool uevent; + int (*emit)(struct nouveau_fence *); + int (*sync)(struct nouveau_fence *, struct nouveau_channel *, + struct nouveau_channel *); + u32 (*read)(struct nouveau_channel *); }; #define nouveau_fence(drm) ((struct nouveau_fence_priv *)(drm)->fence) @@ -66,31 +60,13 @@ u32 nv10_fence_read(struct nouveau_channel *); void nv10_fence_context_del(struct nouveau_channel *); void nv10_fence_destroy(struct nouveau_drm *); int nv10_fence_create(struct nouveau_drm *); - -int nv17_fence_create(struct nouveau_drm *); void nv17_fence_resume(struct nouveau_drm *drm); int nv50_fence_create(struct nouveau_drm *); int nv84_fence_create(struct nouveau_drm *); int nvc0_fence_create(struct nouveau_drm *); +u64 nvc0_fence_crtc(struct nouveau_channel *, int crtc); int nouveau_flip_complete(void *chan); -struct nv84_fence_chan { - struct nouveau_fence_chan base; - struct nouveau_vma vma; - struct nouveau_vma vma_gart; - struct nouveau_vma dispc_vma[4]; -}; - -struct nv84_fence_priv { - struct nouveau_fence_priv base; - struct nouveau_bo *bo; - struct nouveau_bo *bo_gart; - u32 *suspend; -}; - -u64 nv84_fence_crtc(struct nouveau_channel *, int); -int nv84_fence_context_new(struct nouveau_channel *); - #endif diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_gem.c b/trunk/drivers/gpu/drm/nouveau/nouveau_gem.c index b4b4d0c1f4af..d98bee012cab 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -203,7 +203,6 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_fb *pfb = nouveau_fb(drm->device); struct drm_nouveau_gem_new *req = data; struct nouveau_bo *nvbo = NULL; @@ -212,7 +211,7 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, drm->ttm.bdev.dev_mapping = drm->dev->dev_mapping; if (!pfb->memtype_valid(pfb, req->info.tile_flags)) { - NV_ERROR(cli, "bad page flags: 0x%08x\n", req->info.tile_flags); + NV_ERROR(drm, "bad page flags: 0x%08x\n", req->info.tile_flags); return -EINVAL; } @@ -314,7 +313,6 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv, struct drm_nouveau_gem_pushbuf_bo *pbbo, int nr_buffers, struct validate_op *op) { - struct nouveau_cli *cli = nouveau_cli(file_priv); struct drm_device *dev = chan->drm->dev; struct nouveau_drm *drm = nouveau_drm(dev); uint32_t sequence; @@ -325,7 +323,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv, sequence = atomic_add_return(1, &drm->ttm.validate_sequence); retry: if (++trycnt > 100000) { - NV_ERROR(cli, "%s failed and gave up.\n", __func__); + NV_ERROR(drm, "%s failed and gave up.\n", __func__); return -EINVAL; } @@ -336,7 +334,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv, gem = drm_gem_object_lookup(dev, file_priv, b->handle); if (!gem) { - NV_ERROR(cli, "Unknown handle 0x%08x\n", b->handle); + NV_ERROR(drm, "Unknown handle 0x%08x\n", b->handle); validate_fini(op, NULL); return -ENOENT; } @@ -348,7 +346,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv, } if (nvbo->reserved_by && nvbo->reserved_by == file_priv) { - NV_ERROR(cli, "multiple instances of buffer %d on " + NV_ERROR(drm, "multiple instances of buffer %d on " "validation list\n", b->handle); drm_gem_object_unreference_unlocked(gem); validate_fini(op, NULL); @@ -368,7 +366,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv, if (unlikely(ret)) { drm_gem_object_unreference_unlocked(gem); if (ret != -ERESTARTSYS) - NV_ERROR(cli, "fail reserve\n"); + NV_ERROR(drm, "fail reserve\n"); return ret; } } @@ -386,7 +384,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv, if (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART) list_add_tail(&nvbo->entry, &op->gart_list); else { - NV_ERROR(cli, "invalid valid domains: 0x%08x\n", + NV_ERROR(drm, "invalid valid domains: 0x%08x\n", b->valid_domains); list_add_tail(&nvbo->entry, &op->both_list); validate_fini(op, NULL); @@ -419,9 +417,8 @@ validate_sync(struct nouveau_channel *chan, struct nouveau_bo *nvbo) } static int -validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, - struct list_head *list, struct drm_nouveau_gem_pushbuf_bo *pbbo, - uint64_t user_pbbo_ptr) +validate_list(struct nouveau_channel *chan, struct list_head *list, + struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr) { struct nouveau_drm *drm = chan->drm; struct drm_nouveau_gem_pushbuf_bo __user *upbbo = @@ -434,7 +431,7 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, ret = validate_sync(chan, nvbo); if (unlikely(ret)) { - NV_ERROR(cli, "fail pre-validate sync\n"); + NV_ERROR(drm, "fail pre-validate sync\n"); return ret; } @@ -442,20 +439,20 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, b->write_domains, b->valid_domains); if (unlikely(ret)) { - NV_ERROR(cli, "fail set_domain\n"); + NV_ERROR(drm, "fail set_domain\n"); return ret; } ret = nouveau_bo_validate(nvbo, true, false); if (unlikely(ret)) { if (ret != -ERESTARTSYS) - NV_ERROR(cli, "fail ttm_validate\n"); + NV_ERROR(drm, "fail ttm_validate\n"); return ret; } ret = validate_sync(chan, nvbo); if (unlikely(ret)) { - NV_ERROR(cli, "fail post-validate sync\n"); + NV_ERROR(drm, "fail post-validate sync\n"); return ret; } @@ -491,7 +488,7 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, uint64_t user_buffers, int nr_buffers, struct validate_op *op, int *apply_relocs) { - struct nouveau_cli *cli = nouveau_cli(file_priv); + struct nouveau_drm *drm = chan->drm; int ret, relocs = 0; INIT_LIST_HEAD(&op->vram_list); @@ -504,32 +501,32 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, ret = validate_init(chan, file_priv, pbbo, nr_buffers, op); if (unlikely(ret)) { if (ret != -ERESTARTSYS) - NV_ERROR(cli, "validate_init\n"); + NV_ERROR(drm, "validate_init\n"); return ret; } - ret = validate_list(chan, cli, &op->vram_list, pbbo, user_buffers); + ret = validate_list(chan, &op->vram_list, pbbo, user_buffers); if (unlikely(ret < 0)) { if (ret != -ERESTARTSYS) - NV_ERROR(cli, "validate vram_list\n"); + NV_ERROR(drm, "validate vram_list\n"); validate_fini(op, NULL); return ret; } relocs += ret; - ret = validate_list(chan, cli, &op->gart_list, pbbo, user_buffers); + ret = validate_list(chan, &op->gart_list, pbbo, user_buffers); if (unlikely(ret < 0)) { if (ret != -ERESTARTSYS) - NV_ERROR(cli, "validate gart_list\n"); + NV_ERROR(drm, "validate gart_list\n"); validate_fini(op, NULL); return ret; } relocs += ret; - ret = validate_list(chan, cli, &op->both_list, pbbo, user_buffers); + ret = validate_list(chan, &op->both_list, pbbo, user_buffers); if (unlikely(ret < 0)) { if (ret != -ERESTARTSYS) - NV_ERROR(cli, "validate both_list\n"); + NV_ERROR(drm, "validate both_list\n"); validate_fini(op, NULL); return ret; } @@ -558,10 +555,11 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size) } static int -nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, +nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev, struct drm_nouveau_gem_pushbuf *req, struct drm_nouveau_gem_pushbuf_bo *bo) { + struct nouveau_drm *drm = nouveau_drm(dev); struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL; int ret = 0; unsigned i; @@ -577,7 +575,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, uint32_t data; if (unlikely(r->bo_index > req->nr_buffers)) { - NV_ERROR(cli, "reloc bo index invalid\n"); + NV_ERROR(drm, "reloc bo index invalid\n"); ret = -EINVAL; break; } @@ -587,7 +585,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, continue; if (unlikely(r->reloc_bo_index > req->nr_buffers)) { - NV_ERROR(cli, "reloc container bo index invalid\n"); + NV_ERROR(drm, "reloc container bo index invalid\n"); ret = -EINVAL; break; } @@ -595,7 +593,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, if (unlikely(r->reloc_bo_offset + 4 > nvbo->bo.mem.num_pages << PAGE_SHIFT)) { - NV_ERROR(cli, "reloc outside of bo\n"); + NV_ERROR(drm, "reloc outside of bo\n"); ret = -EINVAL; break; } @@ -604,7 +602,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages, &nvbo->kmap); if (ret) { - NV_ERROR(cli, "failed kmap for reloc\n"); + NV_ERROR(drm, "failed kmap for reloc\n"); break; } nvbo->validate_mapped = true; @@ -629,7 +627,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, ret = ttm_bo_wait(&nvbo->bo, false, false, false); spin_unlock(&nvbo->bo.bdev->fence_lock); if (ret) { - NV_ERROR(cli, "reloc wait_idle failed: %d\n", ret); + NV_ERROR(drm, "reloc wait_idle failed: %d\n", ret); break; } @@ -645,7 +643,6 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); - struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_abi16_chan *temp; struct nouveau_drm *drm = nouveau_drm(dev); struct drm_nouveau_gem_pushbuf *req = data; @@ -675,19 +672,19 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, goto out_next; if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) { - NV_ERROR(cli, "pushbuf push count exceeds limit: %d max %d\n", + NV_ERROR(drm, "pushbuf push count exceeds limit: %d max %d\n", req->nr_push, NOUVEAU_GEM_MAX_PUSH); return nouveau_abi16_put(abi16, -EINVAL); } if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) { - NV_ERROR(cli, "pushbuf bo count exceeds limit: %d max %d\n", + NV_ERROR(drm, "pushbuf bo count exceeds limit: %d max %d\n", req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS); return nouveau_abi16_put(abi16, -EINVAL); } if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) { - NV_ERROR(cli, "pushbuf reloc count exceeds limit: %d max %d\n", + NV_ERROR(drm, "pushbuf reloc count exceeds limit: %d max %d\n", req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS); return nouveau_abi16_put(abi16, -EINVAL); } @@ -705,7 +702,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, /* Ensure all push buffers are on validate list */ for (i = 0; i < req->nr_push; i++) { if (push[i].bo_index >= req->nr_buffers) { - NV_ERROR(cli, "push %d buffer not in list\n", i); + NV_ERROR(drm, "push %d buffer not in list\n", i); ret = -EINVAL; goto out_prevalid; } @@ -716,15 +713,15 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, req->nr_buffers, &op, &do_reloc); if (ret) { if (ret != -ERESTARTSYS) - NV_ERROR(cli, "validate: %d\n", ret); + NV_ERROR(drm, "validate: %d\n", ret); goto out_prevalid; } /* Apply any relocations that are required */ if (do_reloc) { - ret = nouveau_gem_pushbuf_reloc_apply(cli, req, bo); + ret = nouveau_gem_pushbuf_reloc_apply(dev, req, bo); if (ret) { - NV_ERROR(cli, "reloc apply: %d\n", ret); + NV_ERROR(drm, "reloc apply: %d\n", ret); goto out; } } @@ -732,7 +729,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, if (chan->dma.ib_max) { ret = nouveau_dma_wait(chan, req->nr_push + 1, 16); if (ret) { - NV_ERROR(cli, "nv50cal_space: %d\n", ret); + NV_ERROR(drm, "nv50cal_space: %d\n", ret); goto out; } @@ -747,7 +744,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, if (nv_device(drm->device)->chipset >= 0x25) { ret = RING_SPACE(chan, req->nr_push * 2); if (ret) { - NV_ERROR(cli, "cal_space: %d\n", ret); + NV_ERROR(drm, "cal_space: %d\n", ret); goto out; } @@ -761,7 +758,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, } else { ret = RING_SPACE(chan, req->nr_push * (2 + NOUVEAU_DMA_SKIPS)); if (ret) { - NV_ERROR(cli, "jmp_space: %d\n", ret); + NV_ERROR(drm, "jmp_space: %d\n", ret); goto out; } @@ -797,9 +794,9 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, } } - ret = nouveau_fence_new(chan, false, &fence); + ret = nouveau_fence_new(chan, &fence); if (ret) { - NV_ERROR(cli, "error fencing pushbuf: %d\n", ret); + NV_ERROR(drm, "error fencing pushbuf: %d\n", ret); WIND_RING(chan); goto out; } diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_pm.c b/trunk/drivers/gpu/drm/nouveau/nouveau_pm.c index bb54098c6d97..a701ff5ffa5b 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -408,81 +408,6 @@ nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp, NULL, 0); -static ssize_t -nouveau_hwmon_show_temp1_auto_point1_pwm(struct device *d, - struct device_attribute *a, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", 100); -} -static SENSOR_DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO, - nouveau_hwmon_show_temp1_auto_point1_pwm, NULL, 0); - -static ssize_t -nouveau_hwmon_temp1_auto_point1_temp(struct device *d, - struct device_attribute *a, char *buf) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_therm *therm = nouveau_therm(drm->device); - - return snprintf(buf, PAGE_SIZE, "%d\n", - therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_FAN_BOOST) * 1000); -} -static ssize_t -nouveau_hwmon_set_temp1_auto_point1_temp(struct device *d, - struct device_attribute *a, - const char *buf, size_t count) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_therm *therm = nouveau_therm(drm->device); - long value; - - if (kstrtol(buf, 10, &value) == -EINVAL) - return count; - - therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_FAN_BOOST, - value / 1000); - - return count; -} -static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, S_IRUGO | S_IWUSR, - nouveau_hwmon_temp1_auto_point1_temp, - nouveau_hwmon_set_temp1_auto_point1_temp, 0); - -static ssize_t -nouveau_hwmon_temp1_auto_point1_temp_hyst(struct device *d, - struct device_attribute *a, char *buf) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_therm *therm = nouveau_therm(drm->device); - - return snprintf(buf, PAGE_SIZE, "%d\n", - therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000); -} -static ssize_t -nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d, - struct device_attribute *a, - const char *buf, size_t count) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_therm *therm = nouveau_therm(drm->device); - long value; - - if (kstrtol(buf, 10, &value) == -EINVAL) - return count; - - therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST, - value / 1000); - - return count; -} -static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp_hyst, S_IRUGO | S_IWUSR, - nouveau_hwmon_temp1_auto_point1_temp_hyst, - nouveau_hwmon_set_temp1_auto_point1_temp_hyst, 0); - static ssize_t nouveau_hwmon_max_temp(struct device *d, struct device_attribute *a, char *buf) { @@ -513,38 +438,6 @@ static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, nouveau_hwmon_max_temp, nouveau_hwmon_set_max_temp, 0); -static ssize_t -nouveau_hwmon_max_temp_hyst(struct device *d, struct device_attribute *a, - char *buf) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_therm *therm = nouveau_therm(drm->device); - - return snprintf(buf, PAGE_SIZE, "%d\n", - therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST) * 1000); -} -static ssize_t -nouveau_hwmon_set_max_temp_hyst(struct device *d, struct device_attribute *a, - const char *buf, size_t count) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_therm *therm = nouveau_therm(drm->device); - long value; - - if (kstrtol(buf, 10, &value) == -EINVAL) - return count; - - therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST, - value / 1000); - - return count; -} -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, - nouveau_hwmon_max_temp_hyst, - nouveau_hwmon_set_max_temp_hyst, 0); - static ssize_t nouveau_hwmon_critical_temp(struct device *d, struct device_attribute *a, char *buf) @@ -578,107 +471,6 @@ static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR, nouveau_hwmon_set_critical_temp, 0); -static ssize_t -nouveau_hwmon_critical_temp_hyst(struct device *d, struct device_attribute *a, - char *buf) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_therm *therm = nouveau_therm(drm->device); - - return snprintf(buf, PAGE_SIZE, "%d\n", - therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST) * 1000); -} -static ssize_t -nouveau_hwmon_set_critical_temp_hyst(struct device *d, - struct device_attribute *a, - const char *buf, - size_t count) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_therm *therm = nouveau_therm(drm->device); - long value; - - if (kstrtol(buf, 10, &value) == -EINVAL) - return count; - - therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST, - value / 1000); - - return count; -} -static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO | S_IWUSR, - nouveau_hwmon_critical_temp_hyst, - nouveau_hwmon_set_critical_temp_hyst, 0); -static ssize_t -nouveau_hwmon_emergency_temp(struct device *d, struct device_attribute *a, - char *buf) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_therm *therm = nouveau_therm(drm->device); - - return snprintf(buf, PAGE_SIZE, "%d\n", - therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_SHUTDOWN) * 1000); -} -static ssize_t -nouveau_hwmon_set_emergency_temp(struct device *d, struct device_attribute *a, - const char *buf, - size_t count) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_therm *therm = nouveau_therm(drm->device); - long value; - - if (kstrtol(buf, 10, &value) == -EINVAL) - return count; - - therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_SHUTDOWN, value / 1000); - - return count; -} -static SENSOR_DEVICE_ATTR(temp1_emergency, S_IRUGO | S_IWUSR, - nouveau_hwmon_emergency_temp, - nouveau_hwmon_set_emergency_temp, - 0); - -static ssize_t -nouveau_hwmon_emergency_temp_hyst(struct device *d, struct device_attribute *a, - char *buf) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_therm *therm = nouveau_therm(drm->device); - - return snprintf(buf, PAGE_SIZE, "%d\n", - therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST) * 1000); -} -static ssize_t -nouveau_hwmon_set_emergency_temp_hyst(struct device *d, - struct device_attribute *a, - const char *buf, - size_t count) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_therm *therm = nouveau_therm(drm->device); - long value; - - if (kstrtol(buf, 10, &value) == -EINVAL) - return count; - - therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST, - value / 1000); - - return count; -} -static SENSOR_DEVICE_ATTR(temp1_emergency_hyst, S_IRUGO | S_IWUSR, - nouveau_hwmon_emergency_temp_hyst, - nouveau_hwmon_set_emergency_temp_hyst, - 0); - static ssize_t nouveau_hwmon_show_name(struct device *dev, struct device_attribute *attr, char *buf) @@ -698,7 +490,7 @@ static SENSOR_DEVICE_ATTR(update_rate, S_IRUGO, NULL, 0); static ssize_t -nouveau_hwmon_show_fan1_input(struct device *d, struct device_attribute *attr, +nouveau_hwmon_show_fan0_input(struct device *d, struct device_attribute *attr, char *buf) { struct drm_device *dev = dev_get_drvdata(d); @@ -707,7 +499,7 @@ nouveau_hwmon_show_fan1_input(struct device *d, struct device_attribute *attr, return snprintf(buf, PAGE_SIZE, "%d\n", therm->fan_sense(therm)); } -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, nouveau_hwmon_show_fan1_input, +static SENSOR_DEVICE_ATTR(fan0_input, S_IRUGO, nouveau_hwmon_show_fan0_input, NULL, 0); static ssize_t @@ -873,21 +665,14 @@ static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO | S_IWUSR, static struct attribute *hwmon_attributes[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_emergency.dev_attr.attr, - &sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr, &sensor_dev_attr_name.dev_attr.attr, &sensor_dev_attr_update_rate.dev_attr.attr, NULL }; static struct attribute *hwmon_fan_rpm_attributes[] = { - &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan0_input.dev_attr.attr, NULL }; static struct attribute *hwmon_pwm_fan_attributes[] = { @@ -932,7 +717,7 @@ nouveau_hwmon_init(struct drm_device *dev) dev_set_drvdata(hwmon_dev, dev); /* default sysfs entries */ - ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_attrgroup); + ret = sysfs_create_group(&dev->pdev->dev.kobj, &hwmon_attrgroup); if (ret) { if (ret) goto error; @@ -943,7 +728,7 @@ nouveau_hwmon_init(struct drm_device *dev) * the gpio entries for pwm fan control even when there's no * actual fan connected to it... therm table? */ if (therm->fan_get && therm->fan_get(therm) >= 0) { - ret = sysfs_create_group(&hwmon_dev->kobj, + ret = sysfs_create_group(&dev->pdev->dev.kobj, &hwmon_pwm_fan_attrgroup); if (ret) goto error; @@ -951,7 +736,7 @@ nouveau_hwmon_init(struct drm_device *dev) /* if the card can read the fan rpm */ if (therm->fan_sense(therm) >= 0) { - ret = sysfs_create_group(&hwmon_dev->kobj, + ret = sysfs_create_group(&dev->pdev->dev.kobj, &hwmon_fan_rpm_attrgroup); if (ret) goto error; @@ -979,10 +764,10 @@ nouveau_hwmon_fini(struct drm_device *dev) struct nouveau_pm *pm = nouveau_pm(dev); if (pm->hwmon) { - sysfs_remove_group(&pm->hwmon->kobj, &hwmon_attrgroup); - sysfs_remove_group(&pm->hwmon->kobj, + sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_attrgroup); + sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_pwm_fan_attrgroup); - sysfs_remove_group(&pm->hwmon->kobj, + sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_fan_rpm_attrgroup); hwmon_device_unregister(pm->hwmon); diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_dfp.c b/trunk/drivers/gpu/drm/nouveau/nv04_dfp.c index 7e24cdf1cb39..39ffc07f906b 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/trunk/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -490,8 +490,8 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) /* BIOS scripts usually take care of the backlight, thanks * Apple for your consistency. */ - if (dev->pci_device == 0x0174 || dev->pci_device == 0x0179 || - dev->pci_device == 0x0189 || dev->pci_device == 0x0329) { + if (dev->pci_device == 0x0179 || dev->pci_device == 0x0189 || + dev->pci_device == 0x0329) { if (mode == DRM_MODE_DPMS_ON) { nv_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 0, 1 << 31); nv_mask(device, NV_PCRTC_GPIO_EXT, 3, 1); diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_display.c b/trunk/drivers/gpu/drm/nouveau/nv04_display.c index ad48444c385c..4c6e9f83fe82 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_display.c +++ b/trunk/drivers/gpu/drm/nouveau/nv04_display.c @@ -22,9 +22,6 @@ * Author: Ben Skeggs */ -#include -#include - #include #include @@ -34,8 +31,6 @@ #include "nouveau_encoder.h" #include "nouveau_connector.h" -#include - int nv04_display_early_init(struct drm_device *dev) { @@ -58,7 +53,6 @@ int nv04_display_create(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); - struct nouveau_i2c *i2c = nouveau_i2c(drm->device); struct dcb_table *dcb = &drm->vbios.dcb; struct drm_connector *connector, *ct; struct drm_encoder *encoder; @@ -77,11 +71,6 @@ nv04_display_create(struct drm_device *dev) nouveau_hw_save_vga_fonts(dev, 1); - ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, 0xd1500000, - NV04_DISP_CLASS, NULL, 0, &disp->core); - if (ret) - return ret; - nv04_crtc_create(dev, 0); if (nv_two_heads(dev)) nv04_crtc_create(dev, 1); @@ -125,11 +114,6 @@ nv04_display_create(struct drm_device *dev) } } - list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - nv_encoder->i2c = i2c->find(i2c, nv_encoder->dcb->i2c_index); - } - /* Save previous state */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) crtc->funcs->save(crtc); diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_display.h b/trunk/drivers/gpu/drm/nouveau/nv04_display.h index a0a031dad13f..45322802e37d 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_display.h +++ b/trunk/drivers/gpu/drm/nouveau/nv04_display.h @@ -80,7 +80,6 @@ struct nv04_display { struct nv04_mode_state saved_reg; uint32_t saved_vga_font[4][16384]; uint32_t dac_users[4]; - struct nouveau_object *core; }; static inline struct nv04_display * diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_fence.c b/trunk/drivers/gpu/drm/nouveau/nv04_fence.c index 94eadd1dd10a..a220b94ba9f2 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_fence.c +++ b/trunk/drivers/gpu/drm/nouveau/nv04_fence.c @@ -78,9 +78,6 @@ nv04_fence_context_new(struct nouveau_channel *chan) struct nv04_fence_chan *fctx = kzalloc(sizeof(*fctx), GFP_KERNEL); if (fctx) { nouveau_fence_context_new(&fctx->base); - fctx->base.emit = nv04_fence_emit; - fctx->base.sync = nv04_fence_sync; - fctx->base.read = nv04_fence_read; chan->fence = fctx; return 0; } @@ -107,5 +104,8 @@ nv04_fence_create(struct nouveau_drm *drm) priv->base.dtor = nv04_fence_destroy; priv->base.context_new = nv04_fence_context_new; priv->base.context_del = nv04_fence_context_del; + priv->base.emit = nv04_fence_emit; + priv->base.sync = nv04_fence_sync; + priv->base.read = nv04_fence_read; return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_tv.c b/trunk/drivers/gpu/drm/nouveau/nv04_tv.c index 4a69ccdef9b4..62e826a139b3 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/trunk/drivers/gpu/drm/nouveau/nv04_tv.c @@ -184,23 +184,14 @@ static const struct drm_encoder_funcs nv04_tv_funcs = { .destroy = nv04_tv_destroy, }; -static const struct drm_encoder_helper_funcs nv04_tv_helper_funcs = { - .dpms = nv04_tv_dpms, - .save = drm_i2c_encoder_save, - .restore = drm_i2c_encoder_restore, - .mode_fixup = drm_i2c_encoder_mode_fixup, - .prepare = nv04_tv_prepare, - .commit = nv04_tv_commit, - .mode_set = nv04_tv_mode_set, - .detect = drm_i2c_encoder_detect, -}; - int nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry) { struct nouveau_encoder *nv_encoder; struct drm_encoder *encoder; struct drm_device *dev = connector->dev; + struct drm_encoder_helper_funcs *hfuncs; + struct drm_encoder_slave_funcs *sfuncs; struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_i2c *i2c = nouveau_i2c(drm->device); struct nouveau_i2c_port *port = i2c->find(i2c, entry->i2c_index); @@ -216,11 +207,17 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry) if (!nv_encoder) return -ENOMEM; + hfuncs = kzalloc(sizeof(*hfuncs), GFP_KERNEL); + if (!hfuncs) { + ret = -ENOMEM; + goto fail_free; + } + /* Initialize the common members */ encoder = to_drm_encoder(nv_encoder); drm_encoder_init(dev, encoder, &nv04_tv_funcs, DRM_MODE_ENCODER_TVDAC); - drm_encoder_helper_add(encoder, &nv04_tv_helper_funcs); + drm_encoder_helper_add(encoder, hfuncs); encoder->possible_crtcs = entry->heads; encoder->possible_clones = 0; @@ -233,14 +230,30 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry) if (ret < 0) goto fail_cleanup; + /* Fill the function pointers */ + sfuncs = get_slave_funcs(encoder); + + *hfuncs = (struct drm_encoder_helper_funcs) { + .dpms = nv04_tv_dpms, + .save = sfuncs->save, + .restore = sfuncs->restore, + .mode_fixup = sfuncs->mode_fixup, + .prepare = nv04_tv_prepare, + .commit = nv04_tv_commit, + .mode_set = nv04_tv_mode_set, + .detect = sfuncs->detect, + }; + /* Attach it to the specified connector. */ - get_slave_funcs(encoder)->create_resources(encoder, connector); + sfuncs->create_resources(encoder, connector); drm_mode_connector_attach_encoder(connector, encoder); return 0; fail_cleanup: drm_encoder_cleanup(encoder); + kfree(hfuncs); +fail_free: kfree(nv_encoder); return ret; } diff --git a/trunk/drivers/gpu/drm/nouveau/nv10_fence.c b/trunk/drivers/gpu/drm/nouveau/nv10_fence.c index 06f434f03fba..03017f24d593 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv10_fence.c +++ b/trunk/drivers/gpu/drm/nouveau/nv10_fence.c @@ -27,7 +27,18 @@ #include "nouveau_drm.h" #include "nouveau_dma.h" -#include "nv10_fence.h" +#include "nouveau_fence.h" + +struct nv10_fence_chan { + struct nouveau_fence_chan base; +}; + +struct nv10_fence_priv { + struct nouveau_fence_priv base; + struct nouveau_bo *bo; + spinlock_t lock; + u32 sequence; +}; int nv10_fence_emit(struct nouveau_fence *fence) @@ -50,6 +61,45 @@ nv10_fence_sync(struct nouveau_fence *fence, return -ENODEV; } +int +nv17_fence_sync(struct nouveau_fence *fence, + struct nouveau_channel *prev, struct nouveau_channel *chan) +{ + struct nv10_fence_priv *priv = chan->drm->fence; + u32 value; + int ret; + + if (!mutex_trylock(&prev->cli->mutex)) + return -EBUSY; + + spin_lock(&priv->lock); + value = priv->sequence; + priv->sequence += 2; + spin_unlock(&priv->lock); + + ret = RING_SPACE(prev, 5); + if (!ret) { + BEGIN_NV04(prev, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 4); + OUT_RING (prev, NvSema); + OUT_RING (prev, 0); + OUT_RING (prev, value + 0); + OUT_RING (prev, value + 1); + FIRE_RING (prev); + } + + if (!ret && !(ret = RING_SPACE(chan, 5))) { + BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 4); + OUT_RING (chan, NvSema); + OUT_RING (chan, 0); + OUT_RING (chan, value + 1); + OUT_RING (chan, value + 2); + FIRE_RING (chan); + } + + mutex_unlock(&prev->cli->mutex); + return 0; +} + u32 nv10_fence_read(struct nouveau_channel *chan) { @@ -65,20 +115,39 @@ nv10_fence_context_del(struct nouveau_channel *chan) kfree(fctx); } -int +static int nv10_fence_context_new(struct nouveau_channel *chan) { + struct nv10_fence_priv *priv = chan->drm->fence; struct nv10_fence_chan *fctx; + int ret = 0; fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); if (!fctx) return -ENOMEM; nouveau_fence_context_new(&fctx->base); - fctx->base.emit = nv10_fence_emit; - fctx->base.read = nv10_fence_read; - fctx->base.sync = nv10_fence_sync; - return 0; + + if (priv->bo) { + struct ttm_mem_reg *mem = &priv->bo->bo.mem; + struct nouveau_object *object; + u32 start = mem->start * PAGE_SIZE; + u32 limit = mem->start + mem->size - 1; + + ret = nouveau_object_new(nv_object(chan->cli), chan->handle, + NvSema, 0x0002, + &(struct nv_dma_class) { + .flags = NV_DMA_TARGET_VRAM | + NV_DMA_ACCESS_RDWR, + .start = start, + .limit = limit, + }, sizeof(struct nv_dma_class), + &object); + } + + if (ret) + nv10_fence_context_del(chan); + return ret; } void @@ -93,10 +162,18 @@ nv10_fence_destroy(struct nouveau_drm *drm) kfree(priv); } +void nv17_fence_resume(struct nouveau_drm *drm) +{ + struct nv10_fence_priv *priv = drm->fence; + + nouveau_bo_wr32(priv->bo, 0, priv->sequence); +} + int nv10_fence_create(struct nouveau_drm *drm) { struct nv10_fence_priv *priv; + int ret = 0; priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) @@ -105,6 +182,33 @@ nv10_fence_create(struct nouveau_drm *drm) priv->base.dtor = nv10_fence_destroy; priv->base.context_new = nv10_fence_context_new; priv->base.context_del = nv10_fence_context_del; + priv->base.emit = nv10_fence_emit; + priv->base.read = nv10_fence_read; + priv->base.sync = nv10_fence_sync; spin_lock_init(&priv->lock); - return 0; + + if (nv_device(drm->device)->chipset >= 0x17) { + ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, + 0, 0x0000, NULL, &priv->bo); + if (!ret) { + ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); + if (!ret) { + ret = nouveau_bo_map(priv->bo); + if (ret) + nouveau_bo_unpin(priv->bo); + } + if (ret) + nouveau_bo_ref(NULL, &priv->bo); + } + + if (ret == 0) { + nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); + priv->base.sync = nv17_fence_sync; + priv->base.resume = nv17_fence_resume; + } + } + + if (ret) + nv10_fence_destroy(drm); + return ret; } diff --git a/trunk/drivers/gpu/drm/nouveau/nv10_fence.h b/trunk/drivers/gpu/drm/nouveau/nv10_fence.h deleted file mode 100644 index e5d9204826c2..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/nv10_fence.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __NV10_FENCE_H_ -#define __NV10_FENCE_H_ - -#include -#include "nouveau_fence.h" -#include "nouveau_bo.h" - -struct nv10_fence_chan { - struct nouveau_fence_chan base; -}; - -struct nv10_fence_priv { - struct nouveau_fence_priv base; - struct nouveau_bo *bo; - spinlock_t lock; - u32 sequence; -}; - -#endif diff --git a/trunk/drivers/gpu/drm/nouveau/nv17_fence.c b/trunk/drivers/gpu/drm/nouveau/nv17_fence.c deleted file mode 100644 index 8e47a9bae8c3..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/nv17_fence.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include -#include - -#include "nouveau_drm.h" -#include "nouveau_dma.h" -#include "nv10_fence.h" - -int -nv17_fence_sync(struct nouveau_fence *fence, - struct nouveau_channel *prev, struct nouveau_channel *chan) -{ - struct nv10_fence_priv *priv = chan->drm->fence; - u32 value; - int ret; - - if (!mutex_trylock(&prev->cli->mutex)) - return -EBUSY; - - spin_lock(&priv->lock); - value = priv->sequence; - priv->sequence += 2; - spin_unlock(&priv->lock); - - ret = RING_SPACE(prev, 5); - if (!ret) { - BEGIN_NV04(prev, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 4); - OUT_RING (prev, NvSema); - OUT_RING (prev, 0); - OUT_RING (prev, value + 0); - OUT_RING (prev, value + 1); - FIRE_RING (prev); - } - - if (!ret && !(ret = RING_SPACE(chan, 5))) { - BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 4); - OUT_RING (chan, NvSema); - OUT_RING (chan, 0); - OUT_RING (chan, value + 1); - OUT_RING (chan, value + 2); - FIRE_RING (chan); - } - - mutex_unlock(&prev->cli->mutex); - return 0; -} - -static int -nv17_fence_context_new(struct nouveau_channel *chan) -{ - struct nv10_fence_priv *priv = chan->drm->fence; - struct nv10_fence_chan *fctx; - struct ttm_mem_reg *mem = &priv->bo->bo.mem; - struct nouveau_object *object; - u32 start = mem->start * PAGE_SIZE; - u32 limit = mem->start + mem->size - 1; - int ret = 0; - - fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); - if (!fctx) - return -ENOMEM; - - nouveau_fence_context_new(&fctx->base); - fctx->base.emit = nv10_fence_emit; - fctx->base.read = nv10_fence_read; - fctx->base.sync = nv17_fence_sync; - - ret = nouveau_object_new(nv_object(chan->cli), chan->handle, - NvSema, 0x0002, - &(struct nv_dma_class) { - .flags = NV_DMA_TARGET_VRAM | - NV_DMA_ACCESS_RDWR, - .start = start, - .limit = limit, - }, sizeof(struct nv_dma_class), - &object); - if (ret) - nv10_fence_context_del(chan); - return ret; -} - -void -nv17_fence_resume(struct nouveau_drm *drm) -{ - struct nv10_fence_priv *priv = drm->fence; - - nouveau_bo_wr32(priv->bo, 0, priv->sequence); -} - -int -nv17_fence_create(struct nouveau_drm *drm) -{ - struct nv10_fence_priv *priv; - int ret = 0; - - priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->base.dtor = nv10_fence_destroy; - priv->base.resume = nv17_fence_resume; - priv->base.context_new = nv17_fence_context_new; - priv->base.context_del = nv10_fence_context_del; - spin_lock_init(&priv->lock); - - ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, - 0, 0x0000, NULL, &priv->bo); - if (!ret) { - ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); - if (!ret) { - ret = nouveau_bo_map(priv->bo); - if (ret) - nouveau_bo_unpin(priv->bo); - } - if (ret) - nouveau_bo_ref(NULL, &priv->bo); - } - - if (ret) { - nv10_fence_destroy(drm); - return ret; - } - - nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); - return ret; -} diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_display.c b/trunk/drivers/gpu/drm/nouveau/nv50_display.c index a6237c9cbbc3..d4cbea19b890 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_display.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_display.c @@ -43,7 +43,6 @@ #include #include #include -#include #define EVO_DMA_NR 9 @@ -434,10 +433,7 @@ evo_kick(u32 *push, void *evoc) static bool evo_sync_wait(void *data) { - if (nouveau_bo_rd32(data, EVO_MAST_NTFY) != 0x00000000) - return true; - usleep_range(1, 2); - return false; + return nouveau_bo_rd32(data, EVO_MAST_NTFY) != 0x00000000; } static int @@ -516,7 +512,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, if (ret) return ret; - if (nv_mclass(chan->object) < NV84_CHANNEL_IND_CLASS) { + if (nv_mclass(chan->object) < NVC0_CHANNEL_IND_CLASS) { BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 2); OUT_RING (chan, NvEvoSema0 + nv_crtc->index); OUT_RING (chan, sync->sem.offset); @@ -526,36 +522,24 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, OUT_RING (chan, sync->sem.offset ^ 0x10); OUT_RING (chan, 0x74b1e000); BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); - OUT_RING (chan, NvSema); - } else - if (nv_mclass(chan->object) < NVC0_CHANNEL_IND_CLASS) { - u64 offset = nv84_fence_crtc(chan, nv_crtc->index); - offset += sync->sem.offset; - - BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); - OUT_RING (chan, upper_32_bits(offset)); - OUT_RING (chan, lower_32_bits(offset)); - OUT_RING (chan, 0xf00d0000 | sync->sem.value); - OUT_RING (chan, 0x00000002); - BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); - OUT_RING (chan, upper_32_bits(offset)); - OUT_RING (chan, lower_32_bits(offset ^ 0x10)); - OUT_RING (chan, 0x74b1e000); - OUT_RING (chan, 0x00000001); + if (nv_mclass(chan->object) < NV84_CHANNEL_DMA_CLASS) + OUT_RING (chan, NvSema); + else + OUT_RING (chan, chan->vram); } else { - u64 offset = nv84_fence_crtc(chan, nv_crtc->index); + u64 offset = nvc0_fence_crtc(chan, nv_crtc->index); offset += sync->sem.offset; BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); OUT_RING (chan, upper_32_bits(offset)); OUT_RING (chan, lower_32_bits(offset)); OUT_RING (chan, 0xf00d0000 | sync->sem.value); - OUT_RING (chan, 0x00001002); + OUT_RING (chan, 0x1002); BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); OUT_RING (chan, upper_32_bits(offset)); OUT_RING (chan, lower_32_bits(offset ^ 0x10)); OUT_RING (chan, 0x74b1e000); - OUT_RING (chan, 0x00001001); + OUT_RING (chan, 0x1001); } FIRE_RING (chan); @@ -1519,6 +1503,9 @@ nv50_dac_disconnect(struct drm_encoder *encoder) evo_mthd(push, 0x0180 + (or * 0x020), 1); evo_data(push, 0x00000000); } + + evo_mthd(push, 0x0080, 1); + evo_data(push, 0x00000000); evo_kick(push, mast); } } @@ -1565,23 +1552,20 @@ static const struct drm_encoder_funcs nv50_dac_func = { static int nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe) { - struct nouveau_drm *drm = nouveau_drm(connector->dev); - struct nouveau_i2c *i2c = nouveau_i2c(drm->device); + struct drm_device *dev = connector->dev; struct nouveau_encoder *nv_encoder; struct drm_encoder *encoder; - int type = DRM_MODE_ENCODER_DAC; nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); if (!nv_encoder) return -ENOMEM; nv_encoder->dcb = dcbe; nv_encoder->or = ffs(dcbe->or) - 1; - nv_encoder->i2c = i2c->find(i2c, dcbe->i2c_index); encoder = to_drm_encoder(nv_encoder); encoder->possible_crtcs = dcbe->heads; encoder->possible_clones = 0; - drm_encoder_init(connector->dev, encoder, &nv50_dac_func, type); + drm_encoder_init(dev, encoder, &nv50_dac_func, DRM_MODE_ENCODER_DAC); drm_encoder_helper_add(encoder, &nv50_dac_hfunc); drm_mode_connector_attach_encoder(connector, encoder); @@ -1690,6 +1674,9 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) } nv_call(disp->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON)); + + if (nv_encoder->dcb->type == DCB_OUTPUT_DP) + nouveau_dp_dpms(encoder, mode, nv_encoder->dp.datarate, disp->core); } static bool @@ -1732,6 +1719,9 @@ nv50_sor_disconnect(struct drm_encoder *encoder) evo_mthd(push, 0x0200 + (or * 0x20), 1); evo_data(push, 0x00000000); } + + evo_mthd(push, 0x0080, 1); + evo_data(push, 0x00000000); evo_kick(push, mast); } @@ -1742,6 +1732,14 @@ nv50_sor_disconnect(struct drm_encoder *encoder) nv_encoder->crtc = NULL; } +static void +nv50_sor_prepare(struct drm_encoder *encoder) +{ + nv50_sor_disconnect(encoder); + if (nouveau_encoder(encoder)->dcb->type == DCB_OUTPUT_DP) + evo_sync(encoder->dev); +} + static void nv50_sor_commit(struct drm_encoder *encoder) { @@ -1837,13 +1835,8 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, push = evo_wait(nv50_mast(dev), 8); if (push) { if (nv50_vers(mast) < NVD0_DISP_CLASS) { - u32 ctrl = (depth << 16) | (proto << 8) | owner; - if (mode->flags & DRM_MODE_FLAG_NHSYNC) - ctrl |= 0x00001000; - if (mode->flags & DRM_MODE_FLAG_NVSYNC) - ctrl |= 0x00002000; evo_mthd(push, 0x0600 + (nv_encoder->or * 0x040), 1); - evo_data(push, ctrl); + evo_data(push, (depth << 16) | (proto << 8) | owner); } else { u32 magic = 0x31ec6000 | (nv_crtc->index << 25); u32 syncs = 0x00000001; @@ -1879,7 +1872,7 @@ nv50_sor_destroy(struct drm_encoder *encoder) static const struct drm_encoder_helper_funcs nv50_sor_hfunc = { .dpms = nv50_sor_dpms, .mode_fixup = nv50_sor_mode_fixup, - .prepare = nv50_sor_disconnect, + .prepare = nv50_sor_prepare, .commit = nv50_sor_commit, .mode_set = nv50_sor_mode_set, .disable = nv50_sor_disconnect, @@ -1893,214 +1886,27 @@ static const struct drm_encoder_funcs nv50_sor_func = { static int nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe) { - struct nouveau_drm *drm = nouveau_drm(connector->dev); - struct nouveau_i2c *i2c = nouveau_i2c(drm->device); + struct drm_device *dev = connector->dev; struct nouveau_encoder *nv_encoder; struct drm_encoder *encoder; - int type; - - switch (dcbe->type) { - case DCB_OUTPUT_LVDS: type = DRM_MODE_ENCODER_LVDS; break; - case DCB_OUTPUT_TMDS: - case DCB_OUTPUT_DP: - default: - type = DRM_MODE_ENCODER_TMDS; - break; - } nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); if (!nv_encoder) return -ENOMEM; nv_encoder->dcb = dcbe; nv_encoder->or = ffs(dcbe->or) - 1; - nv_encoder->i2c = i2c->find(i2c, dcbe->i2c_index); nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; encoder = to_drm_encoder(nv_encoder); encoder->possible_crtcs = dcbe->heads; encoder->possible_clones = 0; - drm_encoder_init(connector->dev, encoder, &nv50_sor_func, type); + drm_encoder_init(dev, encoder, &nv50_sor_func, DRM_MODE_ENCODER_TMDS); drm_encoder_helper_add(encoder, &nv50_sor_hfunc); drm_mode_connector_attach_encoder(connector, encoder); return 0; } -/****************************************************************************** - * PIOR - *****************************************************************************/ - -static void -nv50_pior_dpms(struct drm_encoder *encoder, int mode) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nv50_disp *disp = nv50_disp(encoder->dev); - u32 mthd = (nv_encoder->dcb->type << 12) | nv_encoder->or; - u32 ctrl = (mode == DRM_MODE_DPMS_ON); - nv_call(disp->core, NV50_DISP_PIOR_PWR + mthd, ctrl); -} - -static bool -nv50_pior_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_connector *nv_connector; - - nv_connector = nouveau_encoder_connector_get(nv_encoder); - if (nv_connector && nv_connector->native_mode) { - if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) { - int id = adjusted_mode->base.id; - *adjusted_mode = *nv_connector->native_mode; - adjusted_mode->base.id = id; - } - } - - adjusted_mode->clock *= 2; - return true; -} - -static void -nv50_pior_commit(struct drm_encoder *encoder) -{ -} - -static void -nv50_pior_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct nv50_mast *mast = nv50_mast(encoder->dev); - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); - struct nouveau_connector *nv_connector; - u8 owner = 1 << nv_crtc->index; - u8 proto, depth; - u32 *push; - - nv_connector = nouveau_encoder_connector_get(nv_encoder); - switch (nv_connector->base.display_info.bpc) { - case 10: depth = 0x6; break; - case 8: depth = 0x5; break; - case 6: depth = 0x2; break; - default: depth = 0x0; break; - } - - switch (nv_encoder->dcb->type) { - case DCB_OUTPUT_TMDS: - case DCB_OUTPUT_DP: - proto = 0x0; - break; - default: - BUG_ON(1); - break; - } - - nv50_pior_dpms(encoder, DRM_MODE_DPMS_ON); - - push = evo_wait(mast, 8); - if (push) { - if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) { - u32 ctrl = (depth << 16) | (proto << 8) | owner; - if (mode->flags & DRM_MODE_FLAG_NHSYNC) - ctrl |= 0x00001000; - if (mode->flags & DRM_MODE_FLAG_NVSYNC) - ctrl |= 0x00002000; - evo_mthd(push, 0x0700 + (nv_encoder->or * 0x040), 1); - evo_data(push, ctrl); - } - - evo_kick(push, mast); - } - - nv_encoder->crtc = encoder->crtc; -} - -static void -nv50_pior_disconnect(struct drm_encoder *encoder) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nv50_mast *mast = nv50_mast(encoder->dev); - const int or = nv_encoder->or; - u32 *push; - - if (nv_encoder->crtc) { - nv50_crtc_prepare(nv_encoder->crtc); - - push = evo_wait(mast, 4); - if (push) { - if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) { - evo_mthd(push, 0x0700 + (or * 0x040), 1); - evo_data(push, 0x00000000); - } - evo_kick(push, mast); - } - } - - nv_encoder->crtc = NULL; -} - -static void -nv50_pior_destroy(struct drm_encoder *encoder) -{ - drm_encoder_cleanup(encoder); - kfree(encoder); -} - -static const struct drm_encoder_helper_funcs nv50_pior_hfunc = { - .dpms = nv50_pior_dpms, - .mode_fixup = nv50_pior_mode_fixup, - .prepare = nv50_pior_disconnect, - .commit = nv50_pior_commit, - .mode_set = nv50_pior_mode_set, - .disable = nv50_pior_disconnect, - .get_crtc = nv50_display_crtc_get, -}; - -static const struct drm_encoder_funcs nv50_pior_func = { - .destroy = nv50_pior_destroy, -}; - -static int -nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe) -{ - struct nouveau_drm *drm = nouveau_drm(connector->dev); - struct nouveau_i2c *i2c = nouveau_i2c(drm->device); - struct nouveau_i2c_port *ddc = NULL; - struct nouveau_encoder *nv_encoder; - struct drm_encoder *encoder; - int type; - - switch (dcbe->type) { - case DCB_OUTPUT_TMDS: - ddc = i2c->find_type(i2c, NV_I2C_TYPE_EXTDDC(dcbe->extdev)); - type = DRM_MODE_ENCODER_TMDS; - break; - case DCB_OUTPUT_DP: - ddc = i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(dcbe->extdev)); - type = DRM_MODE_ENCODER_TMDS; - break; - default: - return -ENODEV; - } - - nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); - if (!nv_encoder) - return -ENOMEM; - nv_encoder->dcb = dcbe; - nv_encoder->or = ffs(dcbe->or) - 1; - nv_encoder->i2c = ddc; - - encoder = to_drm_encoder(nv_encoder); - encoder->possible_crtcs = dcbe->heads; - encoder->possible_clones = 0; - drm_encoder_init(connector->dev, encoder, &nv50_pior_func, type); - drm_encoder_helper_add(encoder, &nv50_pior_hfunc); - - drm_mode_connector_attach_encoder(connector, encoder); - return 0; -} - /****************************************************************************** * Init *****************************************************************************/ @@ -2117,7 +1923,7 @@ nv50_display_init(struct drm_device *dev) evo_mthd(push, 0x0088, 1); evo_data(push, NvEvoSync); evo_kick(push, nv50_mast(dev)); - return 0; + return evo_sync(dev); } return -EBUSY; @@ -2223,28 +2029,25 @@ nv50_display_create(struct drm_device *dev) if (IS_ERR(connector)) continue; - if (dcbe->location == DCB_LOC_ON_CHIP) { - switch (dcbe->type) { - case DCB_OUTPUT_TMDS: - case DCB_OUTPUT_LVDS: - case DCB_OUTPUT_DP: - ret = nv50_sor_create(connector, dcbe); - break; - case DCB_OUTPUT_ANALOG: - ret = nv50_dac_create(connector, dcbe); - break; - default: - ret = -ENODEV; - break; - } - } else { - ret = nv50_pior_create(connector, dcbe); + if (dcbe->location != DCB_LOC_ON_CHIP) { + NV_WARN(drm, "skipping off-chip encoder %d/%d\n", + dcbe->type, ffs(dcbe->or) - 1); + continue; } - if (ret) { - NV_WARN(drm, "failed to create encoder %d/%d/%d: %d\n", - dcbe->location, dcbe->type, - ffs(dcbe->or) - 1, ret); + switch (dcbe->type) { + case DCB_OUTPUT_TMDS: + case DCB_OUTPUT_LVDS: + case DCB_OUTPUT_DP: + nv50_sor_create(connector, dcbe); + break; + case DCB_OUTPUT_ANALOG: + nv50_dac_create(connector, dcbe); + break; + default: + NV_WARN(drm, "skipping unsupported encoder %d/%d\n", + dcbe->type, ffs(dcbe->or) - 1); + continue; } } diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_fence.c b/trunk/drivers/gpu/drm/nouveau/nv50_fence.c index f9701e567db8..d889f3ac0d41 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_fence.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_fence.c @@ -27,16 +27,27 @@ #include "nouveau_drm.h" #include "nouveau_dma.h" -#include "nv10_fence.h" +#include "nouveau_fence.h" #include "nv50_display.h" +struct nv50_fence_chan { + struct nouveau_fence_chan base; +}; + +struct nv50_fence_priv { + struct nouveau_fence_priv base; + struct nouveau_bo *bo; + spinlock_t lock; + u32 sequence; +}; + static int nv50_fence_context_new(struct nouveau_channel *chan) { struct drm_device *dev = chan->drm->dev; - struct nv10_fence_priv *priv = chan->drm->fence; - struct nv10_fence_chan *fctx; + struct nv50_fence_priv *priv = chan->drm->fence; + struct nv50_fence_chan *fctx; struct ttm_mem_reg *mem = &priv->bo->bo.mem; struct nouveau_object *object; int ret, i; @@ -46,9 +57,6 @@ nv50_fence_context_new(struct nouveau_channel *chan) return -ENOMEM; nouveau_fence_context_new(&fctx->base); - fctx->base.emit = nv10_fence_emit; - fctx->base.read = nv10_fence_read; - fctx->base.sync = nv17_fence_sync; ret = nouveau_object_new(nv_object(chan->cli), chan->handle, NvSema, 0x0002, @@ -83,7 +91,7 @@ nv50_fence_context_new(struct nouveau_channel *chan) int nv50_fence_create(struct nouveau_drm *drm) { - struct nv10_fence_priv *priv; + struct nv50_fence_priv *priv; int ret = 0; priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); @@ -91,9 +99,11 @@ nv50_fence_create(struct nouveau_drm *drm) return -ENOMEM; priv->base.dtor = nv10_fence_destroy; - priv->base.resume = nv17_fence_resume; priv->base.context_new = nv50_fence_context_new; priv->base.context_del = nv10_fence_context_del; + priv->base.emit = nv10_fence_emit; + priv->base.read = nv10_fence_read; + priv->base.sync = nv17_fence_sync; spin_lock_init(&priv->lock); ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, @@ -109,11 +119,13 @@ nv50_fence_create(struct nouveau_drm *drm) nouveau_bo_ref(NULL, &priv->bo); } - if (ret) { - nv10_fence_destroy(drm); - return ret; + if (ret == 0) { + nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); + priv->base.sync = nv17_fence_sync; + priv->base.resume = nv17_fence_resume; } - nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); + if (ret) + nv10_fence_destroy(drm); return ret; } diff --git a/trunk/drivers/gpu/drm/nouveau/nv84_fence.c b/trunk/drivers/gpu/drm/nouveau/nv84_fence.c index 9fd475c89820..c686650584b6 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/trunk/drivers/gpu/drm/nouveau/nv84_fence.c @@ -23,7 +23,6 @@ */ #include -#include #include #include @@ -34,115 +33,79 @@ #include "nv50_display.h" -u64 -nv84_fence_crtc(struct nouveau_channel *chan, int crtc) -{ - struct nv84_fence_chan *fctx = chan->fence; - return fctx->dispc_vma[crtc].offset; -} +struct nv84_fence_chan { + struct nouveau_fence_chan base; +}; + +struct nv84_fence_priv { + struct nouveau_fence_priv base; + struct nouveau_gpuobj *mem; +}; static int -nv84_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence) +nv84_fence_emit(struct nouveau_fence *fence) { - int ret = RING_SPACE(chan, 8); + struct nouveau_channel *chan = fence->channel; + struct nouveau_fifo_chan *fifo = (void *)chan->object; + int ret = RING_SPACE(chan, 7); if (ret == 0) { BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); - OUT_RING (chan, chan->vram); - BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 5); - OUT_RING (chan, upper_32_bits(virtual)); - OUT_RING (chan, lower_32_bits(virtual)); - OUT_RING (chan, sequence); + OUT_RING (chan, NvSema); + BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); + OUT_RING (chan, upper_32_bits(fifo->chid * 16)); + OUT_RING (chan, lower_32_bits(fifo->chid * 16)); + OUT_RING (chan, fence->sequence); OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG); - OUT_RING (chan, 0x00000000); FIRE_RING (chan); } return ret; } + static int -nv84_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence) +nv84_fence_sync(struct nouveau_fence *fence, + struct nouveau_channel *prev, struct nouveau_channel *chan) { + struct nouveau_fifo_chan *fifo = (void *)prev->object; int ret = RING_SPACE(chan, 7); if (ret == 0) { BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); - OUT_RING (chan, chan->vram); + OUT_RING (chan, NvSema); BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); - OUT_RING (chan, upper_32_bits(virtual)); - OUT_RING (chan, lower_32_bits(virtual)); - OUT_RING (chan, sequence); + OUT_RING (chan, upper_32_bits(fifo->chid * 16)); + OUT_RING (chan, lower_32_bits(fifo->chid * 16)); + OUT_RING (chan, fence->sequence); OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL); FIRE_RING (chan); } return ret; } -static int -nv84_fence_emit(struct nouveau_fence *fence) -{ - struct nouveau_channel *chan = fence->channel; - struct nv84_fence_chan *fctx = chan->fence; - struct nouveau_fifo_chan *fifo = (void *)chan->object; - u64 addr = fifo->chid * 16; - - if (fence->sysmem) - addr += fctx->vma_gart.offset; - else - addr += fctx->vma.offset; - - return fctx->base.emit32(chan, addr, fence->sequence); -} - -static int -nv84_fence_sync(struct nouveau_fence *fence, - struct nouveau_channel *prev, struct nouveau_channel *chan) -{ - struct nv84_fence_chan *fctx = chan->fence; - struct nouveau_fifo_chan *fifo = (void *)prev->object; - u64 addr = fifo->chid * 16; - - if (fence->sysmem) - addr += fctx->vma_gart.offset; - else - addr += fctx->vma.offset; - - return fctx->base.sync32(chan, addr, fence->sequence); -} - static u32 nv84_fence_read(struct nouveau_channel *chan) { struct nouveau_fifo_chan *fifo = (void *)chan->object; struct nv84_fence_priv *priv = chan->drm->fence; - return nouveau_bo_rd32(priv->bo, fifo->chid * 16/4); + return nv_ro32(priv->mem, fifo->chid * 16); } static void nv84_fence_context_del(struct nouveau_channel *chan) { - struct drm_device *dev = chan->drm->dev; - struct nv84_fence_priv *priv = chan->drm->fence; struct nv84_fence_chan *fctx = chan->fence; - int i; - - for (i = 0; i < dev->mode_config.num_crtc; i++) { - struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); - nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); - } - - nouveau_bo_vma_del(priv->bo, &fctx->vma_gart); - nouveau_bo_vma_del(priv->bo, &fctx->vma); nouveau_fence_context_del(&fctx->base); chan->fence = NULL; kfree(fctx); } -int +static int nv84_fence_context_new(struct nouveau_channel *chan) { + struct drm_device *dev = chan->drm->dev; struct nouveau_fifo_chan *fifo = (void *)chan->object; - struct nouveau_client *client = nouveau_client(fifo); struct nv84_fence_priv *priv = chan->drm->fence; struct nv84_fence_chan *fctx; + struct nouveau_object *object; int ret, i; fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); @@ -150,74 +113,44 @@ nv84_fence_context_new(struct nouveau_channel *chan) return -ENOMEM; nouveau_fence_context_new(&fctx->base); - fctx->base.emit = nv84_fence_emit; - fctx->base.sync = nv84_fence_sync; - fctx->base.read = nv84_fence_read; - fctx->base.emit32 = nv84_fence_emit32; - fctx->base.sync32 = nv84_fence_sync32; - ret = nouveau_bo_vma_add(priv->bo, client->vm, &fctx->vma); - if (ret == 0) { - ret = nouveau_bo_vma_add(priv->bo_gart, client->vm, - &fctx->vma_gart); - } + ret = nouveau_object_new(nv_object(chan->cli), chan->handle, + NvSema, 0x0002, + &(struct nv_dma_class) { + .flags = NV_DMA_TARGET_VRAM | + NV_DMA_ACCESS_RDWR, + .start = priv->mem->addr, + .limit = priv->mem->addr + + priv->mem->size - 1, + }, sizeof(struct nv_dma_class), + &object); + + /* dma objects for display sync channel semaphore blocks */ + for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) { + struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); - /* map display semaphore buffers into channel's vm */ - for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { - struct nouveau_bo *bo = nv50_display_crtc_sema(chan->drm->dev, i); - ret = nouveau_bo_vma_add(bo, client->vm, &fctx->dispc_vma[i]); + ret = nouveau_object_new(nv_object(chan->cli), chan->handle, + NvEvoSema0 + i, 0x003d, + &(struct nv_dma_class) { + .flags = NV_DMA_TARGET_VRAM | + NV_DMA_ACCESS_RDWR, + .start = bo->bo.offset, + .limit = bo->bo.offset + 0xfff, + }, sizeof(struct nv_dma_class), + &object); } - nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000); - if (ret) nv84_fence_context_del(chan); + nv_wo32(priv->mem, fifo->chid * 16, 0x00000000); return ret; } -static bool -nv84_fence_suspend(struct nouveau_drm *drm) -{ - struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); - struct nv84_fence_priv *priv = drm->fence; - int i; - - priv->suspend = vmalloc((pfifo->max + 1) * sizeof(u32)); - if (priv->suspend) { - for (i = 0; i <= pfifo->max; i++) - priv->suspend[i] = nouveau_bo_rd32(priv->bo, i*4); - } - - return priv->suspend != NULL; -} - -static void -nv84_fence_resume(struct nouveau_drm *drm) -{ - struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); - struct nv84_fence_priv *priv = drm->fence; - int i; - - if (priv->suspend) { - for (i = 0; i <= pfifo->max; i++) - nouveau_bo_wr32(priv->bo, i*4, priv->suspend[i]); - vfree(priv->suspend); - priv->suspend = NULL; - } -} - static void nv84_fence_destroy(struct nouveau_drm *drm) { struct nv84_fence_priv *priv = drm->fence; - nouveau_bo_unmap(priv->bo_gart); - if (priv->bo_gart) - nouveau_bo_unpin(priv->bo_gart); - nouveau_bo_ref(NULL, &priv->bo_gart); - nouveau_bo_unmap(priv->bo); - if (priv->bo) - nouveau_bo_unpin(priv->bo); - nouveau_bo_ref(NULL, &priv->bo); + nouveau_gpuobj_ref(NULL, &priv->mem); drm->fence = NULL; kfree(priv); } @@ -227,6 +160,7 @@ nv84_fence_create(struct nouveau_drm *drm) { struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); struct nv84_fence_priv *priv; + u32 chan = pfifo->max + 1; int ret; priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); @@ -234,42 +168,14 @@ nv84_fence_create(struct nouveau_drm *drm) return -ENOMEM; priv->base.dtor = nv84_fence_destroy; - priv->base.suspend = nv84_fence_suspend; - priv->base.resume = nv84_fence_resume; priv->base.context_new = nv84_fence_context_new; priv->base.context_del = nv84_fence_context_del; + priv->base.emit = nv84_fence_emit; + priv->base.sync = nv84_fence_sync; + priv->base.read = nv84_fence_read; - init_waitqueue_head(&priv->base.waiting); - priv->base.uevent = true; - - ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, - TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo); - if (ret == 0) { - ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); - if (ret == 0) { - ret = nouveau_bo_map(priv->bo); - if (ret) - nouveau_bo_unpin(priv->bo); - } - if (ret) - nouveau_bo_ref(NULL, &priv->bo); - } - - if (ret == 0) - ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, - TTM_PL_FLAG_TT, 0, 0, NULL, - &priv->bo_gart); - if (ret == 0) { - ret = nouveau_bo_pin(priv->bo_gart, TTM_PL_FLAG_TT); - if (ret == 0) { - ret = nouveau_bo_map(priv->bo_gart); - if (ret) - nouveau_bo_unpin(priv->bo_gart); - } - if (ret) - nouveau_bo_ref(NULL, &priv->bo_gart); - } - + ret = nouveau_gpuobj_new(drm->device, NULL, chan * 16, 0x1000, 0, + &priv->mem); if (ret) nv84_fence_destroy(drm); return ret; diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_fence.c b/trunk/drivers/gpu/drm/nouveau/nvc0_fence.c index 9566267fbc42..2a56b1b551cb 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_fence.c +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_fence.c @@ -34,57 +34,203 @@ #include "nv50_display.h" +struct nvc0_fence_priv { + struct nouveau_fence_priv base; + struct nouveau_bo *bo; + u32 *suspend; +}; + +struct nvc0_fence_chan { + struct nouveau_fence_chan base; + struct nouveau_vma vma; + struct nouveau_vma dispc_vma[4]; +}; + +u64 +nvc0_fence_crtc(struct nouveau_channel *chan, int crtc) +{ + struct nvc0_fence_chan *fctx = chan->fence; + return fctx->dispc_vma[crtc].offset; +} + static int -nvc0_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence) +nvc0_fence_emit(struct nouveau_fence *fence) { - int ret = RING_SPACE(chan, 6); + struct nouveau_channel *chan = fence->channel; + struct nvc0_fence_chan *fctx = chan->fence; + struct nouveau_fifo_chan *fifo = (void *)chan->object; + u64 addr = fctx->vma.offset + fifo->chid * 16; + int ret; + + ret = RING_SPACE(chan, 5); if (ret == 0) { - BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 5); - OUT_RING (chan, upper_32_bits(virtual)); - OUT_RING (chan, lower_32_bits(virtual)); - OUT_RING (chan, sequence); + BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); + OUT_RING (chan, upper_32_bits(addr)); + OUT_RING (chan, lower_32_bits(addr)); + OUT_RING (chan, fence->sequence); OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG); - OUT_RING (chan, 0x00000000); FIRE_RING (chan); } + return ret; } static int -nvc0_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence) +nvc0_fence_sync(struct nouveau_fence *fence, + struct nouveau_channel *prev, struct nouveau_channel *chan) { - int ret = RING_SPACE(chan, 5); + struct nvc0_fence_chan *fctx = chan->fence; + struct nouveau_fifo_chan *fifo = (void *)prev->object; + u64 addr = fctx->vma.offset + fifo->chid * 16; + int ret; + + ret = RING_SPACE(chan, 5); if (ret == 0) { BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); - OUT_RING (chan, upper_32_bits(virtual)); - OUT_RING (chan, lower_32_bits(virtual)); - OUT_RING (chan, sequence); + OUT_RING (chan, upper_32_bits(addr)); + OUT_RING (chan, lower_32_bits(addr)); + OUT_RING (chan, fence->sequence); OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL | NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD); FIRE_RING (chan); } + return ret; } +static u32 +nvc0_fence_read(struct nouveau_channel *chan) +{ + struct nouveau_fifo_chan *fifo = (void *)chan->object; + struct nvc0_fence_priv *priv = chan->drm->fence; + return nouveau_bo_rd32(priv->bo, fifo->chid * 16/4); +} + +static void +nvc0_fence_context_del(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->drm->dev; + struct nvc0_fence_priv *priv = chan->drm->fence; + struct nvc0_fence_chan *fctx = chan->fence; + int i; + + for (i = 0; i < dev->mode_config.num_crtc; i++) { + struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); + nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); + } + + nouveau_bo_vma_del(priv->bo, &fctx->vma); + nouveau_fence_context_del(&fctx->base); + chan->fence = NULL; + kfree(fctx); +} + static int nvc0_fence_context_new(struct nouveau_channel *chan) { - int ret = nv84_fence_context_new(chan); - if (ret == 0) { - struct nv84_fence_chan *fctx = chan->fence; - fctx->base.emit32 = nvc0_fence_emit32; - fctx->base.sync32 = nvc0_fence_sync32; + struct nouveau_fifo_chan *fifo = (void *)chan->object; + struct nouveau_client *client = nouveau_client(fifo); + struct nvc0_fence_priv *priv = chan->drm->fence; + struct nvc0_fence_chan *fctx; + int ret, i; + + fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); + if (!fctx) + return -ENOMEM; + + nouveau_fence_context_new(&fctx->base); + + ret = nouveau_bo_vma_add(priv->bo, client->vm, &fctx->vma); + if (ret) + nvc0_fence_context_del(chan); + + /* map display semaphore buffers into channel's vm */ + for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { + struct nouveau_bo *bo = nv50_display_crtc_sema(chan->drm->dev, i); + ret = nouveau_bo_vma_add(bo, client->vm, &fctx->dispc_vma[i]); } + + nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000); return ret; } +static bool +nvc0_fence_suspend(struct nouveau_drm *drm) +{ + struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); + struct nvc0_fence_priv *priv = drm->fence; + int i; + + priv->suspend = vmalloc((pfifo->max + 1) * sizeof(u32)); + if (priv->suspend) { + for (i = 0; i <= pfifo->max; i++) + priv->suspend[i] = nouveau_bo_rd32(priv->bo, i); + } + + return priv->suspend != NULL; +} + +static void +nvc0_fence_resume(struct nouveau_drm *drm) +{ + struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); + struct nvc0_fence_priv *priv = drm->fence; + int i; + + if (priv->suspend) { + for (i = 0; i <= pfifo->max; i++) + nouveau_bo_wr32(priv->bo, i, priv->suspend[i]); + vfree(priv->suspend); + priv->suspend = NULL; + } +} + +static void +nvc0_fence_destroy(struct nouveau_drm *drm) +{ + struct nvc0_fence_priv *priv = drm->fence; + nouveau_bo_unmap(priv->bo); + if (priv->bo) + nouveau_bo_unpin(priv->bo); + nouveau_bo_ref(NULL, &priv->bo); + drm->fence = NULL; + kfree(priv); +} + int nvc0_fence_create(struct nouveau_drm *drm) { - int ret = nv84_fence_create(drm); + struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); + struct nvc0_fence_priv *priv; + int ret; + + priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->base.dtor = nvc0_fence_destroy; + priv->base.suspend = nvc0_fence_suspend; + priv->base.resume = nvc0_fence_resume; + priv->base.context_new = nvc0_fence_context_new; + priv->base.context_del = nvc0_fence_context_del; + priv->base.emit = nvc0_fence_emit; + priv->base.sync = nvc0_fence_sync; + priv->base.read = nvc0_fence_read; + + ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, + TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo); if (ret == 0) { - struct nv84_fence_priv *priv = drm->fence; - priv->base.context_new = nvc0_fence_context_new; + ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); + if (ret == 0) { + ret = nouveau_bo_map(priv->bo); + if (ret) + nouveau_bo_unpin(priv->bo); + } + if (ret) + nouveau_bo_ref(NULL, &priv->bo); } + + if (ret) + nvc0_fence_destroy(drm); return ret; } diff --git a/trunk/drivers/gpu/drm/omapdrm/TODO b/trunk/drivers/gpu/drm/omapdrm/TODO deleted file mode 100644 index 4d8c18aa5dd7..000000000000 --- a/trunk/drivers/gpu/drm/omapdrm/TODO +++ /dev/null @@ -1,23 +0,0 @@ -TODO -. Where should we do eviction (detatch_pages())? We aren't necessarily - accessing the pages via a GART, so maybe we need some other threshold - to put a cap on the # of pages that can be pin'd. - . Use mm_shrinker to trigger unpinning pages. - . This is mainly theoretical since most of these devices don't actually - have swap or harddrive. -. GEM/shmem backed pages can have existing mappings (kernel linear map, - etc..), which isn't really ideal. -. Revisit GEM sync object infrastructure.. TTM has some framework for this - already. Possibly this could be refactored out and made more common? - There should be some way to do this with less wheel-reinvention. - . This can be handled by the dma-buf fence/reservation stuff when it - lands - -Userspace: -. git://anongit.freedesktop.org/xorg/driver/xf86-video-omap - -Currently tested on -. OMAP3530 beagleboard -. OMAP4430 pandaboard -. OMAP4460 pandaboard -. OMAP5432 uEVM diff --git a/trunk/drivers/gpu/drm/radeon/atom.c b/trunk/drivers/gpu/drm/radeon/atom.c index 46a9c3772850..5ce9bf51a8de 100644 --- a/trunk/drivers/gpu/drm/radeon/atom.c +++ b/trunk/drivers/gpu/drm/radeon/atom.c @@ -1238,8 +1238,6 @@ static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 }; static void atom_index_iio(struct atom_context *ctx, int base) { ctx->iio = kzalloc(2 * 256, GFP_KERNEL); - if (!ctx->iio) - return; while (CU8(base) == ATOM_IIO_START) { ctx->iio[CU8(base + 1)] = base + 2; base += 2; @@ -1289,10 +1287,6 @@ struct atom_context *atom_parse(struct card_info *card, void *bios) ctx->cmd_table = CU16(base + ATOM_ROM_CMD_PTR); ctx->data_table = CU16(base + ATOM_ROM_DATA_PTR); atom_index_iio(ctx, CU16(ctx->data_table + ATOM_DATA_IIO_PTR) + 4); - if (!ctx->iio) { - atom_destroy(ctx); - return NULL; - } str = CSTR(CU16(base + ATOM_ROM_MSG_PTR)); while (*str && ((*str == '\n') || (*str == '\r'))) @@ -1341,7 +1335,8 @@ int atom_asic_init(struct atom_context *ctx) void atom_destroy(struct atom_context *ctx) { - kfree(ctx->iio); + if (ctx->iio) + kfree(ctx->iio); kfree(ctx); } diff --git a/trunk/drivers/gpu/drm/radeon/evergreen.c b/trunk/drivers/gpu/drm/radeon/evergreen.c index 3c38ea46531c..2916de896a60 100644 --- a/trunk/drivers/gpu/drm/radeon/evergreen.c +++ b/trunk/drivers/gpu/drm/radeon/evergreen.c @@ -403,19 +403,6 @@ void evergreen_pm_misc(struct radeon_device *rdev) rdev->pm.current_vddc = voltage->voltage; DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage); } - - /* starting with BTC, there is one state that is used for both - * MH and SH. Difference is that we always use the high clock index for - * mclk and vddci. - */ - if ((rdev->pm.pm_method == PM_METHOD_PROFILE) && - (rdev->family >= CHIP_BARTS) && - rdev->pm.active_crtc_count && - ((rdev->pm.profile_index == PM_PROFILE_MID_MH_IDX) || - (rdev->pm.profile_index == PM_PROFILE_LOW_MH_IDX))) - voltage = &rdev->pm.power_state[req_ps_idx]. - clock_info[rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx].voltage; - /* 0xff01 is a flag rather then an actual voltage */ if (voltage->vddci == 0xff01) return; diff --git a/trunk/drivers/gpu/drm/radeon/r600.c b/trunk/drivers/gpu/drm/radeon/r600.c index 6d4b5611daf4..dbcb0752f083 100644 --- a/trunk/drivers/gpu/drm/radeon/r600.c +++ b/trunk/drivers/gpu/drm/radeon/r600.c @@ -109,19 +109,6 @@ void r600_fini(struct radeon_device *rdev); void r600_irq_disable(struct radeon_device *rdev); static void r600_pcie_gen2_enable(struct radeon_device *rdev); -/** - * r600_get_xclk - get the xclk - * - * @rdev: radeon_device pointer - * - * Returns the reference clock used by the gfx engine - * (r6xx, IGPs, APUs). - */ -u32 r600_get_xclk(struct radeon_device *rdev) -{ - return rdev->clock.spll.reference_freq; -} - /* get temperature in millidegrees */ int rv6xx_get_temp(struct radeon_device *rdev) { @@ -4461,14 +4448,14 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev) } /** - * r600_get_gpu_clock_counter - return GPU clock counter snapshot + * r600_get_gpu_clock - return GPU clock counter snapshot * * @rdev: radeon_device pointer * * Fetches a GPU clock counter snapshot (R6xx-cayman). * Returns the 64 bit clock counter snapshot. */ -uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev) +uint64_t r600_get_gpu_clock(struct radeon_device *rdev) { uint64_t clock; diff --git a/trunk/drivers/gpu/drm/radeon/r600_hdmi.c b/trunk/drivers/gpu/drm/radeon/r600_hdmi.c index 95970ec47c45..ff80efe9cb7d 100644 --- a/trunk/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/trunk/drivers/gpu/drm/radeon/r600_hdmi.c @@ -544,6 +544,7 @@ void r600_hdmi_disable(struct drm_encoder *encoder) /* Called for ATOM_ENCODER_MODE_HDMI only */ if (!dig || !dig->afmt) { + WARN_ON(1); return; } if (!dig->afmt->enabled) diff --git a/trunk/drivers/gpu/drm/radeon/radeon.h b/trunk/drivers/gpu/drm/radeon/radeon.h index 8263af3fd832..bb43a849759b 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon.h +++ b/trunk/drivers/gpu/drm/radeon/radeon.h @@ -1178,10 +1178,6 @@ struct radeon_asic { bool (*gui_idle)(struct radeon_device *rdev); /* wait for mc_idle */ int (*mc_wait_for_idle)(struct radeon_device *rdev); - /* get the reference clock */ - u32 (*get_xclk)(struct radeon_device *rdev); - /* get the gpu clock counter */ - uint64_t (*get_gpu_clock_counter)(struct radeon_device *rdev); /* gart */ struct { void (*tlb_flush)(struct radeon_device *rdev); @@ -1863,8 +1859,6 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v); #define radeon_post_page_flip(rdev, crtc) (rdev)->asic->pflip.post_page_flip((rdev), (crtc)) #define radeon_wait_for_vblank(rdev, crtc) (rdev)->asic->display.wait_for_vblank((rdev), (crtc)) #define radeon_mc_wait_for_idle(rdev) (rdev)->asic->mc_wait_for_idle((rdev)) -#define radeon_get_xclk(rdev) (rdev)->asic->get_xclk((rdev)) -#define radeon_get_gpu_clock_counter(rdev) (rdev)->asic->get_gpu_clock_counter((rdev)) /* Common functions */ /* AGP */ diff --git a/trunk/drivers/gpu/drm/radeon/radeon_asic.c b/trunk/drivers/gpu/drm/radeon/radeon_asic.c index aba0a893ea98..67f008febec7 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_asic.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_asic.c @@ -934,8 +934,6 @@ static struct radeon_asic r600_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &r600_mc_wait_for_idle, - .get_xclk = &r600_get_xclk, - .get_gpu_clock_counter = &r600_get_gpu_clock_counter, .gart = { .tlb_flush = &r600_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, @@ -1020,8 +1018,6 @@ static struct radeon_asic rs780_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &r600_mc_wait_for_idle, - .get_xclk = &r600_get_xclk, - .get_gpu_clock_counter = &r600_get_gpu_clock_counter, .gart = { .tlb_flush = &r600_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, @@ -1106,8 +1102,6 @@ static struct radeon_asic rv770_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &r600_mc_wait_for_idle, - .get_xclk = &rv770_get_xclk, - .get_gpu_clock_counter = &r600_get_gpu_clock_counter, .gart = { .tlb_flush = &r600_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, @@ -1192,8 +1186,6 @@ static struct radeon_asic evergreen_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &evergreen_mc_wait_for_idle, - .get_xclk = &rv770_get_xclk, - .get_gpu_clock_counter = &r600_get_gpu_clock_counter, .gart = { .tlb_flush = &evergreen_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, @@ -1278,8 +1270,6 @@ static struct radeon_asic sumo_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &evergreen_mc_wait_for_idle, - .get_xclk = &r600_get_xclk, - .get_gpu_clock_counter = &r600_get_gpu_clock_counter, .gart = { .tlb_flush = &evergreen_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, @@ -1364,8 +1354,6 @@ static struct radeon_asic btc_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &evergreen_mc_wait_for_idle, - .get_xclk = &rv770_get_xclk, - .get_gpu_clock_counter = &r600_get_gpu_clock_counter, .gart = { .tlb_flush = &evergreen_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, @@ -1450,8 +1438,6 @@ static struct radeon_asic cayman_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &evergreen_mc_wait_for_idle, - .get_xclk = &rv770_get_xclk, - .get_gpu_clock_counter = &r600_get_gpu_clock_counter, .gart = { .tlb_flush = &cayman_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, @@ -1579,8 +1565,6 @@ static struct radeon_asic trinity_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &evergreen_mc_wait_for_idle, - .get_xclk = &r600_get_xclk, - .get_gpu_clock_counter = &r600_get_gpu_clock_counter, .gart = { .tlb_flush = &cayman_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, @@ -1708,8 +1692,6 @@ static struct radeon_asic si_asic = { .ioctl_wait_idle = r600_ioctl_wait_idle, .gui_idle = &r600_gui_idle, .mc_wait_for_idle = &evergreen_mc_wait_for_idle, - .get_xclk = &si_get_xclk, - .get_gpu_clock_counter = &si_get_gpu_clock_counter, .gart = { .tlb_flush = &si_pcie_gart_tlb_flush, .set_page = &rs600_gart_set_page, diff --git a/trunk/drivers/gpu/drm/radeon/radeon_asic.h b/trunk/drivers/gpu/drm/radeon/radeon_asic.h index 3535f73ad3e2..f4134a823958 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_asic.h +++ b/trunk/drivers/gpu/drm/radeon/radeon_asic.h @@ -389,8 +389,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev, unsigned num_gpu_pages, struct radeon_sa_bo *vb); int r600_mc_wait_for_idle(struct radeon_device *rdev); -u32 r600_get_xclk(struct radeon_device *rdev); -uint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev); +uint64_t r600_get_gpu_clock(struct radeon_device *rdev); /* * rv770,rv730,rv710,rv740 @@ -408,7 +407,6 @@ int rv770_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, struct radeon_fence **fence); -u32 rv770_get_xclk(struct radeon_device *rdev); /* * evergreen @@ -517,12 +515,11 @@ void si_vm_set_page(struct radeon_device *rdev, uint32_t incr, uint32_t flags); void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm); int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); +uint64_t si_get_gpu_clock(struct radeon_device *rdev); int si_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, struct radeon_fence **fence); void si_dma_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm); -u32 si_get_xclk(struct radeon_device *rdev); -uint64_t si_get_gpu_clock_counter(struct radeon_device *rdev); #endif diff --git a/trunk/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/trunk/drivers/gpu/drm/radeon/radeon_atpx_handler.c index d96070bf8388..15f5ded65e0c 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -43,12 +43,6 @@ struct atpx_verify_interface { u32 function_bits; /* supported functions bit vector */ } __packed; -struct atpx_px_params { - u16 size; /* structure size in bytes (includes size field) */ - u32 valid_flags; /* which flags are valid */ - u32 flags; /* flags */ -} __packed; - struct atpx_power_control { u16 size; u8 dgpu_state; @@ -128,62 +122,10 @@ static void radeon_atpx_parse_functions(struct radeon_atpx_functions *f, u32 mas f->disp_detetion_ports = mask & ATPX_GET_DISPLAY_DETECTION_PORTS_SUPPORTED; } -/** - * radeon_atpx_validate_functions - validate ATPX functions - * - * @atpx: radeon atpx struct - * - * Validate that required functions are enabled (all asics). - * returns 0 on success, error on failure. - */ -static int radeon_atpx_validate(struct radeon_atpx *atpx) -{ - /* make sure required functions are enabled */ - /* dGPU power control is required */ - atpx->functions.power_cntl = true; - - if (atpx->functions.px_params) { - union acpi_object *info; - struct atpx_px_params output; - size_t size; - u32 valid_bits; - - info = radeon_atpx_call(atpx->handle, ATPX_FUNCTION_GET_PX_PARAMETERS, NULL); - if (!info) - return -EIO; - - memset(&output, 0, sizeof(output)); - - size = *(u16 *) info->buffer.pointer; - if (size < 10) { - printk("ATPX buffer is too small: %zu\n", size); - kfree(info); - return -EINVAL; - } - size = min(sizeof(output), size); - - memcpy(&output, info->buffer.pointer, size); - - valid_bits = output.flags & output.valid_flags; - /* if separate mux flag is set, mux controls are required */ - if (valid_bits & ATPX_SEPARATE_MUX_FOR_I2C) { - atpx->functions.i2c_mux_cntl = true; - atpx->functions.disp_mux_cntl = true; - } - /* if any outputs are muxed, mux controls are required */ - if (valid_bits & (ATPX_CRT1_RGB_SIGNAL_MUXED | - ATPX_TV_SIGNAL_MUXED | - ATPX_DFP_SIGNAL_MUXED)) - atpx->functions.disp_mux_cntl = true; - - kfree(info); - } - return 0; -} - /** * radeon_atpx_verify_interface - verify ATPX * + * @handle: acpi handle * @atpx: radeon atpx struct * * Execute the ATPX_FUNCTION_VERIFY_INTERFACE ATPX function @@ -464,19 +406,8 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) */ static int radeon_atpx_init(void) { - int r; - /* set up the ATPX handle */ - r = radeon_atpx_verify_interface(&radeon_atpx_priv.atpx); - if (r) - return r; - - /* validate the atpx setup */ - r = radeon_atpx_validate(&radeon_atpx_priv.atpx); - if (r) - return r; - - return 0; + return radeon_atpx_verify_interface(&radeon_atpx_priv.atpx); } /** diff --git a/trunk/drivers/gpu/drm/radeon/radeon_device.c b/trunk/drivers/gpu/drm/radeon/radeon_device.c index 44b8034a400d..8794de10a6c7 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_device.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_device.c @@ -759,11 +759,6 @@ int radeon_atombios_init(struct radeon_device *rdev) atom_card_info->pll_write = cail_pll_write; rdev->mode_info.atom_context = atom_parse(atom_card_info, rdev->bios); - if (!rdev->mode_info.atom_context) { - radeon_atombios_fini(rdev); - return -ENOMEM; - } - mutex_init(&rdev->mode_info.atom_context->mutex); radeon_atom_initialize_bios_scratch_regs(rdev->ddev); atom_allocate_fb_scratch(rdev->mode_info.atom_context); @@ -783,11 +778,9 @@ void radeon_atombios_fini(struct radeon_device *rdev) { if (rdev->mode_info.atom_context) { kfree(rdev->mode_info.atom_context->scratch); + kfree(rdev->mode_info.atom_context); } - kfree(rdev->mode_info.atom_context); - rdev->mode_info.atom_context = NULL; kfree(rdev->mode_info.atom_card_info); - rdev->mode_info.atom_card_info = NULL; } /* COMBIOS */ diff --git a/trunk/drivers/gpu/drm/radeon/radeon_fb.c b/trunk/drivers/gpu/drm/radeon/radeon_fb.c index b1746741bc59..515e5ee1f9ee 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_fb.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_fb.c @@ -187,10 +187,9 @@ static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, return ret; } -static int radeonfb_create(struct drm_fb_helper *helper, +static int radeonfb_create(struct radeon_fbdev *rfbdev, struct drm_fb_helper_surface_size *sizes) { - struct radeon_fbdev *rfbdev = (struct radeon_fbdev *)helper; struct radeon_device *rdev = rfbdev->rdev; struct fb_info *info; struct drm_framebuffer *fb = NULL; @@ -301,6 +300,22 @@ static int radeonfb_create(struct drm_fb_helper *helper, return ret; } +static int radeon_fb_find_or_create_single(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + struct radeon_fbdev *rfbdev = (struct radeon_fbdev *)helper; + int new_fb = 0; + int ret; + + if (!helper->fb) { + ret = radeonfb_create(rfbdev, sizes); + if (ret) + return ret; + new_fb = 1; + } + return new_fb; +} + void radeon_fb_output_poll_changed(struct radeon_device *rdev) { drm_fb_helper_hotplug_event(&rdev->mode_info.rfbdev->helper); @@ -334,7 +349,7 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb static struct drm_fb_helper_funcs radeon_fb_helper_funcs = { .gamma_set = radeon_crtc_fb_gamma_set, .gamma_get = radeon_crtc_fb_gamma_get, - .fb_probe = radeonfb_create, + .fb_probe = radeon_fb_find_or_create_single, }; int radeon_fbdev_init(struct radeon_device *rdev) @@ -364,10 +379,6 @@ int radeon_fbdev_init(struct radeon_device *rdev) } drm_fb_helper_single_add_all_connectors(&rfbdev->helper); - - /* disable all the possible outputs/crtcs before entering KMS mode */ - drm_helper_disable_unused_functions(rdev->ddev); - drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); return 0; } diff --git a/trunk/drivers/gpu/drm/radeon/radeon_kms.c b/trunk/drivers/gpu/drm/radeon/radeon_kms.c index c75cb2c6ba71..9c312f9afb68 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_kms.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_kms.c @@ -185,7 +185,11 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) if (info->request == RADEON_INFO_TIMESTAMP) { if (rdev->family >= CHIP_R600) { value_ptr64 = (uint64_t*)((unsigned long)info->value); - value64 = radeon_get_gpu_clock_counter(rdev); + if (rdev->family >= CHIP_TAHITI) { + value64 = si_get_gpu_clock(rdev); + } else { + value64 = r600_get_gpu_clock(rdev); + } if (DRM_COPY_TO_USER(value_ptr64, &value64, sizeof(value64))) { DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__); @@ -278,10 +282,7 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) break; case RADEON_INFO_CLOCK_CRYSTAL_FREQ: /* return clock value in KHz */ - if (rdev->asic->get_xclk) - value = radeon_get_xclk(rdev) * 10; - else - value = rdev->clock.spll.reference_freq * 10; + value = rdev->clock.spll.reference_freq * 10; break; case RADEON_INFO_NUM_BACKENDS: if (rdev->family >= CHIP_TAHITI) diff --git a/trunk/drivers/gpu/drm/radeon/radeon_pm.c b/trunk/drivers/gpu/drm/radeon/radeon_pm.c index 338fd6a74e87..0bfa656aa87d 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_pm.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_pm.c @@ -169,7 +169,7 @@ static void radeon_set_power_state(struct radeon_device *rdev) /* starting with BTC, there is one state that is used for both * MH and SH. Difference is that we always use the high clock index for - * mclk and vddci. + * mclk. */ if ((rdev->pm.pm_method == PM_METHOD_PROFILE) && (rdev->family >= CHIP_BARTS) && diff --git a/trunk/drivers/gpu/drm/radeon/radeon_ttm.c b/trunk/drivers/gpu/drm/radeon/radeon_ttm.c index 93f760e27a92..1d8ff2f850ba 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_ttm.c @@ -38,7 +38,6 @@ #include #include #include -#include #include "radeon_reg.h" #include "radeon.h" diff --git a/trunk/drivers/gpu/drm/radeon/rv770.c b/trunk/drivers/gpu/drm/radeon/rv770.c index d63fe1d0f53f..1b2444f4d8f4 100644 --- a/trunk/drivers/gpu/drm/radeon/rv770.c +++ b/trunk/drivers/gpu/drm/radeon/rv770.c @@ -43,31 +43,6 @@ static void rv770_gpu_init(struct radeon_device *rdev); void rv770_fini(struct radeon_device *rdev); static void rv770_pcie_gen2_enable(struct radeon_device *rdev); -#define PCIE_BUS_CLK 10000 -#define TCLK (PCIE_BUS_CLK / 10) - -/** - * rv770_get_xclk - get the xclk - * - * @rdev: radeon_device pointer - * - * Returns the reference clock used by the gfx engine - * (r7xx-cayman). - */ -u32 rv770_get_xclk(struct radeon_device *rdev) -{ - u32 reference_clock = rdev->clock.spll.reference_freq; - u32 tmp = RREG32(CG_CLKPIN_CNTL); - - if (tmp & MUX_TCLK_TO_XCLK) - return TCLK; - - if (tmp & XTALIN_DIVIDE) - return reference_clock / 4; - - return reference_clock; -} - u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) { struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; diff --git a/trunk/drivers/gpu/drm/radeon/rv770d.h b/trunk/drivers/gpu/drm/radeon/rv770d.h index c55f950a4af7..20e29d23d348 100644 --- a/trunk/drivers/gpu/drm/radeon/rv770d.h +++ b/trunk/drivers/gpu/drm/radeon/rv770d.h @@ -128,10 +128,6 @@ #define GUI_ACTIVE (1<<31) #define GRBM_STATUS2 0x8014 -#define CG_CLKPIN_CNTL 0x660 -# define MUX_TCLK_TO_XCLK (1 << 8) -# define XTALIN_DIVIDE (1 << 9) - #define CG_MULT_THERMAL_STATUS 0x740 #define ASIC_T(x) ((x) << 16) #define ASIC_T_MASK 0x3FF0000 diff --git a/trunk/drivers/gpu/drm/radeon/si.c b/trunk/drivers/gpu/drm/radeon/si.c index 80979ed951eb..719f03e061db 100644 --- a/trunk/drivers/gpu/drm/radeon/si.c +++ b/trunk/drivers/gpu/drm/radeon/si.c @@ -70,33 +70,6 @@ extern u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev); extern void evergreen_print_gpu_status_regs(struct radeon_device *rdev); extern bool evergreen_is_display_hung(struct radeon_device *rdev); -#define PCIE_BUS_CLK 10000 -#define TCLK (PCIE_BUS_CLK / 10) - -/** - * si_get_xclk - get the xclk - * - * @rdev: radeon_device pointer - * - * Returns the reference clock used by the gfx engine - * (SI). - */ -u32 si_get_xclk(struct radeon_device *rdev) -{ - u32 reference_clock = rdev->clock.spll.reference_freq; - u32 tmp; - - tmp = RREG32(CG_CLKPIN_CNTL_2); - if (tmp & MUX_TCLK_TO_XCLK) - return TCLK; - - tmp = RREG32(CG_CLKPIN_CNTL); - if (tmp & XTALIN_DIVIDE) - return reference_clock / 4; - - return reference_clock; -} - /* get temperature in millidegrees */ int si_get_temp(struct radeon_device *rdev) { @@ -4609,14 +4582,14 @@ void si_fini(struct radeon_device *rdev) } /** - * si_get_gpu_clock_counter - return GPU clock counter snapshot + * si_get_gpu_clock - return GPU clock counter snapshot * * @rdev: radeon_device pointer * * Fetches a GPU clock counter snapshot (SI). * Returns the 64 bit clock counter snapshot. */ -uint64_t si_get_gpu_clock_counter(struct radeon_device *rdev) +uint64_t si_get_gpu_clock(struct radeon_device *rdev) { uint64_t clock; diff --git a/trunk/drivers/gpu/drm/radeon/sid.h b/trunk/drivers/gpu/drm/radeon/sid.h index 23fc08fc8e7f..07fc455e35ae 100644 --- a/trunk/drivers/gpu/drm/radeon/sid.h +++ b/trunk/drivers/gpu/drm/radeon/sid.h @@ -58,11 +58,6 @@ #define VGA_HDP_CONTROL 0x328 #define VGA_MEMORY_DISABLE (1 << 4) -#define CG_CLKPIN_CNTL 0x660 -# define XTALIN_DIVIDE (1 << 1) -#define CG_CLKPIN_CNTL_2 0x664 -# define MUX_TCLK_TO_XCLK (1 << 8) - #define DMIF_ADDR_CONFIG 0xBD4 #define SRBM_STATUS 0xE50 diff --git a/trunk/drivers/gpu/drm/tegra/dc.c b/trunk/drivers/gpu/drm/tegra/dc.c index bf8095c55bd1..656b2e3334a6 100644 --- a/trunk/drivers/gpu/drm/tegra/dc.c +++ b/trunk/drivers/gpu/drm/tegra/dc.c @@ -18,257 +18,26 @@ #include "drm.h" #include "dc.h" -struct tegra_plane { - struct drm_plane base; - unsigned int index; +struct tegra_dc_window { + fixed20_12 x; + fixed20_12 y; + fixed20_12 w; + fixed20_12 h; + unsigned int outx; + unsigned int outy; + unsigned int outw; + unsigned int outh; + unsigned int stride; + unsigned int fmt; }; -static inline struct tegra_plane *to_tegra_plane(struct drm_plane *plane) -{ - return container_of(plane, struct tegra_plane, base); -} - -static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, - struct drm_framebuffer *fb, int crtc_x, - int crtc_y, unsigned int crtc_w, - unsigned int crtc_h, uint32_t src_x, - uint32_t src_y, uint32_t src_w, uint32_t src_h) -{ - struct tegra_plane *p = to_tegra_plane(plane); - struct tegra_dc *dc = to_tegra_dc(crtc); - struct tegra_dc_window window; - unsigned int i; - - memset(&window, 0, sizeof(window)); - window.src.x = src_x >> 16; - window.src.y = src_y >> 16; - window.src.w = src_w >> 16; - window.src.h = src_h >> 16; - window.dst.x = crtc_x; - window.dst.y = crtc_y; - window.dst.w = crtc_w; - window.dst.h = crtc_h; - window.format = tegra_dc_format(fb->pixel_format); - window.bits_per_pixel = fb->bits_per_pixel; - - for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { - struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i); - - window.base[i] = gem->paddr + fb->offsets[i]; - - /* - * Tegra doesn't support different strides for U and V planes - * so we display a warning if the user tries to display a - * framebuffer with such a configuration. - */ - if (i >= 2) { - if (fb->pitches[i] != window.stride[1]) - DRM_ERROR("unsupported UV-plane configuration\n"); - } else { - window.stride[i] = fb->pitches[i]; - } - } - - return tegra_dc_setup_window(dc, p->index, &window); -} - -static int tegra_plane_disable(struct drm_plane *plane) -{ - struct tegra_dc *dc = to_tegra_dc(plane->crtc); - struct tegra_plane *p = to_tegra_plane(plane); - unsigned long value; - - value = WINDOW_A_SELECT << p->index; - tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); - - value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS); - value &= ~WIN_ENABLE; - tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS); - - tegra_dc_writel(dc, WIN_A_UPDATE << p->index, DC_CMD_STATE_CONTROL); - tegra_dc_writel(dc, WIN_A_ACT_REQ << p->index, DC_CMD_STATE_CONTROL); - - return 0; -} - -static void tegra_plane_destroy(struct drm_plane *plane) -{ - tegra_plane_disable(plane); - drm_plane_cleanup(plane); -} - -static const struct drm_plane_funcs tegra_plane_funcs = { - .update_plane = tegra_plane_update, - .disable_plane = tegra_plane_disable, - .destroy = tegra_plane_destroy, -}; - -static const uint32_t plane_formats[] = { - DRM_FORMAT_XRGB8888, - DRM_FORMAT_UYVY, - DRM_FORMAT_YUV420, - DRM_FORMAT_YUV422, -}; - -static int tegra_dc_add_planes(struct drm_device *drm, struct tegra_dc *dc) -{ - unsigned int i; - int err = 0; - - for (i = 0; i < 2; i++) { - struct tegra_plane *plane; - - plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL); - if (!plane) - return -ENOMEM; - - plane->index = 1 + i; - - err = drm_plane_init(drm, &plane->base, 1 << dc->pipe, - &tegra_plane_funcs, plane_formats, - ARRAY_SIZE(plane_formats), false); - if (err < 0) - return err; - } - - return 0; -} - -static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, - struct drm_framebuffer *fb) -{ - struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, 0); - unsigned long value; - - tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); - - value = fb->offsets[0] + y * fb->pitches[0] + - x * fb->bits_per_pixel / 8; - - tegra_dc_writel(dc, gem->paddr + value, DC_WINBUF_START_ADDR); - tegra_dc_writel(dc, fb->pitches[0], DC_WIN_LINE_STRIDE); - - value = GENERAL_UPDATE | WIN_A_UPDATE; - tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); - - value = GENERAL_ACT_REQ | WIN_A_ACT_REQ; - tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); - - return 0; -} - -void tegra_dc_enable_vblank(struct tegra_dc *dc) -{ - unsigned long value, flags; - - spin_lock_irqsave(&dc->lock, flags); - - value = tegra_dc_readl(dc, DC_CMD_INT_MASK); - value |= VBLANK_INT; - tegra_dc_writel(dc, value, DC_CMD_INT_MASK); - - spin_unlock_irqrestore(&dc->lock, flags); -} - -void tegra_dc_disable_vblank(struct tegra_dc *dc) -{ - unsigned long value, flags; - - spin_lock_irqsave(&dc->lock, flags); - - value = tegra_dc_readl(dc, DC_CMD_INT_MASK); - value &= ~VBLANK_INT; - tegra_dc_writel(dc, value, DC_CMD_INT_MASK); - - spin_unlock_irqrestore(&dc->lock, flags); -} - -static void tegra_dc_finish_page_flip(struct tegra_dc *dc) -{ - struct drm_device *drm = dc->base.dev; - struct drm_crtc *crtc = &dc->base; - struct drm_gem_cma_object *gem; - unsigned long flags, base; - - if (!dc->event) - return; - - gem = drm_fb_cma_get_gem_obj(crtc->fb, 0); - - /* check if new start address has been latched */ - tegra_dc_writel(dc, READ_MUX, DC_CMD_STATE_ACCESS); - base = tegra_dc_readl(dc, DC_WINBUF_START_ADDR); - tegra_dc_writel(dc, 0, DC_CMD_STATE_ACCESS); - - if (base == gem->paddr + crtc->fb->offsets[0]) { - spin_lock_irqsave(&drm->event_lock, flags); - drm_send_vblank_event(drm, dc->pipe, dc->event); - drm_vblank_put(drm, dc->pipe); - dc->event = NULL; - spin_unlock_irqrestore(&drm->event_lock, flags); - } -} - -void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) -{ - struct tegra_dc *dc = to_tegra_dc(crtc); - struct drm_device *drm = crtc->dev; - unsigned long flags; - - spin_lock_irqsave(&drm->event_lock, flags); - - if (dc->event && dc->event->base.file_priv == file) { - dc->event->base.destroy(&dc->event->base); - drm_vblank_put(drm, dc->pipe); - dc->event = NULL; - } - - spin_unlock_irqrestore(&drm->event_lock, flags); -} - -static int tegra_dc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event) -{ - struct tegra_dc *dc = to_tegra_dc(crtc); - struct drm_device *drm = crtc->dev; - - if (dc->event) - return -EBUSY; - - if (event) { - event->pipe = dc->pipe; - dc->event = event; - drm_vblank_get(drm, dc->pipe); - } - - tegra_dc_set_base(dc, 0, 0, fb); - crtc->fb = fb; - - return 0; -} - static const struct drm_crtc_funcs tegra_crtc_funcs = { - .page_flip = tegra_dc_page_flip, .set_config = drm_crtc_helper_set_config, .destroy = drm_crtc_cleanup, }; -static void tegra_crtc_disable(struct drm_crtc *crtc) +static void tegra_crtc_dpms(struct drm_crtc *crtc, int mode) { - struct drm_device *drm = crtc->dev; - struct drm_plane *plane; - - list_for_each_entry(plane, &drm->mode_config.plane_list, head) { - if (plane->crtc == crtc) { - tegra_plane_disable(plane); - plane->crtc = NULL; - - if (plane->fb) { - drm_framebuffer_unreference(plane->fb); - plane->fb = NULL; - } - } - } } static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc, @@ -278,11 +47,10 @@ static bool tegra_crtc_mode_fixup(struct drm_crtc *crtc, return true; } -static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v, +static inline u32 compute_dda_inc(fixed20_12 inf, unsigned int out, bool v, unsigned int bpp) { fixed20_12 outf = dfixed_init(out); - fixed20_12 inf = dfixed_init(in); u32 dda_inc; int max; @@ -312,10 +80,9 @@ static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v, return dda_inc; } -static inline u32 compute_initial_dda(unsigned int in) +static inline u32 compute_initial_dda(fixed20_12 in) { - fixed20_12 inf = dfixed_init(in); - return dfixed_frac(inf); + return dfixed_frac(in); } static int tegra_dc_set_timings(struct tegra_dc *dc, @@ -386,198 +153,18 @@ static int tegra_crtc_setup_clk(struct drm_crtc *crtc, return 0; } -static bool tegra_dc_format_is_yuv(unsigned int format, bool *planar) -{ - switch (format) { - case WIN_COLOR_DEPTH_YCbCr422: - case WIN_COLOR_DEPTH_YUV422: - if (planar) - *planar = false; - - return true; - - case WIN_COLOR_DEPTH_YCbCr420P: - case WIN_COLOR_DEPTH_YUV420P: - case WIN_COLOR_DEPTH_YCbCr422P: - case WIN_COLOR_DEPTH_YUV422P: - case WIN_COLOR_DEPTH_YCbCr422R: - case WIN_COLOR_DEPTH_YUV422R: - case WIN_COLOR_DEPTH_YCbCr422RA: - case WIN_COLOR_DEPTH_YUV422RA: - if (planar) - *planar = true; - - return true; - } - - return false; -} - -int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, - const struct tegra_dc_window *window) -{ - unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp; - unsigned long value; - bool yuv, planar; - - /* - * For YUV planar modes, the number of bytes per pixel takes into - * account only the luma component and therefore is 1. - */ - yuv = tegra_dc_format_is_yuv(window->format, &planar); - if (!yuv) - bpp = window->bits_per_pixel / 8; - else - bpp = planar ? 1 : 2; - - value = WINDOW_A_SELECT << index; - tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); - - tegra_dc_writel(dc, window->format, DC_WIN_COLOR_DEPTH); - tegra_dc_writel(dc, 0, DC_WIN_BYTE_SWAP); - - value = V_POSITION(window->dst.y) | H_POSITION(window->dst.x); - tegra_dc_writel(dc, value, DC_WIN_POSITION); - - value = V_SIZE(window->dst.h) | H_SIZE(window->dst.w); - tegra_dc_writel(dc, value, DC_WIN_SIZE); - - h_offset = window->src.x * bpp; - v_offset = window->src.y; - h_size = window->src.w * bpp; - v_size = window->src.h; - - value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size); - tegra_dc_writel(dc, value, DC_WIN_PRESCALED_SIZE); - - /* - * For DDA computations the number of bytes per pixel for YUV planar - * modes needs to take into account all Y, U and V components. - */ - if (yuv && planar) - bpp = 2; - - h_dda = compute_dda_inc(window->src.w, window->dst.w, false, bpp); - v_dda = compute_dda_inc(window->src.h, window->dst.h, true, bpp); - - value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda); - tegra_dc_writel(dc, value, DC_WIN_DDA_INC); - - h_dda = compute_initial_dda(window->src.x); - v_dda = compute_initial_dda(window->src.y); - - tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA); - tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA); - - tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE); - tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE); - - tegra_dc_writel(dc, window->base[0], DC_WINBUF_START_ADDR); - - if (yuv && planar) { - tegra_dc_writel(dc, window->base[1], DC_WINBUF_START_ADDR_U); - tegra_dc_writel(dc, window->base[2], DC_WINBUF_START_ADDR_V); - value = window->stride[1] << 16 | window->stride[0]; - tegra_dc_writel(dc, value, DC_WIN_LINE_STRIDE); - } else { - tegra_dc_writel(dc, window->stride[0], DC_WIN_LINE_STRIDE); - } - - tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET); - tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET); - - value = WIN_ENABLE; - - if (yuv) { - /* setup default colorspace conversion coefficients */ - tegra_dc_writel(dc, 0x00f0, DC_WIN_CSC_YOF); - tegra_dc_writel(dc, 0x012a, DC_WIN_CSC_KYRGB); - tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KUR); - tegra_dc_writel(dc, 0x0198, DC_WIN_CSC_KVR); - tegra_dc_writel(dc, 0x039b, DC_WIN_CSC_KUG); - tegra_dc_writel(dc, 0x032f, DC_WIN_CSC_KVG); - tegra_dc_writel(dc, 0x0204, DC_WIN_CSC_KUB); - tegra_dc_writel(dc, 0x0000, DC_WIN_CSC_KVB); - - value |= CSC_ENABLE; - } else if (window->bits_per_pixel < 24) { - value |= COLOR_EXPAND; - } - - tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS); - - /* - * Disable blending and assume Window A is the bottom-most window, - * Window C is the top-most window and Window B is in the middle. - */ - tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_NOKEY); - tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_1WIN); - - switch (index) { - case 0: - tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_X); - tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y); - tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY); - break; - - case 1: - tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X); - tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_2WIN_Y); - tegra_dc_writel(dc, 0x000000, DC_WIN_BLEND_3WIN_XY); - break; - - case 2: - tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_X); - tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_2WIN_Y); - tegra_dc_writel(dc, 0xffff00, DC_WIN_BLEND_3WIN_XY); - break; - } - - tegra_dc_writel(dc, WIN_A_UPDATE << index, DC_CMD_STATE_CONTROL); - tegra_dc_writel(dc, WIN_A_ACT_REQ << index, DC_CMD_STATE_CONTROL); - - return 0; -} - -unsigned int tegra_dc_format(uint32_t format) -{ - switch (format) { - case DRM_FORMAT_XRGB8888: - return WIN_COLOR_DEPTH_B8G8R8A8; - - case DRM_FORMAT_RGB565: - return WIN_COLOR_DEPTH_B5G6R5; - - case DRM_FORMAT_UYVY: - return WIN_COLOR_DEPTH_YCbCr422; - - case DRM_FORMAT_YUV420: - return WIN_COLOR_DEPTH_YCbCr420P; - - case DRM_FORMAT_YUV422: - return WIN_COLOR_DEPTH_YCbCr422P; - - default: - break; - } - - WARN(1, "unsupported pixel format %u, using default\n", format); - return WIN_COLOR_DEPTH_B8G8R8A8; -} - static int tegra_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted, int x, int y, struct drm_framebuffer *old_fb) { - struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(crtc->fb, 0); + struct tegra_framebuffer *fb = to_tegra_fb(crtc->fb); struct tegra_dc *dc = to_tegra_dc(crtc); - struct tegra_dc_window window; + unsigned int h_dda, v_dda, bpp; + struct tegra_dc_window win; unsigned long div, value; int err; - drm_vblank_pre_modeset(crtc->dev, dc->pipe); - err = tegra_crtc_setup_clk(crtc, mode, &div); if (err) { dev_err(dc->dev, "failed to setup clock for CRTC: %d\n", err); @@ -605,33 +192,83 @@ static int tegra_crtc_mode_set(struct drm_crtc *crtc, tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL); /* setup window parameters */ - memset(&window, 0, sizeof(window)); - window.src.x = 0; - window.src.y = 0; - window.src.w = mode->hdisplay; - window.src.h = mode->vdisplay; - window.dst.x = 0; - window.dst.y = 0; - window.dst.w = mode->hdisplay; - window.dst.h = mode->vdisplay; - window.format = tegra_dc_format(crtc->fb->pixel_format); - window.bits_per_pixel = crtc->fb->bits_per_pixel; - window.stride[0] = crtc->fb->pitches[0]; - window.base[0] = gem->paddr; - - err = tegra_dc_setup_window(dc, 0, &window); - if (err < 0) - dev_err(dc->dev, "failed to enable root plane\n"); + memset(&win, 0, sizeof(win)); + win.x.full = dfixed_const(0); + win.y.full = dfixed_const(0); + win.w.full = dfixed_const(mode->hdisplay); + win.h.full = dfixed_const(mode->vdisplay); + win.outx = 0; + win.outy = 0; + win.outw = mode->hdisplay; + win.outh = mode->vdisplay; + + switch (crtc->fb->pixel_format) { + case DRM_FORMAT_XRGB8888: + win.fmt = WIN_COLOR_DEPTH_B8G8R8A8; + break; - return 0; -} + case DRM_FORMAT_RGB565: + win.fmt = WIN_COLOR_DEPTH_B5G6R5; + break; -static int tegra_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) -{ - struct tegra_dc *dc = to_tegra_dc(crtc); + default: + win.fmt = WIN_COLOR_DEPTH_B8G8R8A8; + WARN_ON(1); + break; + } + + bpp = crtc->fb->bits_per_pixel / 8; + win.stride = crtc->fb->pitches[0]; + + /* program window registers */ + value = WINDOW_A_SELECT; + tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); + + tegra_dc_writel(dc, win.fmt, DC_WIN_COLOR_DEPTH); + tegra_dc_writel(dc, 0, DC_WIN_BYTE_SWAP); + + value = V_POSITION(win.outy) | H_POSITION(win.outx); + tegra_dc_writel(dc, value, DC_WIN_POSITION); + + value = V_SIZE(win.outh) | H_SIZE(win.outw); + tegra_dc_writel(dc, value, DC_WIN_SIZE); + + value = V_PRESCALED_SIZE(dfixed_trunc(win.h)) | + H_PRESCALED_SIZE(dfixed_trunc(win.w) * bpp); + tegra_dc_writel(dc, value, DC_WIN_PRESCALED_SIZE); + + h_dda = compute_dda_inc(win.w, win.outw, false, bpp); + v_dda = compute_dda_inc(win.h, win.outh, true, bpp); + + value = V_DDA_INC(v_dda) | H_DDA_INC(h_dda); + tegra_dc_writel(dc, value, DC_WIN_DDA_INC); + + h_dda = compute_initial_dda(win.x); + v_dda = compute_initial_dda(win.y); - return tegra_dc_set_base(dc, x, y, crtc->fb); + tegra_dc_writel(dc, h_dda, DC_WIN_H_INITIAL_DDA); + tegra_dc_writel(dc, v_dda, DC_WIN_V_INITIAL_DDA); + + tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE); + tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE); + + tegra_dc_writel(dc, fb->obj->paddr, DC_WINBUF_START_ADDR); + tegra_dc_writel(dc, win.stride, DC_WIN_LINE_STRIDE); + tegra_dc_writel(dc, dfixed_trunc(win.x) * bpp, + DC_WINBUF_ADDR_H_OFFSET); + tegra_dc_writel(dc, dfixed_trunc(win.y), DC_WINBUF_ADDR_V_OFFSET); + + value = WIN_ENABLE; + + if (bpp < 24) + value |= COLOR_EXPAND; + + tegra_dc_writel(dc, value, DC_WIN_WIN_OPTIONS); + + tegra_dc_writel(dc, 0xff00, DC_WIN_BLEND_NOKEY); + tegra_dc_writel(dc, 0xff00, DC_WIN_BLEND_1WIN); + + return 0; } static void tegra_crtc_prepare(struct drm_crtc *crtc) @@ -678,24 +315,31 @@ static void tegra_crtc_prepare(struct drm_crtc *crtc) tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER); value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT; - tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE); - - value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT; tegra_dc_writel(dc, value, DC_CMD_INT_MASK); + + value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT; + tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE); } static void tegra_crtc_commit(struct drm_crtc *crtc) { struct tegra_dc *dc = to_tegra_dc(crtc); + unsigned long update_mask; unsigned long value; - value = GENERAL_UPDATE | WIN_A_UPDATE; - tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); + update_mask = GENERAL_ACT_REQ | WIN_A_ACT_REQ; + + tegra_dc_writel(dc, update_mask << 8, DC_CMD_STATE_CONTROL); - value = GENERAL_ACT_REQ | WIN_A_ACT_REQ; - tegra_dc_writel(dc, value, DC_CMD_STATE_CONTROL); + value = tegra_dc_readl(dc, DC_CMD_INT_ENABLE); + value |= FRAME_END_INT; + tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE); + + value = tegra_dc_readl(dc, DC_CMD_INT_MASK); + value |= FRAME_END_INT; + tegra_dc_writel(dc, value, DC_CMD_INT_MASK); - drm_vblank_post_modeset(crtc->dev, dc->pipe); + tegra_dc_writel(dc, update_mask, DC_CMD_STATE_CONTROL); } static void tegra_crtc_load_lut(struct drm_crtc *crtc) @@ -703,16 +347,15 @@ static void tegra_crtc_load_lut(struct drm_crtc *crtc) } static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = { - .disable = tegra_crtc_disable, + .dpms = tegra_crtc_dpms, .mode_fixup = tegra_crtc_mode_fixup, .mode_set = tegra_crtc_mode_set, - .mode_set_base = tegra_crtc_mode_set_base, .prepare = tegra_crtc_prepare, .commit = tegra_crtc_commit, .load_lut = tegra_crtc_load_lut, }; -static irqreturn_t tegra_dc_irq(int irq, void *data) +static irqreturn_t tegra_drm_irq(int irq, void *data) { struct tegra_dc *dc = data; unsigned long status; @@ -731,7 +374,6 @@ static irqreturn_t tegra_dc_irq(int irq, void *data) dev_dbg(dc->dev, "%s(): vertical blank\n", __func__); */ drm_handle_vblank(dc->base.dev, dc->pipe); - tegra_dc_finish_page_flip(dc); } if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) { @@ -946,7 +588,7 @@ static int tegra_dc_show_regs(struct seq_file *s, void *data) DUMP_REG(DC_WIN_BLEND_1WIN); DUMP_REG(DC_WIN_BLEND_2WIN_X); DUMP_REG(DC_WIN_BLEND_2WIN_Y); - DUMP_REG(DC_WIN_BLEND_3WIN_XY); + DUMP_REG(DC_WIN_BLEND32WIN_XY); DUMP_REG(DC_WIN_HP_FETCH_CONTROL); DUMP_REG(DC_WINBUF_START_ADDR); DUMP_REG(DC_WINBUF_START_ADDR_NS); @@ -1048,17 +690,13 @@ static int tegra_dc_drm_init(struct host1x_client *client, return err; } - err = tegra_dc_add_planes(drm, dc); - if (err < 0) - return err; - if (IS_ENABLED(CONFIG_DEBUG_FS)) { err = tegra_dc_debugfs_init(dc, drm->primary); if (err < 0) dev_err(dc->dev, "debugfs setup failed: %d\n", err); } - err = devm_request_irq(dc->dev, dc->irq, tegra_dc_irq, 0, + err = devm_request_irq(dc->dev, dc->irq, tegra_drm_irq, 0, dev_name(dc->dev), dc); if (err < 0) { dev_err(dc->dev, "failed to request IRQ#%u: %d\n", dc->irq, @@ -1107,7 +745,6 @@ static int tegra_dc_probe(struct platform_device *pdev) if (!dc) return -ENOMEM; - spin_lock_init(&dc->lock); INIT_LIST_HEAD(&dc->list); dc->dev = &pdev->dev; diff --git a/trunk/drivers/gpu/drm/tegra/dc.h b/trunk/drivers/gpu/drm/tegra/dc.h index 79eaec9aac77..99977b5d5c36 100644 --- a/trunk/drivers/gpu/drm/tegra/dc.h +++ b/trunk/drivers/gpu/drm/tegra/dc.h @@ -58,8 +58,6 @@ #define DC_CMD_SIGNAL_RAISE3 0x03e #define DC_CMD_STATE_ACCESS 0x040 -#define READ_MUX (1 << 0) -#define WRITE_MUX (1 << 2) #define DC_CMD_STATE_CONTROL 0x041 #define GENERAL_ACT_REQ (1 << 0) @@ -292,18 +290,8 @@ #define DC_DISP_SD_HW_K_VALUES 0x4dd #define DC_DISP_SD_MAN_K_VALUES 0x4de -#define DC_WIN_CSC_YOF 0x611 -#define DC_WIN_CSC_KYRGB 0x612 -#define DC_WIN_CSC_KUR 0x613 -#define DC_WIN_CSC_KVR 0x614 -#define DC_WIN_CSC_KUG 0x615 -#define DC_WIN_CSC_KVG 0x616 -#define DC_WIN_CSC_KUB 0x617 -#define DC_WIN_CSC_KVB 0x618 - #define DC_WIN_WIN_OPTIONS 0x700 #define COLOR_EXPAND (1 << 6) -#define CSC_ENABLE (1 << 18) #define WIN_ENABLE (1 << 30) #define DC_WIN_BYTE_SWAP 0x701 @@ -371,7 +359,7 @@ #define DC_WIN_BLEND_1WIN 0x710 #define DC_WIN_BLEND_2WIN_X 0x711 #define DC_WIN_BLEND_2WIN_Y 0x712 -#define DC_WIN_BLEND_3WIN_XY 0x713 +#define DC_WIN_BLEND32WIN_XY 0x713 #define DC_WIN_HP_FETCH_CONTROL 0x714 diff --git a/trunk/drivers/gpu/drm/tegra/drm.c b/trunk/drivers/gpu/drm/tegra/drm.c index 181a370c56c1..3a503c9e4686 100644 --- a/trunk/drivers/gpu/drm/tegra/drm.c +++ b/trunk/drivers/gpu/drm/tegra/drm.c @@ -40,10 +40,6 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) if (err < 0) return err; - err = drm_vblank_init(drm, drm->mode_config.num_crtc); - if (err < 0) - return err; - err = tegra_drm_fb_init(drm); if (err < 0) return err; @@ -93,112 +89,13 @@ static const struct file_operations tegra_drm_fops = { .llseek = noop_llseek, }; -static struct drm_crtc *tegra_crtc_from_pipe(struct drm_device *drm, int pipe) -{ - struct drm_crtc *crtc; - - list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) { - struct tegra_dc *dc = to_tegra_dc(crtc); - - if (dc->pipe == pipe) - return crtc; - } - - return NULL; -} - -static u32 tegra_drm_get_vblank_counter(struct drm_device *dev, int crtc) -{ - /* TODO: implement real hardware counter using syncpoints */ - return drm_vblank_count(dev, crtc); -} - -static int tegra_drm_enable_vblank(struct drm_device *drm, int pipe) -{ - struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe); - struct tegra_dc *dc = to_tegra_dc(crtc); - - if (!crtc) - return -ENODEV; - - tegra_dc_enable_vblank(dc); - - return 0; -} - -static void tegra_drm_disable_vblank(struct drm_device *drm, int pipe) -{ - struct drm_crtc *crtc = tegra_crtc_from_pipe(drm, pipe); - struct tegra_dc *dc = to_tegra_dc(crtc); - - if (crtc) - tegra_dc_disable_vblank(dc); -} - -static void tegra_drm_preclose(struct drm_device *drm, struct drm_file *file) -{ - struct drm_crtc *crtc; - - list_for_each_entry(crtc, &drm->mode_config.crtc_list, head) - tegra_dc_cancel_page_flip(crtc, file); -} - -#ifdef CONFIG_DEBUG_FS -static int tegra_debugfs_framebuffers(struct seq_file *s, void *data) -{ - struct drm_info_node *node = (struct drm_info_node *)s->private; - struct drm_device *drm = node->minor->dev; - struct drm_framebuffer *fb; - - mutex_lock(&drm->mode_config.fb_lock); - - list_for_each_entry(fb, &drm->mode_config.fb_list, head) { - seq_printf(s, "%3d: user size: %d x %d, depth %d, %d bpp, refcount %d\n", - fb->base.id, fb->width, fb->height, fb->depth, - fb->bits_per_pixel, - atomic_read(&fb->refcount.refcount)); - } - - mutex_unlock(&drm->mode_config.fb_lock); - - return 0; -} - -static struct drm_info_list tegra_debugfs_list[] = { - { "framebuffers", tegra_debugfs_framebuffers, 0 }, -}; - -static int tegra_debugfs_init(struct drm_minor *minor) -{ - return drm_debugfs_create_files(tegra_debugfs_list, - ARRAY_SIZE(tegra_debugfs_list), - minor->debugfs_root, minor); -} - -static void tegra_debugfs_cleanup(struct drm_minor *minor) -{ - drm_debugfs_remove_files(tegra_debugfs_list, - ARRAY_SIZE(tegra_debugfs_list), minor); -} -#endif - struct drm_driver tegra_drm_driver = { .driver_features = DRIVER_BUS_PLATFORM | DRIVER_MODESET | DRIVER_GEM, .load = tegra_drm_load, .unload = tegra_drm_unload, .open = tegra_drm_open, - .preclose = tegra_drm_preclose, .lastclose = tegra_drm_lastclose, - .get_vblank_counter = tegra_drm_get_vblank_counter, - .enable_vblank = tegra_drm_enable_vblank, - .disable_vblank = tegra_drm_disable_vblank, - -#if defined(CONFIG_DEBUG_FS) - .debugfs_init = tegra_debugfs_init, - .debugfs_cleanup = tegra_debugfs_cleanup, -#endif - .gem_free_object = drm_gem_cma_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, .dumb_create = drm_gem_cma_dumb_create, diff --git a/trunk/drivers/gpu/drm/tegra/drm.h b/trunk/drivers/gpu/drm/tegra/drm.h index 6dd75a2600eb..741b5dc2742c 100644 --- a/trunk/drivers/gpu/drm/tegra/drm.h +++ b/trunk/drivers/gpu/drm/tegra/drm.h @@ -18,6 +18,16 @@ #include #include +struct tegra_framebuffer { + struct drm_framebuffer base; + struct drm_gem_cma_object *obj; +}; + +static inline struct tegra_framebuffer *to_tegra_fb(struct drm_framebuffer *fb) +{ + return container_of(fb, struct tegra_framebuffer, base); +} + struct host1x { struct drm_device *drm; struct device *dev; @@ -34,6 +44,7 @@ struct host1x { struct list_head clients; struct drm_fbdev_cma *fbdev; + struct tegra_framebuffer fb; }; struct host1x_client; @@ -64,7 +75,6 @@ struct tegra_output; struct tegra_dc { struct host1x_client client; - spinlock_t lock; struct host1x *host1x; struct device *dev; @@ -84,9 +94,6 @@ struct tegra_dc { struct drm_info_list *debugfs_files; struct drm_minor *minor; struct dentry *debugfs; - - /* page-flip handling */ - struct drm_pending_vblank_event *event; }; static inline struct tegra_dc *host1x_client_to_dc(struct host1x_client *client) @@ -111,34 +118,6 @@ static inline unsigned long tegra_dc_readl(struct tegra_dc *dc, return readl(dc->regs + (reg << 2)); } -struct tegra_dc_window { - struct { - unsigned int x; - unsigned int y; - unsigned int w; - unsigned int h; - } src; - struct { - unsigned int x; - unsigned int y; - unsigned int w; - unsigned int h; - } dst; - unsigned int bits_per_pixel; - unsigned int format; - unsigned int stride[2]; - unsigned long base[3]; -}; - -/* from dc.c */ -extern unsigned int tegra_dc_format(uint32_t format); -extern int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, - const struct tegra_dc_window *window); -extern void tegra_dc_enable_vblank(struct tegra_dc *dc); -extern void tegra_dc_disable_vblank(struct tegra_dc *dc); -extern void tegra_dc_cancel_page_flip(struct drm_crtc *crtc, - struct drm_file *file); - struct tegra_output_ops { int (*enable)(struct tegra_output *output); int (*disable)(struct tegra_output *output); diff --git a/trunk/drivers/gpu/drm/tegra/fb.c b/trunk/drivers/gpu/drm/tegra/fb.c index 03914953cb1c..97993c6835fd 100644 --- a/trunk/drivers/gpu/drm/tegra/fb.c +++ b/trunk/drivers/gpu/drm/tegra/fb.c @@ -39,6 +39,10 @@ int tegra_drm_fb_init(struct drm_device *drm) if (IS_ERR(fbdev)) return PTR_ERR(fbdev); +#ifndef CONFIG_FRAMEBUFFER_CONSOLE + drm_fbdev_cma_restore_mode(fbdev); +#endif + host1x->fbdev = fbdev; return 0; diff --git a/trunk/drivers/gpu/drm/tilcdc/Kconfig b/trunk/drivers/gpu/drm/tilcdc/Kconfig deleted file mode 100644 index ae14fd6ea924..000000000000 --- a/trunk/drivers/gpu/drm/tilcdc/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -config DRM_TILCDC - tristate "DRM Support for TI LCDC Display Controller" - depends on DRM && OF - select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER - select DRM_GEM_CMA_HELPER - select OF_VIDEOMODE - select OF_DISPLAY_TIMING - select BACKLIGHT_CLASS_DEVICE - help - Choose this option if you have an TI SoC with LCDC display - controller, for example AM33xx in beagle-bone, DA8xx, or - OMAP-L1xx. This driver replaces the FB_DA8XX fbdev driver. diff --git a/trunk/drivers/gpu/drm/tilcdc/Makefile b/trunk/drivers/gpu/drm/tilcdc/Makefile deleted file mode 100644 index deda656b10e7..000000000000 --- a/trunk/drivers/gpu/drm/tilcdc/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -ccflags-y := -Iinclude/drm -Werror - -tilcdc-y := \ - tilcdc_crtc.o \ - tilcdc_tfp410.o \ - tilcdc_slave.o \ - tilcdc_panel.o \ - tilcdc_drv.o - -obj-$(CONFIG_DRM_TILCDC) += tilcdc.o diff --git a/trunk/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/trunk/drivers/gpu/drm/tilcdc/tilcdc_crtc.c deleted file mode 100644 index 5dd3c7d031d5..000000000000 --- a/trunk/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ /dev/null @@ -1,602 +0,0 @@ -/* - * Copyright (C) 2012 Texas Instruments - * Author: Rob Clark - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#include - -#include "tilcdc_drv.h" -#include "tilcdc_regs.h" - -struct tilcdc_crtc { - struct drm_crtc base; - - const struct tilcdc_panel_info *info; - uint32_t dirty; - dma_addr_t start, end; - struct drm_pending_vblank_event *event; - int dpms; - wait_queue_head_t frame_done_wq; - bool frame_done; - - /* fb currently set to scanout 0/1: */ - struct drm_framebuffer *scanout[2]; - - /* for deferred fb unref's: */ - DECLARE_KFIFO_PTR(unref_fifo, struct drm_framebuffer *); - struct work_struct work; -}; -#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base) - -static void unref_worker(struct work_struct *work) -{ - struct tilcdc_crtc *tilcdc_crtc = container_of(work, struct tilcdc_crtc, work); - struct drm_device *dev = tilcdc_crtc->base.dev; - struct drm_framebuffer *fb; - - mutex_lock(&dev->mode_config.mutex); - while (kfifo_get(&tilcdc_crtc->unref_fifo, &fb)) - drm_framebuffer_unreference(fb); - mutex_unlock(&dev->mode_config.mutex); -} - -static void set_scanout(struct drm_crtc *crtc, int n) -{ - static const uint32_t base_reg[] = { - LCDC_DMA_FB_BASE_ADDR_0_REG, LCDC_DMA_FB_BASE_ADDR_1_REG, - }; - static const uint32_t ceil_reg[] = { - LCDC_DMA_FB_CEILING_ADDR_0_REG, LCDC_DMA_FB_CEILING_ADDR_1_REG, - }; - static const uint32_t stat[] = { - LCDC_END_OF_FRAME0, LCDC_END_OF_FRAME1, - }; - struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); - struct drm_device *dev = crtc->dev; - - pm_runtime_get_sync(dev->dev); - tilcdc_write(dev, base_reg[n], tilcdc_crtc->start); - tilcdc_write(dev, ceil_reg[n], tilcdc_crtc->end); - if (tilcdc_crtc->scanout[n]) { - if (kfifo_put(&tilcdc_crtc->unref_fifo, - (const struct drm_framebuffer **)&tilcdc_crtc->scanout[n])) { - struct tilcdc_drm_private *priv = dev->dev_private; - queue_work(priv->wq, &tilcdc_crtc->work); - } else { - dev_err(dev->dev, "unref fifo full!\n"); - drm_framebuffer_unreference(tilcdc_crtc->scanout[n]); - } - } - tilcdc_crtc->scanout[n] = crtc->fb; - drm_framebuffer_reference(tilcdc_crtc->scanout[n]); - tilcdc_crtc->dirty &= ~stat[n]; - pm_runtime_put_sync(dev->dev); -} - -static void update_scanout(struct drm_crtc *crtc) -{ - struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct drm_framebuffer *fb = crtc->fb; - struct drm_gem_cma_object *gem; - unsigned int depth, bpp; - - drm_fb_get_bpp_depth(fb->pixel_format, &depth, &bpp); - gem = drm_fb_cma_get_gem_obj(fb, 0); - - tilcdc_crtc->start = gem->paddr + fb->offsets[0] + - (crtc->y * fb->pitches[0]) + (crtc->x * bpp/8); - - tilcdc_crtc->end = tilcdc_crtc->start + - (crtc->mode.vdisplay * fb->pitches[0]); - - if (tilcdc_crtc->dpms == DRM_MODE_DPMS_ON) { - /* already enabled, so just mark the frames that need - * updating and they will be updated on vblank: - */ - tilcdc_crtc->dirty |= LCDC_END_OF_FRAME0 | LCDC_END_OF_FRAME1; - drm_vblank_get(dev, 0); - } else { - /* not enabled yet, so update registers immediately: */ - set_scanout(crtc, 0); - set_scanout(crtc, 1); - } -} - -static void start(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct tilcdc_drm_private *priv = dev->dev_private; - - if (priv->rev == 2) { - tilcdc_set(dev, LCDC_CLK_RESET_REG, LCDC_CLK_MAIN_RESET); - msleep(1); - tilcdc_clear(dev, LCDC_CLK_RESET_REG, LCDC_CLK_MAIN_RESET); - msleep(1); - } - - tilcdc_set(dev, LCDC_DMA_CTRL_REG, LCDC_DUAL_FRAME_BUFFER_ENABLE); - tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_PALETTE_LOAD_MODE(DATA_ONLY)); - tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); -} - -static void stop(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - - tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); -} - -static void tilcdc_crtc_destroy(struct drm_crtc *crtc) -{ - struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); - - WARN_ON(tilcdc_crtc->dpms == DRM_MODE_DPMS_ON); - - drm_crtc_cleanup(crtc); - WARN_ON(!kfifo_is_empty(&tilcdc_crtc->unref_fifo)); - kfifo_free(&tilcdc_crtc->unref_fifo); - kfree(tilcdc_crtc); -} - -static int tilcdc_crtc_page_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event) -{ - struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); - struct drm_device *dev = crtc->dev; - - if (tilcdc_crtc->event) { - dev_err(dev->dev, "already pending page flip!\n"); - return -EBUSY; - } - - crtc->fb = fb; - tilcdc_crtc->event = event; - update_scanout(crtc); - - return 0; -} - -static void tilcdc_crtc_dpms(struct drm_crtc *crtc, int mode) -{ - struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct tilcdc_drm_private *priv = dev->dev_private; - - /* we really only care about on or off: */ - if (mode != DRM_MODE_DPMS_ON) - mode = DRM_MODE_DPMS_OFF; - - if (tilcdc_crtc->dpms == mode) - return; - - tilcdc_crtc->dpms = mode; - - pm_runtime_get_sync(dev->dev); - - if (mode == DRM_MODE_DPMS_ON) { - pm_runtime_forbid(dev->dev); - start(crtc); - } else { - tilcdc_crtc->frame_done = false; - stop(crtc); - - /* if necessary wait for framedone irq which will still come - * before putting things to sleep.. - */ - if (priv->rev == 2) { - int ret = wait_event_timeout( - tilcdc_crtc->frame_done_wq, - tilcdc_crtc->frame_done, - msecs_to_jiffies(50)); - if (ret == 0) - dev_err(dev->dev, "timeout waiting for framedone\n"); - } - pm_runtime_allow(dev->dev); - } - - pm_runtime_put_sync(dev->dev); -} - -static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - -static void tilcdc_crtc_prepare(struct drm_crtc *crtc) -{ - tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); -} - -static void tilcdc_crtc_commit(struct drm_crtc *crtc) -{ - tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON); -} - -static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, - int x, int y, - struct drm_framebuffer *old_fb) -{ - struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct tilcdc_drm_private *priv = dev->dev_private; - const struct tilcdc_panel_info *info = tilcdc_crtc->info; - uint32_t reg, hbp, hfp, hsw, vbp, vfp, vsw; - int ret; - - ret = tilcdc_crtc_mode_valid(crtc, mode); - if (WARN_ON(ret)) - return ret; - - if (WARN_ON(!info)) - return -EINVAL; - - pm_runtime_get_sync(dev->dev); - - /* Configure the Burst Size and fifo threshold of DMA: */ - reg = tilcdc_read(dev, LCDC_DMA_CTRL_REG) & ~0x00000770; - switch (info->dma_burst_sz) { - case 1: - reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_1); - break; - case 2: - reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_2); - break; - case 4: - reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_4); - break; - case 8: - reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_8); - break; - case 16: - reg |= LCDC_DMA_BURST_SIZE(LCDC_DMA_BURST_16); - break; - default: - return -EINVAL; - } - reg |= (info->fifo_th << 8); - tilcdc_write(dev, LCDC_DMA_CTRL_REG, reg); - - /* Configure timings: */ - hbp = mode->htotal - mode->hsync_end; - hfp = mode->hsync_start - mode->hdisplay; - hsw = mode->hsync_end - mode->hsync_start; - vbp = mode->vtotal - mode->vsync_end; - vfp = mode->vsync_start - mode->vdisplay; - vsw = mode->vsync_end - mode->vsync_start; - - DBG("%dx%d, hbp=%u, hfp=%u, hsw=%u, vbp=%u, vfp=%u, vsw=%u", - mode->hdisplay, mode->vdisplay, hbp, hfp, hsw, vbp, vfp, vsw); - - /* Configure the AC Bias Period and Number of Transitions per Interrupt: */ - reg = tilcdc_read(dev, LCDC_RASTER_TIMING_2_REG) & ~0x000fff00; - reg |= LCDC_AC_BIAS_FREQUENCY(info->ac_bias) | - LCDC_AC_BIAS_TRANSITIONS_PER_INT(info->ac_bias_intrpt); - if (priv->rev == 2) { - reg |= (hfp & 0x300) >> 8; - reg |= (hbp & 0x300) >> 4; - reg |= (hsw & 0x3c0) << 21; - } - tilcdc_write(dev, LCDC_RASTER_TIMING_2_REG, reg); - - reg = (((mode->hdisplay >> 4) - 1) << 4) | - ((hbp & 0xff) << 24) | - ((hfp & 0xff) << 16) | - ((hsw & 0x3f) << 10); - if (priv->rev == 2) - reg |= (((mode->hdisplay >> 4) - 1) & 0x40) >> 3; - tilcdc_write(dev, LCDC_RASTER_TIMING_0_REG, reg); - - reg = ((mode->vdisplay - 1) & 0x3ff) | - ((vbp & 0xff) << 24) | - ((vfp & 0xff) << 16) | - ((vsw & 0x3f) << 10); - tilcdc_write(dev, LCDC_RASTER_TIMING_1_REG, reg); - - /* Configure display type: */ - reg = tilcdc_read(dev, LCDC_RASTER_CTRL_REG) & - ~(LCDC_TFT_MODE | LCDC_MONO_8BIT_MODE | LCDC_MONOCHROME_MODE | - LCDC_V2_TFT_24BPP_MODE | LCDC_V2_TFT_24BPP_UNPACK | 0x000ff000); - reg |= LCDC_TFT_MODE; /* no monochrome/passive support */ - if (info->tft_alt_mode) - reg |= LCDC_TFT_ALT_ENABLE; - if (priv->rev == 2) { - unsigned int depth, bpp; - - drm_fb_get_bpp_depth(crtc->fb->pixel_format, &depth, &bpp); - switch (bpp) { - case 16: - break; - case 32: - reg |= LCDC_V2_TFT_24BPP_UNPACK; - /* fallthrough */ - case 24: - reg |= LCDC_V2_TFT_24BPP_MODE; - break; - default: - dev_err(dev->dev, "invalid pixel format\n"); - return -EINVAL; - } - } - reg |= info->fdd < 12; - tilcdc_write(dev, LCDC_RASTER_CTRL_REG, reg); - - if (info->invert_pxl_clk) - tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK); - else - tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_PIXEL_CLOCK); - - if (info->sync_ctrl) - tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL); - else - tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_CTRL); - - if (info->sync_edge) - tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE); - else - tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE); - - if (mode->flags & DRM_MODE_FLAG_NHSYNC) - tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC); - else - tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC); - - if (mode->flags & DRM_MODE_FLAG_NVSYNC) - tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC); - else - tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_VSYNC); - - if (info->raster_order) - tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER); - else - tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ORDER); - - - update_scanout(crtc); - tilcdc_crtc_update_clk(crtc); - - pm_runtime_put_sync(dev->dev); - - return 0; -} - -static int tilcdc_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, - struct drm_framebuffer *old_fb) -{ - update_scanout(crtc); - return 0; -} - -static void tilcdc_crtc_load_lut(struct drm_crtc *crtc) -{ -} - -static const struct drm_crtc_funcs tilcdc_crtc_funcs = { - .destroy = tilcdc_crtc_destroy, - .set_config = drm_crtc_helper_set_config, - .page_flip = tilcdc_crtc_page_flip, -}; - -static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = { - .dpms = tilcdc_crtc_dpms, - .mode_fixup = tilcdc_crtc_mode_fixup, - .prepare = tilcdc_crtc_prepare, - .commit = tilcdc_crtc_commit, - .mode_set = tilcdc_crtc_mode_set, - .mode_set_base = tilcdc_crtc_mode_set_base, - .load_lut = tilcdc_crtc_load_lut, -}; - -int tilcdc_crtc_max_width(struct drm_crtc *crtc) -{ - struct drm_device *dev = crtc->dev; - struct tilcdc_drm_private *priv = dev->dev_private; - int max_width = 0; - - if (priv->rev == 1) - max_width = 1024; - else if (priv->rev == 2) - max_width = 2048; - - return max_width; -} - -int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) -{ - struct tilcdc_drm_private *priv = crtc->dev->dev_private; - unsigned int bandwidth; - - if (mode->hdisplay > tilcdc_crtc_max_width(crtc)) - return MODE_VIRTUAL_X; - - /* width must be multiple of 16 */ - if (mode->hdisplay & 0xf) - return MODE_VIRTUAL_X; - - if (mode->vdisplay > 2048) - return MODE_VIRTUAL_Y; - - /* filter out modes that would require too much memory bandwidth: */ - bandwidth = mode->hdisplay * mode->vdisplay * drm_mode_vrefresh(mode); - if (bandwidth > priv->max_bandwidth) - return MODE_BAD; - - return MODE_OK; -} - -void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc, - const struct tilcdc_panel_info *info) -{ - struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); - tilcdc_crtc->info = info; -} - -void tilcdc_crtc_update_clk(struct drm_crtc *crtc) -{ - struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct tilcdc_drm_private *priv = dev->dev_private; - int dpms = tilcdc_crtc->dpms; - unsigned int lcd_clk, div; - int ret; - - pm_runtime_get_sync(dev->dev); - - if (dpms == DRM_MODE_DPMS_ON) - tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); - - /* in raster mode, minimum divisor is 2: */ - ret = clk_set_rate(priv->disp_clk, crtc->mode.clock * 1000 * 2); - if (ret) { - dev_err(dev->dev, "failed to set display clock rate to: %d\n", - crtc->mode.clock); - goto out; - } - - lcd_clk = clk_get_rate(priv->clk); - div = lcd_clk / (crtc->mode.clock * 1000); - - DBG("lcd_clk=%u, mode clock=%d, div=%u", lcd_clk, crtc->mode.clock, div); - DBG("fck=%lu, dpll_disp_ck=%lu", clk_get_rate(priv->clk), clk_get_rate(priv->disp_clk)); - - /* Configure the LCD clock divisor. */ - tilcdc_write(dev, LCDC_CTRL_REG, LCDC_CLK_DIVISOR(div) | - LCDC_RASTER_MODE); - - if (priv->rev == 2) - tilcdc_set(dev, LCDC_CLK_ENABLE_REG, - LCDC_V2_DMA_CLK_EN | LCDC_V2_LIDD_CLK_EN | - LCDC_V2_CORE_CLK_EN); - - if (dpms == DRM_MODE_DPMS_ON) - tilcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON); - -out: - pm_runtime_put_sync(dev->dev); -} - -irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc) -{ - struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct tilcdc_drm_private *priv = dev->dev_private; - uint32_t stat = tilcdc_read_irqstatus(dev); - - if ((stat & LCDC_SYNC_LOST) && (stat & LCDC_FIFO_UNDERFLOW)) { - stop(crtc); - dev_err(dev->dev, "error: %08x\n", stat); - tilcdc_clear_irqstatus(dev, stat); - start(crtc); - } else if (stat & LCDC_PL_LOAD_DONE) { - tilcdc_clear_irqstatus(dev, stat); - } else { - struct drm_pending_vblank_event *event; - unsigned long flags; - uint32_t dirty = tilcdc_crtc->dirty & stat; - - tilcdc_clear_irqstatus(dev, stat); - - if (dirty & LCDC_END_OF_FRAME0) - set_scanout(crtc, 0); - - if (dirty & LCDC_END_OF_FRAME1) - set_scanout(crtc, 1); - - drm_handle_vblank(dev, 0); - - spin_lock_irqsave(&dev->event_lock, flags); - event = tilcdc_crtc->event; - tilcdc_crtc->event = NULL; - if (event) - drm_send_vblank_event(dev, 0, event); - spin_unlock_irqrestore(&dev->event_lock, flags); - - if (dirty && !tilcdc_crtc->dirty) - drm_vblank_put(dev, 0); - } - - if (priv->rev == 2) { - if (stat & LCDC_FRAME_DONE) { - tilcdc_crtc->frame_done = true; - wake_up(&tilcdc_crtc->frame_done_wq); - } - tilcdc_write(dev, LCDC_END_OF_INT_IND_REG, 0); - } - - return IRQ_HANDLED; -} - -void tilcdc_crtc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file) -{ - struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); - struct drm_pending_vblank_event *event; - struct drm_device *dev = crtc->dev; - unsigned long flags; - - /* Destroy the pending vertical blanking event associated with the - * pending page flip, if any, and disable vertical blanking interrupts. - */ - spin_lock_irqsave(&dev->event_lock, flags); - event = tilcdc_crtc->event; - if (event && event->base.file_priv == file) { - tilcdc_crtc->event = NULL; - event->base.destroy(&event->base); - drm_vblank_put(dev, 0); - } - spin_unlock_irqrestore(&dev->event_lock, flags); -} - -struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev) -{ - struct tilcdc_crtc *tilcdc_crtc; - struct drm_crtc *crtc; - int ret; - - tilcdc_crtc = kzalloc(sizeof(*tilcdc_crtc), GFP_KERNEL); - if (!tilcdc_crtc) { - dev_err(dev->dev, "allocation failed\n"); - return NULL; - } - - crtc = &tilcdc_crtc->base; - - tilcdc_crtc->dpms = DRM_MODE_DPMS_OFF; - init_waitqueue_head(&tilcdc_crtc->frame_done_wq); - - ret = kfifo_alloc(&tilcdc_crtc->unref_fifo, 16, GFP_KERNEL); - if (ret) { - dev_err(dev->dev, "could not allocate unref FIFO\n"); - goto fail; - } - - INIT_WORK(&tilcdc_crtc->work, unref_worker); - - ret = drm_crtc_init(dev, crtc, &tilcdc_crtc_funcs); - if (ret < 0) - goto fail; - - drm_crtc_helper_add(crtc, &tilcdc_crtc_helper_funcs); - - return crtc; - -fail: - tilcdc_crtc_destroy(crtc); - return NULL; -} diff --git a/trunk/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/trunk/drivers/gpu/drm/tilcdc/tilcdc_drv.c deleted file mode 100644 index c5b592dc1970..000000000000 --- a/trunk/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ /dev/null @@ -1,611 +0,0 @@ -/* - * Copyright (C) 2012 Texas Instruments - * Author: Rob Clark - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -/* LCDC DRM driver, based on da8xx-fb */ - -#include "tilcdc_drv.h" -#include "tilcdc_regs.h" -#include "tilcdc_tfp410.h" -#include "tilcdc_slave.h" -#include "tilcdc_panel.h" - -#include "drm_fb_helper.h" - -static LIST_HEAD(module_list); - -void tilcdc_module_init(struct tilcdc_module *mod, const char *name, - const struct tilcdc_module_ops *funcs) -{ - mod->name = name; - mod->funcs = funcs; - INIT_LIST_HEAD(&mod->list); - list_add(&mod->list, &module_list); -} - -void tilcdc_module_cleanup(struct tilcdc_module *mod) -{ - list_del(&mod->list); -} - -static struct of_device_id tilcdc_of_match[]; - -static struct drm_framebuffer *tilcdc_fb_create(struct drm_device *dev, - struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd) -{ - return drm_fb_cma_create(dev, file_priv, mode_cmd); -} - -static void tilcdc_fb_output_poll_changed(struct drm_device *dev) -{ - struct tilcdc_drm_private *priv = dev->dev_private; - if (priv->fbdev) - drm_fbdev_cma_hotplug_event(priv->fbdev); -} - -static const struct drm_mode_config_funcs mode_config_funcs = { - .fb_create = tilcdc_fb_create, - .output_poll_changed = tilcdc_fb_output_poll_changed, -}; - -static int modeset_init(struct drm_device *dev) -{ - struct tilcdc_drm_private *priv = dev->dev_private; - struct tilcdc_module *mod; - - drm_mode_config_init(dev); - - priv->crtc = tilcdc_crtc_create(dev); - - list_for_each_entry(mod, &module_list, list) { - DBG("loading module: %s", mod->name); - mod->funcs->modeset_init(mod, dev); - } - - if ((priv->num_encoders = 0) || (priv->num_connectors == 0)) { - /* oh nos! */ - dev_err(dev->dev, "no encoders/connectors found\n"); - return -ENXIO; - } - - dev->mode_config.min_width = 0; - dev->mode_config.min_height = 0; - dev->mode_config.max_width = tilcdc_crtc_max_width(priv->crtc); - dev->mode_config.max_height = 2048; - dev->mode_config.funcs = &mode_config_funcs; - - return 0; -} - -#ifdef CONFIG_CPU_FREQ -static int cpufreq_transition(struct notifier_block *nb, - unsigned long val, void *data) -{ - struct tilcdc_drm_private *priv = container_of(nb, - struct tilcdc_drm_private, freq_transition); - if (val == CPUFREQ_POSTCHANGE) { - if (priv->lcd_fck_rate != clk_get_rate(priv->clk)) { - priv->lcd_fck_rate = clk_get_rate(priv->clk); - tilcdc_crtc_update_clk(priv->crtc); - } - } - - return 0; -} -#endif - -/* - * DRM operations: - */ - -static int tilcdc_unload(struct drm_device *dev) -{ - struct tilcdc_drm_private *priv = dev->dev_private; - struct tilcdc_module *mod, *cur; - - drm_kms_helper_poll_fini(dev); - drm_mode_config_cleanup(dev); - drm_vblank_cleanup(dev); - - pm_runtime_get_sync(dev->dev); - drm_irq_uninstall(dev); - pm_runtime_put_sync(dev->dev); - -#ifdef CONFIG_CPU_FREQ - cpufreq_unregister_notifier(&priv->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -#endif - - if (priv->clk) - clk_put(priv->clk); - - if (priv->mmio) - iounmap(priv->mmio); - - flush_workqueue(priv->wq); - destroy_workqueue(priv->wq); - - dev->dev_private = NULL; - - pm_runtime_disable(dev->dev); - - list_for_each_entry_safe(mod, cur, &module_list, list) { - DBG("destroying module: %s", mod->name); - mod->funcs->destroy(mod); - } - - kfree(priv); - - return 0; -} - -static int tilcdc_load(struct drm_device *dev, unsigned long flags) -{ - struct platform_device *pdev = dev->platformdev; - struct device_node *node = pdev->dev.of_node; - struct tilcdc_drm_private *priv; - struct resource *res; - int ret; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) { - dev_err(dev->dev, "failed to allocate private data\n"); - return -ENOMEM; - } - - dev->dev_private = priv; - - priv->wq = alloc_ordered_workqueue("tilcdc", 0); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev->dev, "failed to get memory resource\n"); - ret = -EINVAL; - goto fail; - } - - priv->mmio = ioremap_nocache(res->start, resource_size(res)); - if (!priv->mmio) { - dev_err(dev->dev, "failed to ioremap\n"); - ret = -ENOMEM; - goto fail; - } - - priv->clk = clk_get(dev->dev, "fck"); - if (IS_ERR(priv->clk)) { - dev_err(dev->dev, "failed to get functional clock\n"); - ret = -ENODEV; - goto fail; - } - - priv->disp_clk = clk_get(dev->dev, "dpll_disp_ck"); - if (IS_ERR(priv->clk)) { - dev_err(dev->dev, "failed to get display clock\n"); - ret = -ENODEV; - goto fail; - } - -#ifdef CONFIG_CPU_FREQ - priv->lcd_fck_rate = clk_get_rate(priv->clk); - priv->freq_transition.notifier_call = cpufreq_transition; - ret = cpufreq_register_notifier(&priv->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); - if (ret) { - dev_err(dev->dev, "failed to register cpufreq notifier\n"); - goto fail; - } -#endif - - if (of_property_read_u32(node, "max-bandwidth", &priv->max_bandwidth)) - priv->max_bandwidth = 1280 * 1024 * 60; - - pm_runtime_enable(dev->dev); - - /* Determine LCD IP Version */ - pm_runtime_get_sync(dev->dev); - switch (tilcdc_read(dev, LCDC_PID_REG)) { - case 0x4c100102: - priv->rev = 1; - break; - case 0x4f200800: - case 0x4f201000: - priv->rev = 2; - break; - default: - dev_warn(dev->dev, "Unknown PID Reg value 0x%08x, " - "defaulting to LCD revision 1\n", - tilcdc_read(dev, LCDC_PID_REG)); - priv->rev = 1; - break; - } - - pm_runtime_put_sync(dev->dev); - - ret = modeset_init(dev); - if (ret < 0) { - dev_err(dev->dev, "failed to initialize mode setting\n"); - goto fail; - } - - ret = drm_vblank_init(dev, 1); - if (ret < 0) { - dev_err(dev->dev, "failed to initialize vblank\n"); - goto fail; - } - - pm_runtime_get_sync(dev->dev); - ret = drm_irq_install(dev); - pm_runtime_put_sync(dev->dev); - if (ret < 0) { - dev_err(dev->dev, "failed to install IRQ handler\n"); - goto fail; - } - - platform_set_drvdata(pdev, dev); - - priv->fbdev = drm_fbdev_cma_init(dev, 16, - dev->mode_config.num_crtc, - dev->mode_config.num_connector); - - drm_kms_helper_poll_init(dev); - - return 0; - -fail: - tilcdc_unload(dev); - return ret; -} - -static void tilcdc_preclose(struct drm_device *dev, struct drm_file *file) -{ - struct tilcdc_drm_private *priv = dev->dev_private; - - tilcdc_crtc_cancel_page_flip(priv->crtc, file); -} - -static void tilcdc_lastclose(struct drm_device *dev) -{ - struct tilcdc_drm_private *priv = dev->dev_private; - drm_fbdev_cma_restore_mode(priv->fbdev); -} - -static irqreturn_t tilcdc_irq(DRM_IRQ_ARGS) -{ - struct drm_device *dev = arg; - struct tilcdc_drm_private *priv = dev->dev_private; - return tilcdc_crtc_irq(priv->crtc); -} - -static void tilcdc_irq_preinstall(struct drm_device *dev) -{ - tilcdc_clear_irqstatus(dev, 0xffffffff); -} - -static int tilcdc_irq_postinstall(struct drm_device *dev) -{ - struct tilcdc_drm_private *priv = dev->dev_private; - - /* enable FIFO underflow irq: */ - if (priv->rev == 1) { - tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_V1_UNDERFLOW_INT_ENA); - } else { - tilcdc_set(dev, LCDC_INT_ENABLE_SET_REG, LCDC_V2_UNDERFLOW_INT_ENA); - } - - return 0; -} - -static void tilcdc_irq_uninstall(struct drm_device *dev) -{ - struct tilcdc_drm_private *priv = dev->dev_private; - - /* disable irqs that we might have enabled: */ - if (priv->rev == 1) { - tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, - LCDC_V1_UNDERFLOW_INT_ENA | LCDC_V1_PL_INT_ENA); - tilcdc_clear(dev, LCDC_DMA_CTRL_REG, LCDC_V1_END_OF_FRAME_INT_ENA); - } else { - tilcdc_clear(dev, LCDC_INT_ENABLE_SET_REG, - LCDC_V2_UNDERFLOW_INT_ENA | LCDC_V2_PL_INT_ENA | - LCDC_V2_END_OF_FRAME0_INT_ENA | LCDC_V2_END_OF_FRAME1_INT_ENA | - LCDC_FRAME_DONE); - } - -} - -static void enable_vblank(struct drm_device *dev, bool enable) -{ - struct tilcdc_drm_private *priv = dev->dev_private; - u32 reg, mask; - - if (priv->rev == 1) { - reg = LCDC_DMA_CTRL_REG; - mask = LCDC_V1_END_OF_FRAME_INT_ENA; - } else { - reg = LCDC_INT_ENABLE_SET_REG; - mask = LCDC_V2_END_OF_FRAME0_INT_ENA | - LCDC_V2_END_OF_FRAME1_INT_ENA | LCDC_FRAME_DONE; - } - - if (enable) - tilcdc_set(dev, reg, mask); - else - tilcdc_clear(dev, reg, mask); -} - -static int tilcdc_enable_vblank(struct drm_device *dev, int crtc) -{ - enable_vblank(dev, true); - return 0; -} - -static void tilcdc_disable_vblank(struct drm_device *dev, int crtc) -{ - enable_vblank(dev, false); -} - -#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_PM_SLEEP) -static const struct { - const char *name; - uint8_t rev; - uint8_t save; - uint32_t reg; -} registers[] = { -#define REG(rev, save, reg) { #reg, rev, save, reg } - /* exists in revision 1: */ - REG(1, false, LCDC_PID_REG), - REG(1, true, LCDC_CTRL_REG), - REG(1, false, LCDC_STAT_REG), - REG(1, true, LCDC_RASTER_CTRL_REG), - REG(1, true, LCDC_RASTER_TIMING_0_REG), - REG(1, true, LCDC_RASTER_TIMING_1_REG), - REG(1, true, LCDC_RASTER_TIMING_2_REG), - REG(1, true, LCDC_DMA_CTRL_REG), - REG(1, true, LCDC_DMA_FB_BASE_ADDR_0_REG), - REG(1, true, LCDC_DMA_FB_CEILING_ADDR_0_REG), - REG(1, true, LCDC_DMA_FB_BASE_ADDR_1_REG), - REG(1, true, LCDC_DMA_FB_CEILING_ADDR_1_REG), - /* new in revision 2: */ - REG(2, false, LCDC_RAW_STAT_REG), - REG(2, false, LCDC_MASKED_STAT_REG), - REG(2, false, LCDC_INT_ENABLE_SET_REG), - REG(2, false, LCDC_INT_ENABLE_CLR_REG), - REG(2, false, LCDC_END_OF_INT_IND_REG), - REG(2, true, LCDC_CLK_ENABLE_REG), - REG(2, true, LCDC_INT_ENABLE_SET_REG), -#undef REG -}; -#endif - -#ifdef CONFIG_DEBUG_FS -static int tilcdc_regs_show(struct seq_file *m, void *arg) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - struct tilcdc_drm_private *priv = dev->dev_private; - unsigned i; - - pm_runtime_get_sync(dev->dev); - - seq_printf(m, "revision: %d\n", priv->rev); - - for (i = 0; i < ARRAY_SIZE(registers); i++) - if (priv->rev >= registers[i].rev) - seq_printf(m, "%s:\t %08x\n", registers[i].name, - tilcdc_read(dev, registers[i].reg)); - - pm_runtime_put_sync(dev->dev); - - return 0; -} - -static int tilcdc_mm_show(struct seq_file *m, void *arg) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - return drm_mm_dump_table(m, dev->mm_private); -} - -static struct drm_info_list tilcdc_debugfs_list[] = { - { "regs", tilcdc_regs_show, 0 }, - { "mm", tilcdc_mm_show, 0 }, - { "fb", drm_fb_cma_debugfs_show, 0 }, -}; - -static int tilcdc_debugfs_init(struct drm_minor *minor) -{ - struct drm_device *dev = minor->dev; - struct tilcdc_module *mod; - int ret; - - ret = drm_debugfs_create_files(tilcdc_debugfs_list, - ARRAY_SIZE(tilcdc_debugfs_list), - minor->debugfs_root, minor); - - list_for_each_entry(mod, &module_list, list) - if (mod->funcs->debugfs_init) - mod->funcs->debugfs_init(mod, minor); - - if (ret) { - dev_err(dev->dev, "could not install tilcdc_debugfs_list\n"); - return ret; - } - - return ret; -} - -static void tilcdc_debugfs_cleanup(struct drm_minor *minor) -{ - struct tilcdc_module *mod; - drm_debugfs_remove_files(tilcdc_debugfs_list, - ARRAY_SIZE(tilcdc_debugfs_list), minor); - - list_for_each_entry(mod, &module_list, list) - if (mod->funcs->debugfs_cleanup) - mod->funcs->debugfs_cleanup(mod, minor); -} -#endif - -static const struct file_operations fops = { - .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = drm_compat_ioctl, -#endif - .poll = drm_poll, - .read = drm_read, - .fasync = drm_fasync, - .llseek = no_llseek, - .mmap = drm_gem_cma_mmap, -}; - -static struct drm_driver tilcdc_driver = { - .driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM | DRIVER_MODESET, - .load = tilcdc_load, - .unload = tilcdc_unload, - .preclose = tilcdc_preclose, - .lastclose = tilcdc_lastclose, - .irq_handler = tilcdc_irq, - .irq_preinstall = tilcdc_irq_preinstall, - .irq_postinstall = tilcdc_irq_postinstall, - .irq_uninstall = tilcdc_irq_uninstall, - .get_vblank_counter = drm_vblank_count, - .enable_vblank = tilcdc_enable_vblank, - .disable_vblank = tilcdc_disable_vblank, - .gem_free_object = drm_gem_cma_free_object, - .gem_vm_ops = &drm_gem_cma_vm_ops, - .dumb_create = drm_gem_cma_dumb_create, - .dumb_map_offset = drm_gem_cma_dumb_map_offset, - .dumb_destroy = drm_gem_cma_dumb_destroy, -#ifdef CONFIG_DEBUG_FS - .debugfs_init = tilcdc_debugfs_init, - .debugfs_cleanup = tilcdc_debugfs_cleanup, -#endif - .fops = &fops, - .name = "tilcdc", - .desc = "TI LCD Controller DRM", - .date = "20121205", - .major = 1, - .minor = 0, -}; - -/* - * Power management: - */ - -#ifdef CONFIG_PM_SLEEP -static int tilcdc_pm_suspend(struct device *dev) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct tilcdc_drm_private *priv = ddev->dev_private; - unsigned i, n = 0; - - drm_kms_helper_poll_disable(ddev); - - /* Save register state: */ - for (i = 0; i < ARRAY_SIZE(registers); i++) - if (registers[i].save && (priv->rev >= registers[i].rev)) - priv->saved_register[n++] = tilcdc_read(ddev, registers[i].reg); - - return 0; -} - -static int tilcdc_pm_resume(struct device *dev) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct tilcdc_drm_private *priv = ddev->dev_private; - unsigned i, n = 0; - - /* Restore register state: */ - for (i = 0; i < ARRAY_SIZE(registers); i++) - if (registers[i].save && (priv->rev >= registers[i].rev)) - tilcdc_write(ddev, registers[i].reg, priv->saved_register[n++]); - - drm_kms_helper_poll_enable(ddev); - - return 0; -} -#endif - -static const struct dev_pm_ops tilcdc_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(tilcdc_pm_suspend, tilcdc_pm_resume) -}; - -/* - * Platform driver: - */ - -static int tilcdc_pdev_probe(struct platform_device *pdev) -{ - /* bail out early if no DT data: */ - if (!pdev->dev.of_node) { - dev_err(&pdev->dev, "device-tree data is missing\n"); - return -ENXIO; - } - - return drm_platform_init(&tilcdc_driver, pdev); -} - -static int tilcdc_pdev_remove(struct platform_device *pdev) -{ - drm_platform_exit(&tilcdc_driver, pdev); - - return 0; -} - -static struct of_device_id tilcdc_of_match[] = { - { .compatible = "ti,am33xx-tilcdc", }, - { }, -}; -MODULE_DEVICE_TABLE(of, tilcdc_of_match); - -static struct platform_driver tilcdc_platform_driver = { - .probe = tilcdc_pdev_probe, - .remove = tilcdc_pdev_remove, - .driver = { - .owner = THIS_MODULE, - .name = "tilcdc", - .pm = &tilcdc_pm_ops, - .of_match_table = tilcdc_of_match, - }, -}; - -static int __init tilcdc_drm_init(void) -{ - DBG("init"); - tilcdc_tfp410_init(); - tilcdc_slave_init(); - tilcdc_panel_init(); - return platform_driver_register(&tilcdc_platform_driver); -} - -static void __exit tilcdc_drm_fini(void) -{ - DBG("fini"); - tilcdc_tfp410_fini(); - tilcdc_slave_fini(); - tilcdc_panel_fini(); - platform_driver_unregister(&tilcdc_platform_driver); -} - -late_initcall(tilcdc_drm_init); -module_exit(tilcdc_drm_fini); - -MODULE_AUTHOR("Rob Clark - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#ifndef __TILCDC_DRV_H__ -#define __TILCDC_DRV_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -struct tilcdc_drm_private { - void __iomem *mmio; - - struct clk *disp_clk; /* display dpll */ - struct clk *clk; /* functional clock */ - int rev; /* IP revision */ - - /* don't attempt resolutions w/ higher W * H * Hz: */ - uint32_t max_bandwidth; - - /* register contents saved across suspend/resume: */ - u32 saved_register[12]; - -#ifdef CONFIG_CPU_FREQ - struct notifier_block freq_transition; - unsigned int lcd_fck_rate; -#endif - - struct workqueue_struct *wq; - - struct drm_fbdev_cma *fbdev; - - struct drm_crtc *crtc; - - unsigned int num_encoders; - struct drm_encoder *encoders[8]; - - unsigned int num_connectors; - struct drm_connector *connectors[8]; -}; - -/* Sub-module for display. Since we don't know at compile time what panels - * or display adapter(s) might be present (for ex, off chip dvi/tfp410, - * hdmi encoder, various lcd panels), the connector/encoder(s) are split into - * separate drivers. If they are probed and found to be present, they - * register themselves with tilcdc_register_module(). - */ -struct tilcdc_module; - -struct tilcdc_module_ops { - /* create appropriate encoders/connectors: */ - int (*modeset_init)(struct tilcdc_module *mod, struct drm_device *dev); - void (*destroy)(struct tilcdc_module *mod); -#ifdef CONFIG_DEBUG_FS - /* create debugfs nodes (can be NULL): */ - int (*debugfs_init)(struct tilcdc_module *mod, struct drm_minor *minor); - /* cleanup debugfs nodes (can be NULL): */ - void (*debugfs_cleanup)(struct tilcdc_module *mod, struct drm_minor *minor); -#endif -}; - -struct tilcdc_module { - const char *name; - struct list_head list; - const struct tilcdc_module_ops *funcs; -}; - -void tilcdc_module_init(struct tilcdc_module *mod, const char *name, - const struct tilcdc_module_ops *funcs); -void tilcdc_module_cleanup(struct tilcdc_module *mod); - - -/* Panel config that needs to be set in the crtc, but is not coming from - * the mode timings. The display module is expected to call - * tilcdc_crtc_set_panel_info() to set this during modeset. - */ -struct tilcdc_panel_info { - - /* AC Bias Pin Frequency */ - uint32_t ac_bias; - - /* AC Bias Pin Transitions per Interrupt */ - uint32_t ac_bias_intrpt; - - /* DMA burst size */ - uint32_t dma_burst_sz; - - /* Bits per pixel */ - uint32_t bpp; - - /* FIFO DMA Request Delay */ - uint32_t fdd; - - /* TFT Alternative Signal Mapping (Only for active) */ - bool tft_alt_mode; - - /* Invert pixel clock */ - bool invert_pxl_clk; - - /* Horizontal and Vertical Sync Edge: 0=rising 1=falling */ - uint32_t sync_edge; - - /* Horizontal and Vertical Sync: Control: 0=ignore */ - uint32_t sync_ctrl; - - /* Raster Data Order Select: 1=Most-to-least 0=Least-to-most */ - uint32_t raster_order; - - /* DMA FIFO threshold */ - uint32_t fifo_th; -}; - -#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) - -struct drm_crtc *tilcdc_crtc_create(struct drm_device *dev); -void tilcdc_crtc_cancel_page_flip(struct drm_crtc *crtc, struct drm_file *file); -irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc); -void tilcdc_crtc_update_clk(struct drm_crtc *crtc); -void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc, - const struct tilcdc_panel_info *info); -int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode); -int tilcdc_crtc_max_width(struct drm_crtc *crtc); - -#endif /* __TILCDC_DRV_H__ */ diff --git a/trunk/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/trunk/drivers/gpu/drm/tilcdc/tilcdc_panel.c deleted file mode 100644 index 580b74e2022b..000000000000 --- a/trunk/drivers/gpu/drm/tilcdc/tilcdc_panel.c +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Copyright (C) 2012 Texas Instruments - * Author: Rob Clark - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published by - * the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#include -#include -#include -#include