From 671952a2a290a90017c64e75b7dd0343b0d005b4 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 1 Oct 2013 18:11:26 +0300 Subject: drm/i915: fix rps.vlv_work initialization During driver loading we are initializing rps.vlv_work in valleyview_enable_rps() via the rps.delayed_resume_work delayed work. This is too late since we are using vlv_work already via i915_driver_load()->intel_uncore_sanitize()-> intel_disable_gt_powersave(). This at least leads to the following kernel warning: INFO: trying to register non-static key. the code is fine but needs lockdep annotation. turning off the locking correctness validator. Fix this by initialzing vlv_work before we call intel_uncore_sanitize(). The regression was introduced in commit 7dcd2677ea912573d9ed4bcd629b0023b2d11505 Author: Konstantin Khlebnikov Date: Wed Jul 17 10:22:58 2013 +0400 drm/i915: fix long-standing SNB regression in power consumption after resume though there was no good reason to initialize the static vlv_work from another delayed work to begin with (especially since this will happen multiple times). Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=69397 Tested-by: shui yangwei Signed-off-by: Imre Deak Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index dd176b7296c1..73a8efc65615 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3864,8 +3864,6 @@ static void valleyview_enable_rps(struct drm_device *dev) dev_priv->rps.rpe_delay), dev_priv->rps.rpe_delay); - INIT_DELAYED_WORK(&dev_priv->rps.vlv_work, vlv_rps_timer_work); - valleyview_set_rps(dev_priv->dev, dev_priv->rps.rpe_delay); gen6_enable_rps_interrupts(dev); @@ -5681,5 +5679,7 @@ void intel_pm_init(struct drm_device *dev) INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work, intel_gen6_powersave_work); + + INIT_DELAYED_WORK(&dev_priv->rps.vlv_work, vlv_rps_timer_work); } -- cgit v1.2.3 From f3fc4884ebe6ae649d3723be14b219230d3b7fd2 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Wed, 2 Oct 2013 15:53:16 -0700 Subject: drm/i915/hsw: Disable L3 caching of atomic memory operations. Otherwise using any atomic memory operation will lock up the GPU due to a Haswell hardware bug. v2: Use the _MASKED_BIT_ENABLE macro. Drop drm parameter definition. Signed-off-by: Francisco Jerez Reviewed-by: Ben Widawsky Cc: Daniel Vetter Cc: [danvet: Fix checkpatch fail.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 6 ++++++ drivers/gpu/drm/i915/intel_pm.c | 5 +++++ 2 files changed, 11 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c159e1a6810f..38f96f65d87a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3881,6 +3881,9 @@ #define GEN7_SQ_CHICKEN_MBCUNIT_CONFIG 0x9030 #define GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB (1<<11) +#define HSW_SCRATCH1 0xb038 +#define HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE (1<<27) + #define HSW_FUSE_STRAP 0x42014 #define HSW_CDCLK_LIMIT (1 << 24) @@ -4728,6 +4731,9 @@ #define GEN7_ROW_CHICKEN2_GT2 0xf4f4 #define DOP_CLOCK_GATING_DISABLE (1<<0) +#define HSW_ROW_CHICKEN3 0xe49c +#define HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE (1 << 6) + #define G4X_AUD_VID_DID (dev_priv->info->display_mmio_offset + 0x62020) #define INTEL_AUDIO_DEVCL 0x808629FB #define INTEL_AUDIO_DEVBLC 0x80862801 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 73a8efc65615..f4c5e95b2d6f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4953,6 +4953,11 @@ static void haswell_init_clock_gating(struct drm_device *dev) I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, GEN7_WA_L3_CHICKEN_MODE); + /* L3 caching of data atomics doesn't work -- disable it. */ + I915_WRITE(HSW_SCRATCH1, HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE); + I915_WRITE(HSW_ROW_CHICKEN3, + _MASKED_BIT_ENABLE(HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE)); + /* This is required by WaCatErrorRejectionIssue:hsw */ I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | -- cgit v1.2.3 From 0cc4b69960f3d1231023ad5de6cacbc1fbee2a88 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 3 Oct 2013 13:31:26 -0300 Subject: drm/i915: Mask LPSP to get PSR working even with Power Well in use by audio. Power Well in use forces constantly PSR to exit. On recent Kernel I noticed that PSR Performance Counter was always 0 indicating that PSR was never really achieved. By masking LPSP, PSR can work normally and save power on Haswell. Two bugs had been raised with PSR flag enabled: - "Screen flickers when booted by enabling PSR in the kernel (i915.enable_psr=1) , the system is booting to a gray screen." - "When booting the DUT with PSR feature enabled in the kernel (i915.enable_psr=1) , the system is booting to a gray screen." Both bugs has been fixed by this patch. v2: proper comment for -fixes Tested-by: Selvaraj, Elavarasan Signed-off-by: Rodrigo Vivi Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 79c14e298ba6..2c555f91bfae 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1467,7 +1467,7 @@ static void intel_edp_psr_setup(struct intel_dp *intel_dp) /* Avoid continuous PSR exit by masking memup and hpd */ I915_WRITE(EDP_PSR_DEBUG_CTL, EDP_PSR_DEBUG_MASK_MEMUP | - EDP_PSR_DEBUG_MASK_HPD); + EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP); intel_dp->psr_setup_done = true; } -- cgit v1.2.3 From c9976dcf55c8aaa7037427b239f15e5acfc01a3a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 29 Sep 2013 19:15:07 +0100 Subject: drm/i915: Only apply DPMS to the encoder if enabled The current test for an attached enabled encoder fails if we have multiple connectors aliased to the same encoder - both connectors believe they own the enabled encoder and so we attempt to both enable and disable DPMS on the encoder, leading to hilarity and an OOPs: [ 354.803064] WARNING: CPU: 0 PID: 482 at /usr/src/linux/dist/3.11.2/drivers/gpu/drm/i915/intel_display.c:3869 intel_modeset_check_state+0x764/0x770 [i915]() [ 354.803064] wrong connector dpms state [ 354.803084] Modules linked in: nfsd auth_rpcgss oid_registry exportfs nfs lockd sunrpc xt_nat iptable_nat nf_nat_ipv4 nf_nat xt_limit xt_LOG xt_tcpudp nf_conntrack_ipv4 nf_defrag_ipv4 ipt_REJECT ipv6 xt_recent xt_conntrack nf_conntrack iptable_filter ip_tables x_tables snd_hda_codec_realtek snd_hda_codec_hdmi x86_pkg_temp_thermal snd_hda_intel coretemp kvm_intel snd_hda_codec i915 kvm snd_hwdep snd_pcm_oss snd_mixer_oss crc32_pclmul snd_pcm crc32c_intel e1000e intel_agp igb ghash_clmulni_intel intel_gtt aesni_intel cfbfillrect aes_x86_64 cfbimgblt lrw cfbcopyarea drm_kms_helper ptp video thermal processor gf128mul snd_page_alloc drm snd_timer glue_helper 8250_pci snd pps_core ablk_helper agpgart cryptd sg soundcore fan i2c_algo_bit sr_mod thermal_sys 8250 i2c_i801 serial_core hwmon cdrom i2c_core evdev button [ 354.803086] CPU: 0 PID: 482 Comm: kworker/0:1 Not tainted 3.11.2 #1 [ 354.803087] Hardware name: Supermicro X10SAE/X10SAE, BIOS 1.00 05/03/2013 [ 354.803091] Workqueue: events console_callback [ 354.803092] 0000000000000009 ffff88023611db48 ffffffff814048ac ffff88023611db90 [ 354.803093] ffff88023611db80 ffffffff8103d4e3 ffff880230d82800 ffff880230f9b800 [ 354.803094] ffff880230f99000 ffff880230f99448 ffff8802351c0e00 ffff88023611dbe0 [ 354.803094] Call Trace: [ 354.803098] [] dump_stack+0x54/0x8d [ 354.803101] [] warn_slowpath_common+0x73/0x90 [ 354.803103] [] warn_slowpath_fmt+0x47/0x50 [ 354.803109] [] ? intel_ddi_connector_get_hw_state+0x5e/0x110 [i915] [ 354.803114] [] intel_modeset_check_state+0x764/0x770 [i915] [ 354.803117] [] intel_connector_dpms+0x3b/0x60 [i915] [ 354.803120] [] drm_fb_helper_dpms.isra.11+0x120/0x160 [drm_kms_helper] [ 354.803122] [] drm_fb_helper_blank+0x3e/0x80 [drm_kms_helper] [ 354.803123] [] fb_blank+0x52/0xc0 [ 354.803125] [] fbcon_blank+0x21b/0x2d0 [ 354.803127] [] ? update_rq_clock.part.74+0x13/0x30 [ 354.803129] [] ? lock_timer_base.isra.30+0x26/0x50 [ 354.803130] [] ? internal_add_timer+0x12/0x40 [ 354.803131] [] ? mod_timer+0xf8/0x1c0 [ 354.803133] [] do_unblank_screen+0xa1/0x1c0 [ 354.803134] [] poke_blanked_console+0xc7/0xd0 [ 354.803136] [] console_callback+0x13f/0x160 [ 354.803137] [] process_one_work+0x148/0x3d0 [ 354.803138] [] worker_thread+0x119/0x3a0 [ 354.803140] [] ? manage_workers.isra.30+0x2a0/0x2a0 [ 354.803141] [] kthread+0xbb/0xc0 [ 354.803142] [] ? kthread_create_on_node+0x120/0x120 [ 354.803144] [] ret_from_fork+0x7c/0xb0 [ 354.803145] [] ? kthread_create_on_node+0x120/0x120 This regression goes back to the big modeset rework and the conversion to the new dpms helpers which started with: commit 5ab432ef4997ce32c9406721b37ef6e97e57dae1 Author: Daniel Vetter Date: Sat Jun 30 08:59:56 2012 +0200 drm/i915/hdmi: convert to encoder->disable/enable Fixes: igt/kms_flip/dpms-off-confusion Reported-and-tested-by: Wakko Warner Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=68030 Link: http://lkml.kernel.org/r/20130928185023.GA21672@animx.eu.org Signed-off-by: Chris Wilson Cc: stable@vger.kernel.org [danvet: Add regression citation, mention the igt testcase this fixes and slap a cc: stable on the patch.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e5822e79f912..c89abd33124f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3941,8 +3941,6 @@ static void intel_connector_check_state(struct intel_connector *connector) * consider. */ void intel_connector_dpms(struct drm_connector *connector, int mode) { - struct intel_encoder *encoder = intel_attached_encoder(connector); - /* All the simple cases only support two dpms states. */ if (mode != DRM_MODE_DPMS_ON) mode = DRM_MODE_DPMS_OFF; @@ -3953,10 +3951,8 @@ void intel_connector_dpms(struct drm_connector *connector, int mode) connector->dpms = mode; /* Only need to change hw state when actually enabled */ - if (encoder->base.crtc) - intel_encoder_dpms(encoder, mode); - else - WARN_ON(encoder->connectors_active != false); + if (connector->encoder) + intel_encoder_dpms(to_intel_encoder(connector->encoder), mode); intel_modeset_check_state(connector->dev); } -- cgit v1.2.3 From b46b28d339164c8c74020eace97163e2e478ef34 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 8 Oct 2013 16:23:36 +1000 Subject: drm/nouveau/mc: disable msi support by default, it's busted in tons of places Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/core/subdev/mc/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c index 37712a6df923..e290cfa4acee 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c @@ -113,7 +113,7 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, pmc->use_msi = false; break; default: - pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI", true); + pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI", false); if (pmc->use_msi) { pmc->use_msi = pci_enable_msi(device->pdev) == 0; if (pmc->use_msi) { -- cgit v1.2.3 From b9aa8510dd68143cc9d66c520002b638983e254b Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 8 Oct 2013 16:31:59 -0400 Subject: drm/gma500: fix things after get/put page helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 8b9ba7a3 'drm/gma500: use gem get/put page helpers' was missing a line, which resulted in garbled screen. Signed-off-by: Rob Clark Tested-by: Guillaume CLÉMENT Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/gtt.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index 92babac362ec..2db731f00930 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -204,6 +204,7 @@ static int psb_gtt_attach_pages(struct gtt_range *gt) if (IS_ERR(pages)) return PTR_ERR(pages); + gt->npage = gt->gem.size / PAGE_SIZE; gt->pages = pages; return 0; -- cgit v1.2.3 From ecc7e6f3bb8ad56764667aeabb860c24a6fa37f9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 10 Oct 2013 07:05:41 +1000 Subject: Revert "drm/fb-helper: don't sleep for screen unblank when an oops is in progress" This reverts commit 928c2f0c006bf7f381f58af2b2786d2a858ae311. This patch double applied, two checks for the price of one. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fb_helper.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index f6f6cc7fc133..3d13ca6e257f 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -407,14 +407,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; - /* * fbdev->blank can be called from irq context in case of a panic. * Since we already have our own special panic handler which will -- cgit v1.2.3 From aaed41ec5b8d734f79d7b87723190256ac6a0926 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Sep 2013 18:44:39 -0400 Subject: drm/edid: catch kmalloc failure in drm_edid_to_speaker_allocation Return -ENOMEM if the allocation fails. Signed-off-by: Alex Deucher Reviewed-by: Jani Nikula --- drivers/gpu/drm/drm_edid.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 1688ff500513..830f7501cb4d 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2925,6 +2925,8 @@ int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb) /* Speaker Allocation Data Block */ if (dbl == 3) { *sadb = kmalloc(dbl, GFP_KERNEL); + if (!*sadb) + return -ENOMEM; memcpy(*sadb, &db[1], dbl); count = dbl; break; -- cgit v1.2.3 From 062c2e4363451d49ef840232fe65e8bff0dde2a5 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Sep 2013 18:09:54 -0400 Subject: drm/radeon: use 64-bit math to calculate CTS values for audio (v2) Avoid losing precision. See bug: https://bugs.freedesktop.org/show_bug.cgi?id=69675 v2: fix math as per Anssi's comments. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_hdmi.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index b0fa6002af3e..49043a5ac65c 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -75,8 +75,15 @@ static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { */ static void r600_hdmi_calc_cts(uint32_t clock, int *CTS, int N, int freq) { - if (*CTS == 0) - *CTS = clock * N / (128 * freq) * 1000; + u64 n; + u32 d; + + if (*CTS == 0) { + n = (u64)clock * (u64)N * 1000ULL; + d = 128 * freq; + do_div(n, d); + *CTS = n; + } DRM_DEBUG("Using ACR timing N=%d CTS=%d for frequency %d\n", N, *CTS, freq); } -- cgit v1.2.3 From e7d12c2f98ae1e68c7298e5028048d150fa553a1 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Sep 2013 18:19:42 -0400 Subject: drm/radeon: fix N/CTS clock matching for audio The drm code that calculates the 1001 clocks rounds up rather than truncating. This allows the table to match properly on those modes. See bug: https://bugs.freedesktop.org/show_bug.cgi?id=69675 Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/r600_hdmi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 49043a5ac65c..567703fdfbf1 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -57,15 +57,15 @@ enum r600_hdmi_iec_status_bits { static const struct radeon_hdmi_acr r600_hdmi_predefined_acr[] = { /* 32kHz 44.1kHz 48kHz */ /* Clock N CTS N CTS N CTS */ - { 25174, 4576, 28125, 7007, 31250, 6864, 28125 }, /* 25,20/1.001 MHz */ + { 25175, 4576, 28125, 7007, 31250, 6864, 28125 }, /* 25,20/1.001 MHz */ { 25200, 4096, 25200, 6272, 28000, 6144, 25200 }, /* 25.20 MHz */ { 27000, 4096, 27000, 6272, 30000, 6144, 27000 }, /* 27.00 MHz */ { 27027, 4096, 27027, 6272, 30030, 6144, 27027 }, /* 27.00*1.001 MHz */ { 54000, 4096, 54000, 6272, 60000, 6144, 54000 }, /* 54.00 MHz */ { 54054, 4096, 54054, 6272, 60060, 6144, 54054 }, /* 54.00*1.001 MHz */ - { 74175, 11648, 210937, 17836, 234375, 11648, 140625 }, /* 74.25/1.001 MHz */ + { 74176, 11648, 210937, 17836, 234375, 11648, 140625 }, /* 74.25/1.001 MHz */ { 74250, 4096, 74250, 6272, 82500, 6144, 74250 }, /* 74.25 MHz */ - { 148351, 11648, 421875, 8918, 234375, 5824, 140625 }, /* 148.50/1.001 MHz */ + { 148352, 11648, 421875, 8918, 234375, 5824, 140625 }, /* 148.50/1.001 MHz */ { 148500, 4096, 148500, 6272, 165000, 6144, 148500 }, /* 148.50 MHz */ { 0, 4096, 0, 6272, 0, 6144, 0 } /* Other */ }; -- cgit v1.2.3 From ee0fec312a1c4e26f255955da942562cd8908a4b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 27 Sep 2013 18:22:15 -0400 Subject: drm/radeon: use hw generated CTS/N values for audio Use the hw generated values rather than calculating them in the driver. There may be some older r6xx asics where this doesn't work correctly. This remains to be seen. See bug: https://bugs.freedesktop.org/show_bug.cgi?id=69675 Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/evergreen_hdmi.c | 3 +-- drivers/gpu/drm/radeon/r600_hdmi.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index f71ce390aebe..f815c20640bd 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -288,8 +288,7 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode /* fglrx clears sth in AFMT_AUDIO_PACKET_CONTROL2 here */ WREG32(HDMI_ACR_PACKET_CONTROL + offset, - HDMI_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */ - HDMI_ACR_SOURCE); /* select SW CTS value */ + HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ evergreen_hdmi_update_ACR(encoder, mode->clock); diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 567703fdfbf1..e2ae1c237fb4 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -451,8 +451,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod } WREG32(HDMI0_ACR_PACKET_CONTROL + offset, - HDMI0_ACR_AUTO_SEND | /* allow hw to sent ACR packets when required */ - HDMI0_ACR_SOURCE); /* select SW CTS value */ + HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ WREG32(HDMI0_VBI_PACKET_CONTROL + offset, HDMI0_NULL_SEND | /* send null packets when required */ -- cgit v1.2.3 From dca5086a90c9ec64f4e0de801a659508202b0640 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 30 Sep 2013 19:11:24 -0400 Subject: drm/radeon/dpm: disable multiple UVD states Always use the regular UVD state for now. This fixes a performance regression with UVD playback on certain APUs. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_pm.c | 3 +++ drivers/gpu/drm/radeon/radeon_uvd.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index ac07ad1d4f8c..4f6b7fc7ad3c 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -945,6 +945,8 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable) if (enable) { mutex_lock(&rdev->pm.mutex); rdev->pm.dpm.uvd_active = true; + /* disable this for now */ +#if 0 if ((rdev->pm.dpm.sd == 1) && (rdev->pm.dpm.hd == 0)) dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_SD; else if ((rdev->pm.dpm.sd == 2) && (rdev->pm.dpm.hd == 0)) @@ -954,6 +956,7 @@ void radeon_dpm_enable_uvd(struct radeon_device *rdev, bool enable) else if ((rdev->pm.dpm.sd == 0) && (rdev->pm.dpm.hd == 2)) dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD2; else +#endif dpm_state = POWER_STATE_TYPE_INTERNAL_UVD; rdev->pm.dpm.state = dpm_state; mutex_unlock(&rdev->pm.mutex); diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index a0f11856ddde..4f2e73f79638 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -798,7 +798,8 @@ void radeon_uvd_note_usage(struct radeon_device *rdev) (rdev->pm.dpm.hd != hd)) { rdev->pm.dpm.sd = sd; rdev->pm.dpm.hd = hd; - streams_changed = true; + /* disable this for now */ + /*streams_changed = true;*/ } } -- cgit v1.2.3 From aa3e146d04b6ae37939daeebaec060562b3db559 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 1 Oct 2013 16:40:45 -0400 Subject: drm/radeon: fix typo in CP DMA register headers Wrong bit offset for SRC endian swapping. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/evergreend.h | 4 ++-- drivers/gpu/drm/radeon/r600d.h | 2 +- drivers/gpu/drm/radeon/sid.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 8768fd6a1e27..4f6d2962767d 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -1501,7 +1501,7 @@ * 6. COMMAND [29:22] | BYTE_COUNT [20:0] */ # define PACKET3_CP_DMA_DST_SEL(x) ((x) << 20) - /* 0 - SRC_ADDR + /* 0 - DST_ADDR * 1 - GDS */ # define PACKET3_CP_DMA_ENGINE(x) ((x) << 27) @@ -1516,7 +1516,7 @@ # define PACKET3_CP_DMA_CP_SYNC (1 << 31) /* COMMAND */ # define PACKET3_CP_DMA_DIS_WC (1 << 21) -# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 23) +# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 22) /* 0 - none * 1 - 8 in 16 * 2 - 8 in 32 diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index e673fe26ea84..7b3c7b5932c5 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -1523,7 +1523,7 @@ */ # define PACKET3_CP_DMA_CP_SYNC (1 << 31) /* COMMAND */ -# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 23) +# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 22) /* 0 - none * 1 - 8 in 16 * 2 - 8 in 32 diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 52d2ab6b67a0..7e2e0ea66a00 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -1553,7 +1553,7 @@ * 6. COMMAND [30:21] | BYTE_COUNT [20:0] */ # define PACKET3_CP_DMA_DST_SEL(x) ((x) << 20) - /* 0 - SRC_ADDR + /* 0 - DST_ADDR * 1 - GDS */ # define PACKET3_CP_DMA_ENGINE(x) ((x) << 27) @@ -1568,7 +1568,7 @@ # define PACKET3_CP_DMA_CP_SYNC (1 << 31) /* COMMAND */ # define PACKET3_CP_DMA_DIS_WC (1 << 21) -# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 23) +# define PACKET3_CP_DMA_CMD_SRC_SWAP(x) ((x) << 22) /* 0 - none * 1 - 8 in 16 * 2 - 8 in 32 -- cgit v1.2.3 From 50b8f5aec04ebec7dbdf2adb17220b9148c99e63 Mon Sep 17 00:00:00 2001 From: wojciech kapuscinski Date: Tue, 1 Oct 2013 19:54:33 -0400 Subject: drm/radeon: fix hw contexts for SUMO2 asics They have 4 rather than 8. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=63599 Signed-off-by: wojciech kapuscinski Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/evergreen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 555164e270a7..b5c67a99dda9 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -3131,7 +3131,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sx_max_export_size = 256; rdev->config.evergreen.sx_max_export_pos_size = 64; rdev->config.evergreen.sx_max_export_smx_size = 192; - rdev->config.evergreen.max_hw_contexts = 8; + rdev->config.evergreen.max_hw_contexts = 4; rdev->config.evergreen.sq_num_cf_insts = 2; rdev->config.evergreen.sc_prim_fifo_size = 0x40; -- cgit v1.2.3 From 89cd67b326fa95872cc2b4524cd807128db6071d Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 1 Jul 2013 19:39:34 +0300 Subject: drm/radeon: forever loop on error in radeon_do_test_moves() The error path does this: for (--i; i >= 0; --i) { which is a forever loop because "i" is unsigned. Signed-off-by: Dan Carpenter Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c index f4d6bcee9006..12e8099a0823 100644 --- a/drivers/gpu/drm/radeon/radeon_test.c +++ b/drivers/gpu/drm/radeon/radeon_test.c @@ -36,8 +36,8 @@ static void radeon_do_test_moves(struct radeon_device *rdev, int flag) struct radeon_bo *vram_obj = NULL; struct radeon_bo **gtt_obj = NULL; uint64_t gtt_addr, vram_addr; - unsigned i, n, size; - int r, ring; + unsigned n, size; + int i, r, ring; switch (flag) { case RADEON_TEST_COPY_DMA: -- cgit v1.2.3 From 96d8df846f52a720c8ae1fadadfad7c9e733e336 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 27 Sep 2013 23:18:39 +0300 Subject: drm/radeon/dpm/btc: off by one in btc_set_mc_special_registers() It should be ">=" instead of ">" here. The table->mc_reg_address[] array has SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE (16) elements. Signed-off-by: Dan Carpenter Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/btc_dpm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c index b162e98a2953..9b6950d9b3c0 100644 --- a/drivers/gpu/drm/radeon/btc_dpm.c +++ b/drivers/gpu/drm/radeon/btc_dpm.c @@ -1930,7 +1930,7 @@ static int btc_set_mc_special_registers(struct radeon_device *rdev, } j++; - if (j > SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE) + if (j >= SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE) return -EINVAL; tmp = RREG32(MC_PMG_CMD_MRS); @@ -1945,7 +1945,7 @@ static int btc_set_mc_special_registers(struct radeon_device *rdev, } j++; - if (j > SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE) + if (j >= SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE) return -EINVAL; break; case MC_SEQ_RESERVE_M >> 2: @@ -1959,7 +1959,7 @@ static int btc_set_mc_special_registers(struct radeon_device *rdev, } j++; - if (j > SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE) + if (j >= SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE) return -EINVAL; break; default: -- cgit v1.2.3 From 5fd9c581862a4874c0bdaf16231d8873832bbb99 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 28 Sep 2013 12:35:31 +0300 Subject: drm/radeon/dpm: off by one in si_set_mc_special_registers() These checks should be ">=" instead of ">". j is used as an offset into the table->mc_reg_address[] array and that has SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE (16) elements. Signed-off-by: Dan Carpenter Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/si_dpm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 9ace28702c76..2332aa1bf93c 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -5208,7 +5208,7 @@ static int si_set_mc_special_registers(struct radeon_device *rdev, table->mc_reg_table_entry[k].mc_data[j] |= 0x100; } j++; - if (j > SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) + if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) return -EINVAL; if (!pi->mem_gddr5) { @@ -5218,7 +5218,7 @@ static int si_set_mc_special_registers(struct radeon_device *rdev, table->mc_reg_table_entry[k].mc_data[j] = (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; j++; - if (j > SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) + if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) return -EINVAL; } break; @@ -5231,7 +5231,7 @@ static int si_set_mc_special_registers(struct radeon_device *rdev, (temp_reg & 0xffff0000) | (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); j++; - if (j > SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) + if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) return -EINVAL; break; default: -- cgit v1.2.3 From a6f4ae8dc904ad0e4e416800172fc88f716314dd Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 2 Oct 2013 14:50:57 -0400 Subject: drm/radeon: improve soft reset on SI Disable CG/PG and stop the rlc before resetting. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/si.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index c354c1094967..d4652af425b8 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -85,6 +85,9 @@ extern void si_dma_vm_set_page(struct radeon_device *rdev, uint32_t incr, uint32_t flags); static void si_enable_gui_idle_interrupt(struct radeon_device *rdev, bool enable); +static void si_fini_pg(struct radeon_device *rdev); +static void si_fini_cg(struct radeon_device *rdev); +static void si_rlc_stop(struct radeon_device *rdev); static const u32 verde_rlc_save_restore_register_list[] = { @@ -3608,6 +3611,13 @@ static void si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) dev_info(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS)); + /* disable PG/CG */ + si_fini_pg(rdev); + si_fini_cg(rdev); + + /* stop the rlc */ + si_rlc_stop(rdev); + /* Disable CP parsing/prefetching */ WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT | CP_CE_HALT); -- cgit v1.2.3 From fb2c7f4d2e7a40fa4d5cc589f21dad89b371edb0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 2 Oct 2013 14:54:44 -0400 Subject: drm/radeon: improve soft reset on CIK Disable CG/PG before resetting. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index d02fd1c045d5..b874ccdf52f7 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -77,6 +77,8 @@ static void cik_pcie_gen3_enable(struct radeon_device *rdev); static void cik_program_aspm(struct radeon_device *rdev); static void cik_init_pg(struct radeon_device *rdev); static void cik_init_cg(struct radeon_device *rdev); +static void cik_fini_pg(struct radeon_device *rdev); +static void cik_fini_cg(struct radeon_device *rdev); static void cik_enable_gui_idle_interrupt(struct radeon_device *rdev, bool enable); @@ -4185,6 +4187,10 @@ static void cik_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) dev_info(rdev->dev, " VM_CONTEXT1_PROTECTION_FAULT_STATUS 0x%08X\n", RREG32(VM_CONTEXT1_PROTECTION_FAULT_STATUS)); + /* disable CG/PG */ + cik_fini_pg(rdev); + cik_fini_cg(rdev); + /* stop the rlc */ cik_rlc_stop(rdev); -- cgit v1.2.3 From 4076a65544e2de310cbf4eaadb13ee15bbfaaf4f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 7 Oct 2013 21:25:39 -0400 Subject: drm/radeon/dpm: disable bapm on TN asics Causes hangs on certain boards. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=70053 Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/trinity_dpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c index 7f998bf1cc9d..9364129ba292 100644 --- a/drivers/gpu/drm/radeon/trinity_dpm.c +++ b/drivers/gpu/drm/radeon/trinity_dpm.c @@ -1868,7 +1868,7 @@ int trinity_dpm_init(struct radeon_device *rdev) for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) pi->at[i] = TRINITY_AT_DFLT; - pi->enable_bapm = true; + pi->enable_bapm = false; pi->enable_nbps_policy = true; pi->enable_sclk_ds = true; pi->enable_gfx_power_gating = true; -- cgit v1.2.3 From b852c985010a77c850b7548d64bbb964ca462b02 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Oct 2013 11:47:01 -0400 Subject: drm/radeon: re-enable sw ACR support on pre-DCE4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HW ACR support may have issues on some older chips, so use SW ACR for now until we've tested further. Signed-off-by: Alex Deucher CC: Rafał Miłecki --- drivers/gpu/drm/radeon/r600_hdmi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index e2ae1c237fb4..5b729319f27b 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -451,6 +451,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod } WREG32(HDMI0_ACR_PACKET_CONTROL + offset, + HDMI0_ACR_SOURCE | /* select SW CTS value - XXX verify that hw CTS works on all families */ HDMI0_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ WREG32(HDMI0_VBI_PACKET_CONTROL + offset, -- cgit v1.2.3 From e1264ebe9ff48e1b3e1dd11805eec9f5b143ab7c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 11 Oct 2013 15:11:52 +1000 Subject: Revert "drm/i915: Delay disabling of VGA memory until vgacon->fbcon handoff is done" This reverts commit 6e1b4fdad5157bb9e88777d525704aba24389bee. This is part of a revert due to a userspace breakage, better explained in the revert of 1a1a4cbf4906a13c0c377f708df5d94168e7b582. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_dma.c | 6 ------ drivers/gpu/drm/i915/intel_display.c | 27 +++++++++++---------------- drivers/gpu/drm/i915/intel_drv.h | 1 - 3 files changed, 11 insertions(+), 23 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index c27a21034a5e..52f5ad8037cc 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1351,12 +1351,6 @@ static int i915_load_modeset_init(struct drm_device *dev) */ intel_fbdev_initial_config(dev); - /* - * Must do this after fbcon init so that - * vgacon_save_screen() works during the handover. - */ - i915_disable_vga_mem(dev); - /* Only enable hotplug handling once the fbdev is fully set up. */ dev_priv->enable_hotplug_processing = true; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c89abd33124f..aaea3ec811ed 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10038,6 +10038,15 @@ static void i915_disable_vga(struct drm_device *dev) outb(SR01, VGA_SR_INDEX); sr1 = inb(VGA_SR_DATA); outb(sr1 | 1<<5, VGA_SR_DATA); + + /* Disable VGA memory on Intel HD */ + if (HAS_PCH_SPLIT(dev)) { + outb(inb(VGA_MSR_READ) & ~VGA_MSR_MEM_EN, VGA_MSR_WRITE); + vga_set_legacy_decoding(dev->pdev, VGA_RSRC_LEGACY_IO | + VGA_RSRC_NORMAL_IO | + VGA_RSRC_NORMAL_MEM); + } + vga_put(dev->pdev, VGA_RSRC_LEGACY_IO); udelay(300); @@ -10045,7 +10054,7 @@ static void i915_disable_vga(struct drm_device *dev) POSTING_READ(vga_reg); } -static void i915_enable_vga_mem(struct drm_device *dev) +static void i915_enable_vga(struct drm_device *dev) { /* Enable VGA memory on Intel HD */ if (HAS_PCH_SPLIT(dev)) { @@ -10059,19 +10068,6 @@ static void i915_enable_vga_mem(struct drm_device *dev) } } -void i915_disable_vga_mem(struct drm_device *dev) -{ - /* Disable VGA memory on Intel HD */ - if (HAS_PCH_SPLIT(dev)) { - vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO); - outb(inb(VGA_MSR_READ) & ~VGA_MSR_MEM_EN, VGA_MSR_WRITE); - vga_set_legacy_decoding(dev->pdev, VGA_RSRC_LEGACY_IO | - VGA_RSRC_NORMAL_IO | - VGA_RSRC_NORMAL_MEM); - vga_put(dev->pdev, VGA_RSRC_LEGACY_IO); - } -} - void intel_modeset_init_hw(struct drm_device *dev) { intel_init_power_well(dev); @@ -10350,7 +10346,6 @@ void i915_redisable_vga(struct drm_device *dev) if (I915_READ(vga_reg) != VGA_DISP_DISABLE) { DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n"); i915_disable_vga(dev); - i915_disable_vga_mem(dev); } } @@ -10564,7 +10559,7 @@ void intel_modeset_cleanup(struct drm_device *dev) intel_disable_fbc(dev); - i915_enable_vga_mem(dev); + i915_enable_vga(dev); intel_disable_gt_powersave(dev); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 28cae80495e2..9b7b68fd5d47 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -793,6 +793,5 @@ extern void hsw_pc8_disable_interrupts(struct drm_device *dev); extern void hsw_pc8_restore_interrupts(struct drm_device *dev); extern void intel_aux_display_runtime_get(struct drm_i915_private *dev_priv); extern void intel_aux_display_runtime_put(struct drm_i915_private *dev_priv); -extern void i915_disable_vga_mem(struct drm_device *dev); #endif /* __INTEL_DRV_H__ */ -- cgit v1.2.3 From ebff5fa9d545574324095d9c6a3cb80c9157abc5 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 11 Oct 2013 15:12:04 +1000 Subject: Revert "i915: Update VGA arbiter support for newer devices" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 81b5c7bc8de3e6f63419139c2fc91bf81dea8a7d. Adding drm/i915 into the vga arbiter chain means that X (in a piece of well-meant paranoia) will do a get/put on the vga decoding around _every_ accel call down into the ddx. Which results in some nice performance disasters [1]. This really breaks userspace, by disabling DRI for everyone, and stops OpenGL from working, this isn't limited to just the i915 but both the integrated and discrete GPUs on multi-gpu systems, in other words this causes untold worlds of pain, Ville tried to come up with a Great Hack to fiddle the required VGA I/O ops behind everyone's back using stop_machine, but that didn't really work out [2]. Given that we're fairly late in the -rc stage for such games let's just revert this all. One thing we might want to keep is to delay the disabling of the vga decoding until the fbdev emulation and the fbcon screen is set up. If we kill vga mem decoding beforehand fbcon can end up with a white square in the top-left corner it tried to save from the vga memory for a seamless transition. And we have bug reports on older platforms which seem to match these symptoms. But again that's something to play around with in -next. References: [1] http://lists.x.org/archives/xorg-devel/2013-September/037763.html References: [2] http://www.spinics.net/lists/intel-gfx/msg34062.html Cc: Alex Williamson Cc: Ville Syrjälä Cc: Chris Wilson Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/i915_dma.c | 9 +++------ drivers/gpu/drm/i915/intel_display.c | 25 ------------------------- include/linux/vgaarb.h | 7 ------- 3 files changed, 3 insertions(+), 38 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 52f5ad8037cc..d5c784d48671 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1290,12 +1290,9 @@ static int i915_load_modeset_init(struct drm_device *dev) * then we do not take part in VGA arbitration and the * vga_client_register() fails with -ENODEV. */ - if (!HAS_PCH_SPLIT(dev)) { - ret = vga_client_register(dev->pdev, dev, NULL, - i915_vga_set_decode); - if (ret && ret != -ENODEV) - goto out; - } + ret = vga_client_register(dev->pdev, dev, NULL, i915_vga_set_decode); + if (ret && ret != -ENODEV) + goto out; intel_register_dsm_handler(); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index aaea3ec811ed..581fb4b2f766 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10038,15 +10038,6 @@ static void i915_disable_vga(struct drm_device *dev) outb(SR01, VGA_SR_INDEX); sr1 = inb(VGA_SR_DATA); outb(sr1 | 1<<5, VGA_SR_DATA); - - /* Disable VGA memory on Intel HD */ - if (HAS_PCH_SPLIT(dev)) { - outb(inb(VGA_MSR_READ) & ~VGA_MSR_MEM_EN, VGA_MSR_WRITE); - vga_set_legacy_decoding(dev->pdev, VGA_RSRC_LEGACY_IO | - VGA_RSRC_NORMAL_IO | - VGA_RSRC_NORMAL_MEM); - } - vga_put(dev->pdev, VGA_RSRC_LEGACY_IO); udelay(300); @@ -10054,20 +10045,6 @@ static void i915_disable_vga(struct drm_device *dev) POSTING_READ(vga_reg); } -static void i915_enable_vga(struct drm_device *dev) -{ - /* Enable VGA memory on Intel HD */ - if (HAS_PCH_SPLIT(dev)) { - vga_get_uninterruptible(dev->pdev, VGA_RSRC_LEGACY_IO); - outb(inb(VGA_MSR_READ) | VGA_MSR_MEM_EN, VGA_MSR_WRITE); - vga_set_legacy_decoding(dev->pdev, VGA_RSRC_LEGACY_IO | - VGA_RSRC_LEGACY_MEM | - VGA_RSRC_NORMAL_IO | - VGA_RSRC_NORMAL_MEM); - vga_put(dev->pdev, VGA_RSRC_LEGACY_IO); - } -} - void intel_modeset_init_hw(struct drm_device *dev) { intel_init_power_well(dev); @@ -10559,8 +10536,6 @@ void intel_modeset_cleanup(struct drm_device *dev) intel_disable_fbc(dev); - i915_enable_vga(dev); - intel_disable_gt_powersave(dev); ironlake_teardown_rc6(dev); diff --git a/include/linux/vgaarb.h b/include/linux/vgaarb.h index 80cf8173a65b..2c02f3a8d2ba 100644 --- a/include/linux/vgaarb.h +++ b/include/linux/vgaarb.h @@ -65,15 +65,8 @@ struct pci_dev; * out of the arbitration process (and can be safe to take * interrupts at any time. */ -#if defined(CONFIG_VGA_ARB) extern void vga_set_legacy_decoding(struct pci_dev *pdev, unsigned int decodes); -#else -static inline void vga_set_legacy_decoding(struct pci_dev *pdev, - unsigned int decodes) -{ -} -#endif /** * vga_get - acquire & locks VGA resources -- cgit v1.2.3 From cd66407810869709e0d6764409137d48c6812cfc Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 2 Oct 2013 10:34:19 -0700 Subject: drm/i915: disable LVDS clock gating on CPT v2 Needed to prevent display corruption in high res panels. v2: use correct unit names (Rodrigo) Signed-off-by: Jesse Barnes Tested-by: Ulrich Drepper Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 38f96f65d87a..fd721ea8728e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4279,7 +4279,9 @@ #define FDI_RX_CHICKEN(pipe) _PIPE(pipe, _FDI_RXA_CHICKEN, _FDI_RXB_CHICKEN) #define SOUTH_DSPCLK_GATE_D 0xc2020 +#define PCH_DPLUNIT_CLOCK_GATE_DISABLE (1<<30) #define PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1<<29) +#define PCH_CPUNIT_CLOCK_GATE_DISABLE (1<<14) #define PCH_LP_PARTITION_LEVEL_DISABLE (1<<12) /* CPU: FDI_TX */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f4c5e95b2d6f..26c2ea3e985c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4759,7 +4759,9 @@ static void cpt_init_clock_gating(struct drm_device *dev) * gating for the panel power sequencer or it will fail to * start up when no ports are active. */ - I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE); + I915_WRITE(SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE | + PCH_DPLUNIT_CLOCK_GATE_DISABLE | + PCH_CPUNIT_CLOCK_GATE_DISABLE); I915_WRITE(SOUTH_CHICKEN2, I915_READ(SOUTH_CHICKEN2) | DPLS_EDP_PPS_FIX_DIS); /* The below fixes the weird display corruption, a few pixels shifted -- cgit v1.2.3 From 26682480c202e7360cbcdc3bc9e962bf749c6b8d Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 9 Oct 2013 01:42:50 -0700 Subject: drm/vmwgfx: Don't put resources with invalid id's on lru list The evict code may try to swap them out causing a BUG in the destroy function. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 0e67cf41065d..37fb4befec82 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -970,7 +970,7 @@ void vmw_resource_unreserve(struct vmw_resource *res, if (new_backup) res->backup_offset = new_backup_offset; - if (!res->func->may_evict) + if (!res->func->may_evict || res->id == -1) return; write_lock(&dev_priv->resource_lock); -- cgit v1.2.3 From c4249855ac5b2a383704d31e040d3831d6a25c6f Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 9 Oct 2013 01:42:51 -0700 Subject: drm/vmwgfx: Don't kill clients on VT switch DRI clients that tried to grab the TTM lock when the master (X server) was switched away during a VT switch were sent the SIGTERM signal by the kernel. Fix this so that they are only sent that signal when the master has exited. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 1a90f0a2f7e5..0508f93b9795 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -740,9 +740,17 @@ static void vmw_postclose(struct drm_device *dev, struct vmw_fpriv *vmw_fp; vmw_fp = vmw_fpriv(file_priv); - ttm_object_file_release(&vmw_fp->tfile); - if (vmw_fp->locked_master) + + if (vmw_fp->locked_master) { + struct vmw_master *vmaster = + vmw_master(vmw_fp->locked_master); + + ttm_lock_set_kill(&vmaster->lock, true, SIGTERM); + ttm_vt_unlock(&vmaster->lock); drm_master_put(&vmw_fp->locked_master); + } + + ttm_object_file_release(&vmw_fp->tfile); kfree(vmw_fp); } @@ -925,14 +933,13 @@ static void vmw_master_drop(struct drm_device *dev, vmw_fp->locked_master = drm_master_get(file_priv->master); ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile); - vmw_execbuf_release_pinned_bo(dev_priv); - if (unlikely((ret != 0))) { DRM_ERROR("Unable to lock TTM at VT switch.\n"); drm_master_put(&vmw_fp->locked_master); } - ttm_lock_set_kill(&vmaster->lock, true, SIGTERM); + ttm_lock_set_kill(&vmaster->lock, false, SIGTERM); + vmw_execbuf_release_pinned_bo(dev_priv); if (!dev_priv->enable_fb) { ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM); -- cgit v1.2.3 From b062672e305ce071f21eb9e18b102c2a430e0999 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 16 Oct 2013 11:22:44 +0100 Subject: drm: Prevent overwriting from userspace underallocating core ioctl structs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply the protections from commit 1b2f1489633888d4a06028315dc19d65768a1c05 Author: Dave Airlie Date: Sat Aug 14 20:20:34 2010 +1000 drm: block userspace under allocating buffer and having drivers overwrite it (v2) to the core ioctl structs as well, for we found one instance where there is a 32-/64-bit size mismatch and were guilty of writing beyond the end of the user's buffer. Signed-off-by: Chris Wilson Cc: Dave Airlie Reviewed-by: Ville Syrjälä Cc: dri-devel@lists.freedesktop.org Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_drv.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index e572dd20bdee..05ad9ba0a67e 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -402,9 +402,16 @@ long drm_ioctl(struct file *filp, cmd = ioctl->cmd_drv; } else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) { + u32 drv_size; + ioctl = &drm_ioctls[nr]; - cmd = ioctl->cmd; + + drv_size = _IOC_SIZE(ioctl->cmd); usize = asize = _IOC_SIZE(cmd); + if (drv_size > asize) + asize = drv_size; + + cmd = ioctl->cmd; } else goto err_i1; -- cgit v1.2.3 From b35b380ed46bb01726bec1795e6443e625306757 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Wed, 16 Oct 2013 09:18:21 -0700 Subject: drm/i915: Make PTE valid encoding optional We need this to work around a corruption when the boot kernel image loads the hibernated kernel image from swap on Haswell systems - somehow not everything is properly shut off. This is just the prep work, the next patch will implement the actual workaround. Signed-off-by: Ben Widawsky [danvet: Add a commit message suitable for -fixes and add cc: stable] Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_gem_gtt.c | 35 ++++++++++++++++++++--------------- 2 files changed, 22 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 35874b3a86dc..3979a81dd6ee 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -497,7 +497,8 @@ struct i915_address_space { /* FIXME: Need a more generic return type */ gen6_gtt_pte_t (*pte_encode)(dma_addr_t addr, - enum i915_cache_level level); + enum i915_cache_level level, + bool valid); /* Create a valid PTE */ void (*clear_range)(struct i915_address_space *vm, unsigned int first_entry, unsigned int num_entries); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 212f6d8c35ec..32aa69d7ef20 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -58,9 +58,10 @@ #define HSW_WT_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x6) static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr, - enum i915_cache_level level) + enum i915_cache_level level, + bool valid) { - gen6_gtt_pte_t pte = GEN6_PTE_VALID; + gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; pte |= GEN6_PTE_ADDR_ENCODE(addr); switch (level) { @@ -79,9 +80,10 @@ static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr, } static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr, - enum i915_cache_level level) + enum i915_cache_level level, + bool valid) { - gen6_gtt_pte_t pte = GEN6_PTE_VALID; + gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; pte |= GEN6_PTE_ADDR_ENCODE(addr); switch (level) { @@ -105,9 +107,10 @@ static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr, #define BYT_PTE_SNOOPED_BY_CPU_CACHES (1 << 2) static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr, - enum i915_cache_level level) + enum i915_cache_level level, + bool valid) { - gen6_gtt_pte_t pte = GEN6_PTE_VALID; + gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; pte |= GEN6_PTE_ADDR_ENCODE(addr); /* Mark the page as writeable. Other platforms don't have a @@ -122,9 +125,10 @@ static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr, } static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr, - enum i915_cache_level level) + enum i915_cache_level level, + bool valid) { - gen6_gtt_pte_t pte = GEN6_PTE_VALID; + gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; pte |= HSW_PTE_ADDR_ENCODE(addr); if (level != I915_CACHE_NONE) @@ -134,9 +138,10 @@ static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr, } static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr, - enum i915_cache_level level) + enum i915_cache_level level, + bool valid) { - gen6_gtt_pte_t pte = GEN6_PTE_VALID; + gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; pte |= HSW_PTE_ADDR_ENCODE(addr); switch (level) { @@ -245,7 +250,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; unsigned last_pte, i; - scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC); + scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true); while (num_entries) { last_pte = first_pte + num_entries; @@ -282,7 +287,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, dma_addr_t page_addr; page_addr = sg_page_iter_dma_address(&sg_iter); - pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level); + pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level, true); if (++act_pte == I915_PPGTT_PT_ENTRIES) { kunmap_atomic(pt_vaddr); act_pt++; @@ -536,7 +541,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) { addr = sg_page_iter_dma_address(&sg_iter); - iowrite32(vm->pte_encode(addr, level), >t_entries[i]); + iowrite32(vm->pte_encode(addr, level, true), >t_entries[i]); i++; } @@ -548,7 +553,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, */ if (i != 0) WARN_ON(readl(>t_entries[i-1]) != - vm->pte_encode(addr, level)); + vm->pte_encode(addr, level, true)); /* This next bit makes the above posting read even more important. We * want to flush the TLBs only after we're certain all the PTE updates @@ -573,7 +578,7 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, first_entry, num_entries, max_entries)) num_entries = max_entries; - scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC); + scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true); for (i = 0; i < num_entries; i++) iowrite32(scratch_pte, >t_base[i]); readl(gtt_base); -- cgit v1.2.3 From 828c79087cec61eaf4c76bb32c222fbe35ac3930 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Wed, 16 Oct 2013 09:21:30 -0700 Subject: drm/i915: Disable GGTT PTEs on GEN6+ suspend Once the machine gets to a certain point in the suspend process, we expect the GPU to be idle. If it is not, we might corrupt memory. Empirically (with an early version of this patch) we have seen this is not the case. We cannot currently explain why the latent GPU writes occur. In the technical sense, this patch is a workaround in that we have an issue we can't explain, and the patch indirectly solves the issue. However, it's really better than a workaround because we understand why it works, and it really should be a safe thing to do in all cases. The noticeable effect other than the debug messages would be an increase in the suspend time. I have not measure how expensive it actually is. I think it would be good to spend further time to root cause why we're seeing these latent writes, but it shouldn't preclude preventing the fallout. NOTE: It should be safe (and makes some sense IMO) to also keep the VALID bit unset on resume when we clear_range(). I've opted not to do this as properly clearing those bits at some later point would be extra work. v2: Fix bugzilla link Bugzilla: http://bugs.freedesktop.org/show_bug.cgi?id=65496 Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=59321 Tested-by: Takashi Iwai Tested-by: Paulo Zanoni Signed-off-by: Ben Widawsky Tested-By: Todd Previte Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 5 ++- drivers/gpu/drm/i915/i915_drv.h | 5 ++- drivers/gpu/drm/i915/i915_gem_gtt.c | 76 ++++++++++++++++++++++++++++++++----- drivers/gpu/drm/i915/i915_reg.h | 4 ++ 4 files changed, 78 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 69d8ed5416c3..2ad27880cd04 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -505,6 +505,8 @@ static int i915_drm_freeze(struct drm_device *dev) intel_modeset_suspend_hw(dev); } + i915_gem_suspend_gtt_mappings(dev); + i915_save_state(dev); intel_opregion_fini(dev); @@ -648,7 +650,8 @@ static int i915_drm_thaw(struct drm_device *dev) mutex_lock(&dev->struct_mutex); i915_gem_restore_gtt_mappings(dev); mutex_unlock(&dev->struct_mutex); - } + } else if (drm_core_check_feature(dev, DRIVER_MODESET)) + i915_check_and_clear_faults(dev); __i915_drm_thaw(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3979a81dd6ee..ab0f2c0a440c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -501,7 +501,8 @@ struct i915_address_space { bool valid); /* Create a valid PTE */ void (*clear_range)(struct i915_address_space *vm, unsigned int first_entry, - unsigned int num_entries); + unsigned int num_entries, + bool use_scratch); void (*insert_entries)(struct i915_address_space *vm, struct sg_table *st, unsigned int first_entry, @@ -2066,6 +2067,8 @@ void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, struct drm_i915_gem_object *obj); +void i915_check_and_clear_faults(struct drm_device *dev); +void i915_gem_suspend_gtt_mappings(struct drm_device *dev); void i915_gem_restore_gtt_mappings(struct drm_device *dev); int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj); void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj, diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 32aa69d7ef20..1f7b4caefb6e 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -241,7 +241,8 @@ static int gen6_ppgtt_enable(struct drm_device *dev) /* PPGTT support for Sandybdrige/Gen6 and later */ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, unsigned first_entry, - unsigned num_entries) + unsigned num_entries, + bool use_scratch) { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); @@ -372,7 +373,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) } ppgtt->base.clear_range(&ppgtt->base, 0, - ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES); + ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES, true); ppgtt->pd_offset = first_pd_entry_in_global_pt * sizeof(gen6_gtt_pte_t); @@ -449,7 +450,8 @@ void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, { ppgtt->base.clear_range(&ppgtt->base, i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT, - obj->base.size >> PAGE_SHIFT); + obj->base.size >> PAGE_SHIFT, + true); } extern int intel_iommu_gfx_mapped; @@ -490,15 +492,65 @@ static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible) dev_priv->mm.interruptible = interruptible; } +void i915_check_and_clear_faults(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring; + int i; + + if (INTEL_INFO(dev)->gen < 6) + return; + + for_each_ring(ring, dev_priv, i) { + u32 fault_reg; + fault_reg = I915_READ(RING_FAULT_REG(ring)); + if (fault_reg & RING_FAULT_VALID) { + DRM_DEBUG_DRIVER("Unexpected fault\n" + "\tAddr: 0x%08lx\\n" + "\tAddress space: %s\n" + "\tSource ID: %d\n" + "\tType: %d\n", + fault_reg & PAGE_MASK, + fault_reg & RING_FAULT_GTTSEL_MASK ? "GGTT" : "PPGTT", + RING_FAULT_SRCID(fault_reg), + RING_FAULT_FAULT_TYPE(fault_reg)); + I915_WRITE(RING_FAULT_REG(ring), + fault_reg & ~RING_FAULT_VALID); + } + } + POSTING_READ(RING_FAULT_REG(&dev_priv->ring[RCS])); +} + +void i915_gem_suspend_gtt_mappings(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + /* Don't bother messing with faults pre GEN6 as we have little + * documentation supporting that it's a good idea. + */ + if (INTEL_INFO(dev)->gen < 6) + return; + + i915_check_and_clear_faults(dev); + + dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, + dev_priv->gtt.base.start / PAGE_SIZE, + dev_priv->gtt.base.total / PAGE_SIZE, + false); +} + void i915_gem_restore_gtt_mappings(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj; + i915_check_and_clear_faults(dev); + /* First fill our portion of the GTT with scratch pages */ dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, dev_priv->gtt.base.start / PAGE_SIZE, - dev_priv->gtt.base.total / PAGE_SIZE); + dev_priv->gtt.base.total / PAGE_SIZE, + true); list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { i915_gem_clflush_object(obj, obj->pin_display); @@ -565,7 +617,8 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, static void gen6_ggtt_clear_range(struct i915_address_space *vm, unsigned int first_entry, - unsigned int num_entries) + unsigned int num_entries, + bool use_scratch) { struct drm_i915_private *dev_priv = vm->dev->dev_private; gen6_gtt_pte_t scratch_pte, __iomem *gtt_base = @@ -578,7 +631,8 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, first_entry, num_entries, max_entries)) num_entries = max_entries; - scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true); + scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, use_scratch); + for (i = 0; i < num_entries; i++) iowrite32(scratch_pte, >t_base[i]); readl(gtt_base); @@ -599,7 +653,8 @@ static void i915_ggtt_insert_entries(struct i915_address_space *vm, static void i915_ggtt_clear_range(struct i915_address_space *vm, unsigned int first_entry, - unsigned int num_entries) + unsigned int num_entries, + bool unused) { intel_gtt_clear_range(first_entry, num_entries); } @@ -627,7 +682,8 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj) dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, entry, - obj->base.size >> PAGE_SHIFT); + obj->base.size >> PAGE_SHIFT, + true); obj->has_global_gtt_mapping = 0; } @@ -714,11 +770,11 @@ void i915_gem_setup_global_gtt(struct drm_device *dev, const unsigned long count = (hole_end - hole_start) / PAGE_SIZE; DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n", hole_start, hole_end); - ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count); + ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count, true); } /* And finally clear the reserved guard page */ - ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1); + ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1, true); } static bool diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index fd721ea8728e..ef9b35479f01 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -604,6 +604,10 @@ #define ARB_MODE_SWIZZLE_IVB (1<<5) #define RENDER_HWS_PGA_GEN7 (0x04080) #define RING_FAULT_REG(ring) (0x4094 + 0x100*(ring)->id) +#define RING_FAULT_GTTSEL_MASK (1<<11) +#define RING_FAULT_SRCID(x) ((x >> 3) & 0xff) +#define RING_FAULT_FAULT_TYPE(x) ((x >> 1) & 0x3) +#define RING_FAULT_VALID (1<<0) #define DONE_REG 0x40b0 #define BSD_HWS_PGA_GEN7 (0x04180) #define BLT_HWS_PGA_GEN7 (0x04280) -- cgit v1.2.3 From c23632d4e57c0dd20bf50eca08fa0eb8ad3ff680 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Oct 2013 16:45:27 -0400 Subject: drm/radeon/atom: workaround vbios bug in transmitter table on rs780 Some rs780 asics seem to be affected as well. See: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=91f3a6aaf280294b07c05dfe606e6c27b7ba3c72 Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=60791 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_encoders.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 32923d2f6002..2a761f29133c 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1655,7 +1655,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) * does the same thing and more. */ if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730) && - (rdev->family != CHIP_RS880)) + (rdev->family != CHIP_RS780) && (rdev->family != CHIP_RS880)) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { -- cgit v1.2.3 From 5510f124c6ee53cb52cf632240aea982d64c7d99 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 14 Oct 2013 11:32:28 +0200 Subject: drm/radeon: stop the leaks in cik_ib_test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stop leaking IB memory and scratch register space when the test fails. Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index b874ccdf52f7..8f393dfbd0e3 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -3182,6 +3182,7 @@ int cik_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) r = radeon_ib_get(rdev, ring->idx, &ib, NULL, 256); if (r) { DRM_ERROR("radeon: failed to get ib (%d).\n", r); + radeon_scratch_free(rdev, scratch); return r; } ib.ptr[0] = PACKET3(PACKET3_SET_UCONFIG_REG, 1); @@ -3198,6 +3199,8 @@ int cik_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) r = radeon_fence_wait(ib.fence, false); if (r) { DRM_ERROR("radeon: fence wait failed (%d).\n", r); + radeon_scratch_free(rdev, scratch); + radeon_ib_free(rdev, &ib); return r; } for (i = 0; i < rdev->usec_timeout; i++) { -- cgit v1.2.3 From bcf6f1e935b92aa40c259c5abb427ac49fc083eb Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 15 Oct 2013 20:12:03 +0200 Subject: drm/radeon/uvd: revert lower msg&fb buffer requirements on UVD3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This only seem to work for H.264 but not for VC-1 streams. Need to investigate further why exactly. This reverts commit 4b40e5921230beb1951f04d2b1b92c4c88fbad43. Signed-off-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_cs.c | 3 +-- drivers/gpu/drm/radeon/radeon_uvd.c | 3 ++- drivers/gpu/drm/radeon/uvd_v1_0.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 66c222836631..80285e35bc65 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -85,9 +85,8 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) VRAM, also but everything into VRAM on AGP cards to avoid image corruptions */ if (p->ring == R600_RING_TYPE_UVD_INDEX && - p->rdev->family < CHIP_PALM && (i == 0 || drm_pci_device_is_agp(p->rdev->ddev))) { - + /* TODO: is this still needed for NI+ ? */ p->relocs[i].lobj.domain = RADEON_GEM_DOMAIN_VRAM; diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 4f2e73f79638..308eff5be1b4 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -476,7 +476,8 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p, return -EINVAL; } - if (p->rdev->family < CHIP_PALM && (cmd == 0 || cmd == 0x3) && + /* TODO: is this still necessary on NI+ ? */ + if ((cmd == 0 || cmd == 0x3) && (start >> 28) != (p->rdev->uvd.gpu_addr >> 28)) { DRM_ERROR("msg/fb buffer %LX-%LX out of 256MB segment!\n", start, end); diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c index 3100fa9cb52f..7266805d9786 100644 --- a/drivers/gpu/drm/radeon/uvd_v1_0.c +++ b/drivers/gpu/drm/radeon/uvd_v1_0.c @@ -212,8 +212,8 @@ int uvd_v1_0_start(struct radeon_device *rdev) /* enable VCPU clock */ WREG32(UVD_VCPU_CNTL, 1 << 9); - /* enable UMC and NC0 */ - WREG32_P(UVD_LMI_CTRL2, 1 << 13, ~((1 << 8) | (1 << 13))); + /* enable UMC */ + WREG32_P(UVD_LMI_CTRL2, 0, ~(1 << 8)); /* boot up the VCPU */ WREG32(UVD_SOFT_RESET, 0); -- cgit v1.2.3 From d83671126dc8e7c0b56c9970ea5ffd08c3b0c645 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 16 Oct 2013 11:36:30 -0400 Subject: drm/radeon: make missing smc ucode non-fatal (r7xx-SI) Prevent driver load problems if the smc is missing. bug: https://bugzilla.kernel.org/show_bug.cgi?id=63011 Signed-off-by: Alex Deucher Tested-by: Mikko Rapeli Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/ni.c | 1 + drivers/gpu/drm/radeon/r600.c | 1 + drivers/gpu/drm/radeon/si.c | 1 + 3 files changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 93c1f9ef5da9..cac2866d79da 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -804,6 +804,7 @@ int ni_init_microcode(struct radeon_device *rdev) fw_name); release_firmware(rdev->smc_fw); rdev->smc_fw = NULL; + err = 0; } else if (rdev->smc_fw->size != smc_req_size) { printk(KERN_ERR "ni_mc: Bogus length %zu in firmware \"%s\"\n", diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 2a1b1876b431..f9be22062df1 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2302,6 +2302,7 @@ int r600_init_microcode(struct radeon_device *rdev) fw_name); release_firmware(rdev->smc_fw); rdev->smc_fw = NULL; + err = 0; } else if (rdev->smc_fw->size != smc_req_size) { printk(KERN_ERR "smc: Bogus length %zu in firmware \"%s\"\n", diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index d4652af425b8..d96f7cbca0a1 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -1681,6 +1681,7 @@ static int si_init_microcode(struct radeon_device *rdev) fw_name); release_firmware(rdev->smc_fw); rdev->smc_fw = NULL; + err = 0; } else if (rdev->smc_fw->size != smc_req_size) { printk(KERN_ERR "si_smc: Bogus length %zu in firmware \"%s\"\n", -- cgit v1.2.3 From d30d71e85a4fc932ede2efd8e54de5ed321aa448 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 16 Oct 2013 11:40:48 -0400 Subject: drm/radeon: make missing smc ucode non-fatal (CI) Prevent driver load problems if the smc is missing. bug: https://bugzilla.kernel.org/show_bug.cgi?id=63011 Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 8f393dfbd0e3..9cd2bc989ac7 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -1694,6 +1694,7 @@ static int cik_init_microcode(struct radeon_device *rdev) fw_name); release_firmware(rdev->smc_fw); rdev->smc_fw = NULL; + err = 0; } else if (rdev->smc_fw->size != smc_req_size) { printk(KERN_ERR "cik_smc: Bogus length %zu in firmware \"%s\"\n", -- cgit v1.2.3 From 4b7495770cc4a4e7973ea8079dd15d2618f3636a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 17 Oct 2013 16:11:27 -0400 Subject: drm/radeon/audio: don't set speaker allocation on DCE3.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It causes hangs on some asics. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=70439 Signed-off-by: Alex Deucher Reviewed-by: Christian König --- drivers/gpu/drm/radeon/r600_hdmi.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 5b729319f27b..06022e3b9c3b 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c @@ -309,6 +309,9 @@ static void dce3_2_afmt_write_speaker_allocation(struct drm_encoder *encoder) u8 *sadb; int sad_count; + /* XXX: setting this register causes hangs on some asics */ + return; + list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { if (connector->encoder == encoder) radeon_connector = to_radeon_connector(connector); -- cgit v1.2.3 From 108dc8e8b44a4c64ac53676cc05f6234340ccd4a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 14 Oct 2013 13:17:50 -0400 Subject: drm/radeon: rework audio option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In 3.12 I changed audio to be enabled by default, but you still had to turn it on via xrandr. This was confusing to users so change it to minic the previous behavior: - audio option is set to -1 (auto) by default which is the current 3.12 behavior (audio is enabled but requires xrandr to turn it on). - if audio = 1, the audio is enabled without needing to mess with xrandr (previous behavior) - audio = 0 disables audio It retains the new feature of allowing the user to enable audio on the fly with xrandr, but turns audio on automatically if radeon.audio=1 is set which is what most users expect. Signed-off-by: Alex Deucher Reviewed-by: Christian König --- drivers/gpu/drm/radeon/atombios_encoders.c | 52 ++++++++++++++++++++---------- drivers/gpu/drm/radeon/radeon_connectors.c | 33 ++++++++++++------- drivers/gpu/drm/radeon/radeon_drv.c | 4 +-- 3 files changed, 58 insertions(+), 31 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 2a761f29133c..5e891b226acf 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -707,24 +707,37 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) switch (connector->connector_type) { case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ - if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) || - (drm_detect_hdmi_monitor(radeon_connector->edid) && - (radeon_connector->audio == RADEON_AUDIO_AUTO))) - return ATOM_ENCODER_MODE_HDMI; - else if (radeon_connector->use_digital) + if (radeon_audio != 0) { + if (radeon_connector->use_digital && + (radeon_connector->audio == RADEON_AUDIO_ENABLE)) + return ATOM_ENCODER_MODE_HDMI; + else if (drm_detect_hdmi_monitor(radeon_connector->edid) && + (radeon_connector->audio == RADEON_AUDIO_AUTO)) + return ATOM_ENCODER_MODE_HDMI; + else if (radeon_connector->use_digital) + return ATOM_ENCODER_MODE_DVI; + else + return ATOM_ENCODER_MODE_CRT; + } else if (radeon_connector->use_digital) { return ATOM_ENCODER_MODE_DVI; - else + } else { return ATOM_ENCODER_MODE_CRT; + } break; case DRM_MODE_CONNECTOR_DVID: case DRM_MODE_CONNECTOR_HDMIA: default: - if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) || - (drm_detect_hdmi_monitor(radeon_connector->edid) && - (radeon_connector->audio == RADEON_AUDIO_AUTO))) - return ATOM_ENCODER_MODE_HDMI; - else + if (radeon_audio != 0) { + if (radeon_connector->audio == RADEON_AUDIO_ENABLE) + return ATOM_ENCODER_MODE_HDMI; + else if (drm_detect_hdmi_monitor(radeon_connector->edid) && + (radeon_connector->audio == RADEON_AUDIO_AUTO)) + return ATOM_ENCODER_MODE_HDMI; + else + return ATOM_ENCODER_MODE_DVI; + } else { return ATOM_ENCODER_MODE_DVI; + } break; case DRM_MODE_CONNECTOR_LVDS: return ATOM_ENCODER_MODE_LVDS; @@ -732,14 +745,19 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) case DRM_MODE_CONNECTOR_DisplayPort: dig_connector = radeon_connector->con_priv; if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || - (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) + (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { return ATOM_ENCODER_MODE_DP; - else if ((radeon_connector->audio == RADEON_AUDIO_ENABLE) || - (drm_detect_hdmi_monitor(radeon_connector->edid) && - (radeon_connector->audio == RADEON_AUDIO_AUTO))) - return ATOM_ENCODER_MODE_HDMI; - else + } else if (radeon_audio != 0) { + if (radeon_connector->audio == RADEON_AUDIO_ENABLE) + return ATOM_ENCODER_MODE_HDMI; + else if (drm_detect_hdmi_monitor(radeon_connector->edid) && + (radeon_connector->audio == RADEON_AUDIO_AUTO)) + return ATOM_ENCODER_MODE_HDMI; + else + return ATOM_ENCODER_MODE_DVI; + } else { return ATOM_ENCODER_MODE_DVI; + } break; case DRM_MODE_CONNECTOR_eDP: return ATOM_ENCODER_MODE_DP; diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 79159b5da05b..64565732cb98 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -1658,9 +1658,12 @@ radeon_add_atom_connector(struct drm_device *dev, drm_object_attach_property(&radeon_connector->base.base, rdev->mode_info.underscan_vborder_property, 0); - drm_object_attach_property(&radeon_connector->base.base, - rdev->mode_info.audio_property, - RADEON_AUDIO_DISABLE); + if (radeon_audio != 0) + drm_object_attach_property(&radeon_connector->base.base, + rdev->mode_info.audio_property, + (radeon_audio == 1) ? + RADEON_AUDIO_AUTO : + RADEON_AUDIO_DISABLE); subpixel_order = SubPixelHorizontalRGB; connector->interlace_allowed = true; if (connector_type == DRM_MODE_CONNECTOR_HDMIB) @@ -1754,10 +1757,12 @@ radeon_add_atom_connector(struct drm_device *dev, rdev->mode_info.underscan_vborder_property, 0); } - if (ASIC_IS_DCE2(rdev)) { + if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) { drm_object_attach_property(&radeon_connector->base.base, - rdev->mode_info.audio_property, - RADEON_AUDIO_DISABLE); + rdev->mode_info.audio_property, + (radeon_audio == 1) ? + RADEON_AUDIO_AUTO : + RADEON_AUDIO_DISABLE); } if (connector_type == DRM_MODE_CONNECTOR_DVII) { radeon_connector->dac_load_detect = true; @@ -1799,10 +1804,12 @@ radeon_add_atom_connector(struct drm_device *dev, rdev->mode_info.underscan_vborder_property, 0); } - if (ASIC_IS_DCE2(rdev)) { + if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) { drm_object_attach_property(&radeon_connector->base.base, - rdev->mode_info.audio_property, - RADEON_AUDIO_DISABLE); + rdev->mode_info.audio_property, + (radeon_audio == 1) ? + RADEON_AUDIO_AUTO : + RADEON_AUDIO_DISABLE); } subpixel_order = SubPixelHorizontalRGB; connector->interlace_allowed = true; @@ -1843,10 +1850,12 @@ radeon_add_atom_connector(struct drm_device *dev, rdev->mode_info.underscan_vborder_property, 0); } - if (ASIC_IS_DCE2(rdev)) { + if (ASIC_IS_DCE2(rdev) && (radeon_audio != 0)) { drm_object_attach_property(&radeon_connector->base.base, - rdev->mode_info.audio_property, - RADEON_AUDIO_DISABLE); + rdev->mode_info.audio_property, + (radeon_audio == 1) ? + RADEON_AUDIO_AUTO : + RADEON_AUDIO_DISABLE); } connector->interlace_allowed = true; /* in theory with a DP to VGA converter... */ diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index cdd12dcd988b..9c14a1ba1de4 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -153,7 +153,7 @@ int radeon_benchmarking = 0; int radeon_testing = 0; int radeon_connector_table = 0; int radeon_tv = 1; -int radeon_audio = 1; +int radeon_audio = -1; int radeon_disp_priority = 0; int radeon_hw_i2c = 0; int radeon_pcie_gen2 = -1; @@ -196,7 +196,7 @@ module_param_named(connector_table, radeon_connector_table, int, 0444); MODULE_PARM_DESC(tv, "TV enable (0 = disable)"); module_param_named(tv, radeon_tv, int, 0444); -MODULE_PARM_DESC(audio, "Audio enable (1 = enable)"); +MODULE_PARM_DESC(audio, "Audio enable (-1 = auto, 0 = disable, 1 = enable)"); module_param_named(audio, radeon_audio, int, 0444); MODULE_PARM_DESC(disp_priority, "Display Priority (0 = auto, 1 = normal, 2 = high)"); -- cgit v1.2.3 From 555b1b651acf44bf27ebbb04235d38a8fd2d58dc Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 18 Oct 2013 20:00:09 -0400 Subject: drm/radeon/audio: don't set speaker allocation on DCE4+ It causes hangs on some asics. Disable on DCE6+ as well just to be on the safe side. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/dce6_afmt.c | 3 +++ drivers/gpu/drm/radeon/evergreen_hdmi.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 85a69d2ea3d2..9fcd338c0fcf 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -113,6 +113,9 @@ void dce6_afmt_write_speaker_allocation(struct drm_encoder *encoder) u8 *sadb; int sad_count; + /* XXX: setting this register causes hangs on some asics */ + return; + if (!dig->afmt->pin) return; diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index f815c20640bd..fe1de855775e 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -67,6 +67,9 @@ static void dce4_afmt_write_speaker_allocation(struct drm_encoder *encoder) u8 *sadb; int sad_count; + /* XXX: setting this register causes hangs on some asics */ + return; + list_for_each_entry(connector, &encoder->dev->mode_config.connector_list, head) { if (connector->encoder == encoder) radeon_connector = to_radeon_connector(connector); -- cgit v1.2.3 From dc39fff7229c01550cad1ee8fa0309dfafdcd2e7 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 18 Oct 2013 12:32:07 -0700 Subject: drm/i915: Print RC6 info less often Since we use intel_enable_rc6() now for more than just when we're enabling RC6, we'll see this message many times, and it is just confusing. As an example, calc_residency calls this function whenever poked via sysfs. This leaves the impression in dmesg that we're constantly re-enabling RC6. While at it, move the defines and description from drv.h to intel_pm.c, since these are only ever used in that code. Signed-off-by: Ben Widawsky Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 21 ---------------- drivers/gpu/drm/i915/intel_pm.c | 54 ++++++++++++++++++++++++++++++++--------- 2 files changed, 43 insertions(+), 32 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2ea33eebf01c..dee03325d596 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1784,27 +1784,6 @@ struct drm_i915_file_private { #include "i915_trace.h" -/** - * RC6 is a special power stage which allows the GPU to enter an very - * low-voltage mode when idle, using down to 0V while at this stage. This - * stage is entered automatically when the GPU is idle when RC6 support is - * enabled, and as soon as new workload arises GPU wakes up automatically as well. - * - * There are different RC6 modes available in Intel GPU, which differentiate - * among each other with the latency required to enter and leave RC6 and - * voltage consumed by the GPU in different states. - * - * The combination of the following flags define which states GPU is allowed - * to enter, while RC6 is the normal RC6 state, RC6p is the deep RC6, and - * RC6pp is deepest RC6. Their support by hardware varies according to the - * GPU, BIOS, chipset and platform. RC6 is usually the safest one and the one - * which brings the most power savings; deeper states save more power, but - * require higher latency to switch to and wake up. - */ -#define INTEL_RC6_ENABLE (1<<0) -#define INTEL_RC6p_ENABLE (1<<1) -#define INTEL_RC6pp_ENABLE (1<<2) - extern const struct drm_ioctl_desc i915_ioctls[]; extern int i915_max_ioctl; extern unsigned int i915_fbpercrtc __always_unused; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8064ff927bcc..bff5fa377039 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -32,6 +32,27 @@ #include #include +/** + * RC6 is a special power stage which allows the GPU to enter an very + * low-voltage mode when idle, using down to 0V while at this stage. This + * stage is entered automatically when the GPU is idle when RC6 support is + * enabled, and as soon as new workload arises GPU wakes up automatically as well. + * + * There are different RC6 modes available in Intel GPU, which differentiate + * among each other with the latency required to enter and leave RC6 and + * voltage consumed by the GPU in different states. + * + * The combination of the following flags define which states GPU is allowed + * to enter, while RC6 is the normal RC6 state, RC6p is the deep RC6, and + * RC6pp is deepest RC6. Their support by hardware varies according to the + * GPU, BIOS, chipset and platform. RC6 is usually the safest one and the one + * which brings the most power savings; deeper states save more power, but + * require higher latency to switch to and wake up. + */ +#define INTEL_RC6_ENABLE (1<<0) +#define INTEL_RC6p_ENABLE (1<<1) +#define INTEL_RC6pp_ENABLE (1<<2) + /* FBC, or Frame Buffer Compression, is a technique employed to compress the * framebuffer contents in-memory, aiming at reducing the required bandwidth * during in-memory transfers and, therefore, reduce the power packet. @@ -3685,6 +3706,20 @@ static void valleyview_disable_rps(struct drm_device *dev) } } +static void intel_print_rc6_info(struct drm_device *dev, u32 mode) +{ + if (IS_GEN6(dev)) + DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n"); + + if (IS_HASWELL(dev)) + DRM_DEBUG_DRIVER("Haswell: only RC6 available\n"); + + DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", + (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", + (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", + (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); +} + int intel_enable_rc6(const struct drm_device *dev) { /* No RC6 before Ironlake */ @@ -3699,18 +3734,13 @@ int intel_enable_rc6(const struct drm_device *dev) if (INTEL_INFO(dev)->gen == 5) return 0; - if (IS_HASWELL(dev)) { - DRM_DEBUG_DRIVER("Haswell: only RC6 available\n"); + if (IS_HASWELL(dev)) return INTEL_RC6_ENABLE; - } /* snb/ivb have more than one rc6 state. */ - if (INTEL_INFO(dev)->gen == 6) { - DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n"); + if (INTEL_INFO(dev)->gen == 6) return INTEL_RC6_ENABLE; - } - DRM_DEBUG_DRIVER("RC6 and deep RC6 enabled\n"); return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE); } @@ -3812,10 +3842,7 @@ static void gen6_enable_rps(struct drm_device *dev) rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; } - DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", - (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", - (rc6_mask & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", - (rc6_mask & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); + intel_print_rc6_info(dev, rc6_mask); I915_WRITE(GEN6_RC_CONTROL, rc6_mask | @@ -4051,6 +4078,9 @@ static void valleyview_enable_rps(struct drm_device *dev) VLV_RENDER_RC6_COUNT_EN)); if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE) rc6_mode = GEN7_RC_CTL_TO_MODE; + + intel_print_rc6_info(dev, rc6_mode); + I915_WRITE(GEN6_RC_CONTROL, rc6_mode); val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); @@ -4222,6 +4252,8 @@ static void ironlake_enable_rc6(struct drm_device *dev) I915_WRITE(PWRCTXA, i915_gem_obj_ggtt_offset(dev_priv->ips.pwrctx) | PWRCTX_EN); I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); + + intel_print_rc6_info(dev, INTEL_RC6_ENABLE); } static unsigned long intel_pxfreq(u32 vidfreq) -- cgit v1.2.3 From de45eaf7b9530b6137d3ce370b12b199fae01419 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 18 Oct 2013 18:48:24 -0300 Subject: drm/i915: fix open-coded DIV_ROUND_UP Use the nice Kernel macro, it makes the code much more readable. Signed-off-by: Paulo Zanoni Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/intel_fbdev.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 34df59b660f8..e7b39d731db6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -261,7 +261,7 @@ i915_gem_dumb_create(struct drm_file *file, struct drm_mode_create_dumb *args) { /* have to work out size/pitch and return them */ - args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64); + args->pitch = ALIGN(args->width * DIV_ROUND_UP(args->bpp, 8), 64); args->size = args->pitch * args->height; return i915_gem_create(file, dev, args->size, &args->handle); diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index acc839569c3f..895fcb4fbd94 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -78,8 +78,8 @@ static int intelfb_create(struct drm_fb_helper *helper, mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; - mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) / - 8), 64); + mode_cmd.pitches[0] = ALIGN(mode_cmd.width * + DIV_ROUND_UP(sizes->surface_bpp, 8), 64); mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); -- cgit v1.2.3 From 1cf84bb6ae2d49ce06ffa93c6293edfff70bed55 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 21 Oct 2013 09:10:33 +0100 Subject: drm/i915: Whitespace alignment fix for block header in display error state The current output looks like: Num Pipes: 2 Pipe [0]: SRC: 027f01df Plane [0]: CNTR: d9000000 STRIDE: 00001400 SIZE: 031f04ff POS: 00000000 ADDR: 00020000 Cursor [0]: CNTR: 00000000 POS: 00000000 BASE: 00000000 Pipe [1]: SRC: 04ff031f Plane [1]: CNTR: 01000000 STRIDE: 00000000 SIZE: 018f02cf POS: 00000000 ADDR: 00000000 Cursor [1]: CNTR: 00000000 POS: 00000000 BASE: 00000000 CPU transcoder: A CONF: 00000000 HTOTAL: 031f027f HBLANK: 03170287 HSYNC: 02ef028f VTOTAL: 020c01df VBLANK: 020401e7 VSYNC: 01eb01e9 CPU transcoder: B CONF: 80000000 HTOTAL: 059f04ff HBLANK: 059f04ff HSYNC: 054f052f VTOTAL: 0336031f VBLANK: 0336031f VSYNC: 03280322 which lacks the important visual clue to demarque the transcoder blocks from the last cursor. Signed-off-by: Chris Wilson Cc: Daniel Vetter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8905f83166f2..181f4f8daa79 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11175,7 +11175,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, } for (i = 0; i < error->num_transcoders; i++) { - err_printf(m, " CPU transcoder: %c\n", + err_printf(m, "CPU transcoder: %c\n", transcoder_name(error->transcoder[i].cpu_transcoder)); err_printf(m, " CONF: %08x\n", error->transcoder[i].conf); err_printf(m, " HTOTAL: %08x\n", error->transcoder[i].htotal); -- cgit v1.2.3 From 0b5c5ed072b8e0de8dc4e085dbd855e440c58bf4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 16 Oct 2013 22:55:53 +0200 Subject: drm/i915: Adjust CRC capture for pre-gen5/vlv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Should work down to gen2. The #defines for the interrupt sources are already there in PIPESTAT and are the same on all gmch platforms for gen2 up to vlv. Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 28 +++++++++++++++++++--------- drivers/gpu/drm/i915/i915_reg.h | 30 +++++++++++++++--------------- 2 files changed, 34 insertions(+), 24 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 156a1a4d8e51..98f5ac35e963 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1249,21 +1249,31 @@ static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe) I915_READ(PIPE_CRC_RES_5_IVB(pipe))); } -static void ilk_pipe_crc_update(struct drm_device *dev, enum pipe pipe) +static void i9xx_pipe_crc_update(struct drm_device *dev, enum pipe pipe) { struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t res1, res2; + + if (INTEL_INFO(dev)->gen >= 3) + res1 = I915_READ(PIPE_CRC_RES_RES1_I915(pipe)); + else + res1 = 0; + + if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) + res2 = I915_READ(PIPE_CRC_RES_RES2_G4X(pipe)); + else + res2 = 0; display_pipe_crc_update(dev, pipe, - I915_READ(PIPE_CRC_RES_RED_ILK(pipe)), - I915_READ(PIPE_CRC_RES_GREEN_ILK(pipe)), - I915_READ(PIPE_CRC_RES_BLUE_ILK(pipe)), - I915_READ(PIPE_CRC_RES_RES1_ILK(pipe)), - I915_READ(PIPE_CRC_RES_RES2_ILK(pipe))); + I915_READ(PIPE_CRC_RES_RED(pipe)), + I915_READ(PIPE_CRC_RES_GREEN(pipe)), + I915_READ(PIPE_CRC_RES_BLUE(pipe)), + res1, res2); } #else static inline void hsw_pipe_crc_update(struct drm_device *dev, int pipe) {} static inline void ivb_pipe_crc_update(struct drm_device *dev, int pipe) {} -static inline void ilk_pipe_crc_update(struct drm_device *dev, int pipe) {} +static inline void i9xx_pipe_crc_update(struct drm_device *dev, int pipe) {} #endif /* The RPS events need forcewake, so we add them to a work queue and mask their @@ -1543,10 +1553,10 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n"); if (de_iir & DE_PIPEA_CRC_DONE) - ilk_pipe_crc_update(dev, PIPE_A); + i9xx_pipe_crc_update(dev, PIPE_A); if (de_iir & DE_PIPEB_CRC_DONE) - ilk_pipe_crc_update(dev, PIPE_B); + i9xx_pipe_crc_update(dev, PIPE_B); if (de_iir & DE_PLANEA_FLIP_DONE) { intel_prepare_page_flip(dev, 0); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0e7488b64965..a45fbae59e68 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1858,11 +1858,11 @@ #define _PIPE_CRC_RES_4_A_IVB 0x60070 #define _PIPE_CRC_RES_5_A_IVB 0x60074 -#define _PIPE_CRC_RES_RED_A_ILK 0x60060 -#define _PIPE_CRC_RES_GREEN_A_ILK 0x60064 -#define _PIPE_CRC_RES_BLUE_A_ILK 0x60068 -#define _PIPE_CRC_RES_RES1_A_ILK 0x6006c -#define _PIPE_CRC_RES_RES2_A_ILK 0x60080 +#define _PIPE_CRC_RES_RED_A (dev_priv->info->display_mmio_offset + 0x60060) +#define _PIPE_CRC_RES_GREEN_A (dev_priv->info->display_mmio_offset + 0x60064) +#define _PIPE_CRC_RES_BLUE_A (dev_priv->info->display_mmio_offset + 0x60068) +#define _PIPE_CRC_RES_RES1_A_I915 (dev_priv->info->display_mmio_offset + 0x6006c) +#define _PIPE_CRC_RES_RES2_A_G4X (dev_priv->info->display_mmio_offset + 0x60080) /* Pipe B CRC regs */ #define _PIPE_CRC_CTL_B 0x61050 @@ -1884,16 +1884,16 @@ #define PIPE_CRC_RES_5_IVB(pipe) \ _PIPE(pipe, _PIPE_CRC_RES_5_A_IVB, _PIPE_CRC_RES_5_B_IVB) -#define PIPE_CRC_RES_RED_ILK(pipe) \ - _PIPE_INC(pipe, _PIPE_CRC_RES_RED_A_ILK, 0x01000) -#define PIPE_CRC_RES_GREEN_ILK(pipe) \ - _PIPE_INC(pipe, _PIPE_CRC_RES_GREEN_A_ILK, 0x01000) -#define PIPE_CRC_RES_BLUE_ILK(pipe) \ - _PIPE_INC(pipe, _PIPE_CRC_RES_BLUE_A_ILK, 0x01000) -#define PIPE_CRC_RES_RES1_ILK(pipe) \ - _PIPE_INC(pipe, _PIPE_CRC_RES_RES1_A_ILK, 0x01000) -#define PIPE_CRC_RES_RES2_ILK(pipe) \ - _PIPE_INC(pipe, _PIPE_CRC_RES_RES2_A_ILK, 0x01000) +#define PIPE_CRC_RES_RED(pipe) \ + _PIPE_INC(pipe, _PIPE_CRC_RES_RED_A, 0x01000) +#define PIPE_CRC_RES_GREEN(pipe) \ + _PIPE_INC(pipe, _PIPE_CRC_RES_GREEN_A, 0x01000) +#define PIPE_CRC_RES_BLUE(pipe) \ + _PIPE_INC(pipe, _PIPE_CRC_RES_BLUE_A, 0x01000) +#define PIPE_CRC_RES_RES1_I915(pipe) \ + _PIPE_INC(pipe, _PIPE_CRC_RES_RES1_A_I915, 0x01000) +#define PIPE_CRC_RES_RES2_G4X(pipe) \ + _PIPE_INC(pipe, _PIPE_CRC_RES_RES2_A_G4X, 0x01000) /* Pipe A timing regs */ #define _HTOTAL_A (dev_priv->info->display_mmio_offset + 0x60000) -- cgit v1.2.3 From b4437a4139f455d1d6557d81789dcbbe849b0496 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 16 Oct 2013 22:55:54 +0200 Subject: drm/i915: CRC source selection #defines for gmch/vlv chips MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A bit a mess, since with DP/TV outputs we can't use the pipe CRC. Also, no plane CRCs, so we need to update the basic testcases. Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a45fbae59e68..08061fc83e5c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1843,15 +1843,37 @@ /* Pipe A CRC regs */ #define _PIPE_CRC_CTL_A (dev_priv->info->display_mmio_offset + 0x60050) #define PIPE_CRC_ENABLE (1 << 31) +/* ivb+ source selection */ #define PIPE_CRC_SOURCE_PRIMARY_IVB (0 << 29) #define PIPE_CRC_SOURCE_SPRITE_IVB (1 << 29) #define PIPE_CRC_SOURCE_PF_IVB (2 << 29) +/* ilk+ source selection */ #define PIPE_CRC_SOURCE_PRIMARY_ILK (0 << 28) #define PIPE_CRC_SOURCE_SPRITE_ILK (1 << 28) #define PIPE_CRC_SOURCE_PIPE_ILK (2 << 28) /* embedded DP port on the north display block, reserved on ivb */ #define PIPE_CRC_SOURCE_PORT_A_ILK (4 << 28) #define PIPE_CRC_SOURCE_FDI_ILK (5 << 28) /* reserved on ivb */ +/* vlv source selection */ +#define PIPE_CRC_SOURCE_PIPE_VLV (0 << 27) +#define PIPE_CRC_SOURCE_HDMIB_VLV (1 << 27) +#define PIPE_CRC_SOURCE_HDMIC_VLV (2 << 27) +/* with DP port the pipe source is invalid */ +#define PIPE_CRC_SOURCE_DP_D_VLV (3 << 27) +#define PIPE_CRC_SOURCE_DP_B_VLV (6 << 27) +#define PIPE_CRC_SOURCE_DP_C_VLV (7 << 27) +/* gen3+ source selection */ +#define PIPE_CRC_SOURCE_PIPE_I9XX (0 << 28) +#define PIPE_CRC_SOURCE_SDVOB_I9XX (1 << 28) +#define PIPE_CRC_SOURCE_SDVOC_I9XX (2 << 28) +/* with DP/TV port the pipe source is invalid */ +#define PIPE_CRC_SOURCE_DP_D_G4X (3 << 28) +#define PIPE_CRC_SOURCE_TV_PRE (4 << 28) +#define PIPE_CRC_SOURCE_TV_POST (5 << 28) +#define PIPE_CRC_SOURCE_DP_B_G4X (6 << 28) +#define PIPE_CRC_SOURCE_DP_C_G4X (7 << 28) +/* gen2 doesn't have source selection bits */ + #define _PIPE_CRC_RES_1_A_IVB 0x60064 #define _PIPE_CRC_RES_2_A_IVB 0x60068 #define _PIPE_CRC_RES_3_A_IVB 0x6006c -- cgit v1.2.3 From 4356d5864c29b9f822a496ab62f24a8971e1fbce Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 16 Oct 2013 22:55:55 +0200 Subject: drm/i915: Wire up CRC interrupts for pre-gen5/vlv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And throw in a tiny for_each_pipe refactoring for gen2. Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 98f5ac35e963..b31e7ca614bf 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1350,6 +1350,9 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) intel_prepare_page_flip(dev, pipe); intel_finish_page_flip(dev, pipe); } + + if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) + i9xx_pipe_crc_update(dev, pipe); } /* Consume port. Then clear IIR or we'll miss events */ @@ -2800,13 +2803,14 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) if (iir & I915_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[RCS]); - if (pipe_stats[0] & PIPE_VBLANK_INTERRUPT_STATUS && - i8xx_handle_vblank(dev, 0, iir)) - flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(0); + for_each_pipe(pipe) { + if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS && + i8xx_handle_vblank(dev, pipe, iir)) + flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe); - if (pipe_stats[1] & PIPE_VBLANK_INTERRUPT_STATUS && - i8xx_handle_vblank(dev, 1, iir)) - flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(1); + if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) + i9xx_pipe_crc_update(dev, pipe); + } iir = new_iir; } @@ -2999,6 +3003,9 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) blc_event = true; + + if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) + i9xx_pipe_crc_update(dev, pipe); } if (blc_event || (iir & I915_ASLE_INTERRUPT)) @@ -3243,6 +3250,9 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) blc_event = true; + + if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) + i9xx_pipe_crc_update(dev, pipe); } -- cgit v1.2.3 From 379ef82d460fae81d167c0fba45b0f3513fc6cb7 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 16 Oct 2013 22:55:56 +0200 Subject: drm/i915: Enable CRC interrupts on pre-gen5/vlv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b31e7ca614bf..5c3baa0ec049 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2574,7 +2574,8 @@ static int valleyview_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 enable_mask; - u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV; + u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV | + PIPE_CRC_DONE_ENABLE; unsigned long irqflags; enable_mask = I915_DISPLAY_PORT_INTERRUPT; @@ -2697,6 +2698,7 @@ static void i8xx_irq_preinstall(struct drm_device * dev) static int i8xx_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; + unsigned long irqflags; I915_WRITE16(EMR, ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH)); @@ -2717,6 +2719,13 @@ static int i8xx_irq_postinstall(struct drm_device *dev) I915_USER_INTERRUPT); POSTING_READ16(IER); + /* Interrupt setup is already guaranteed to be single-threaded, this is + * just to make the assert_spin_locked check happy. */ + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); + i915_enable_pipestat(dev_priv, 0, PIPE_CRC_DONE_ENABLE); + i915_enable_pipestat(dev_priv, 1, PIPE_CRC_DONE_ENABLE); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); + return 0; } @@ -2857,6 +2866,7 @@ static int i915_irq_postinstall(struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 enable_mask; + unsigned long irqflags; I915_WRITE(EMR, ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH)); @@ -2892,6 +2902,13 @@ static int i915_irq_postinstall(struct drm_device *dev) i915_enable_asle_pipestat(dev); + /* Interrupt setup is already guaranteed to be single-threaded, this is + * just to make the assert_spin_locked check happy. */ + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); + i915_enable_pipestat(dev_priv, 0, PIPE_CRC_DONE_ENABLE); + i915_enable_pipestat(dev_priv, 1, PIPE_CRC_DONE_ENABLE); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); + return 0; } @@ -3105,6 +3122,8 @@ static int i965_irq_postinstall(struct drm_device *dev) * just to make the assert_spin_locked check happy. */ spin_lock_irqsave(&dev_priv->irq_lock, irqflags); i915_enable_pipestat(dev_priv, 0, PIPE_GMBUS_EVENT_ENABLE); + i915_enable_pipestat(dev_priv, 0, PIPE_CRC_DONE_ENABLE); + i915_enable_pipestat(dev_priv, 1, PIPE_CRC_DONE_ENABLE); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); /* -- cgit v1.2.3 From b073aeaa28b43b00b5c90096c76e872dca4d4ee4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 16 Oct 2013 22:55:57 +0200 Subject: drm/i915: Fix PIPE_CRC_CTL for vlv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PIPE_B #define was missing the display mmio offset. Use the _PIPE_INC macro instead, it's simpler. Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 08061fc83e5c..d0e61f0c34ce 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1887,14 +1887,13 @@ #define _PIPE_CRC_RES_RES2_A_G4X (dev_priv->info->display_mmio_offset + 0x60080) /* Pipe B CRC regs */ -#define _PIPE_CRC_CTL_B 0x61050 #define _PIPE_CRC_RES_1_B_IVB 0x61064 #define _PIPE_CRC_RES_2_B_IVB 0x61068 #define _PIPE_CRC_RES_3_B_IVB 0x6106c #define _PIPE_CRC_RES_4_B_IVB 0x61070 #define _PIPE_CRC_RES_5_B_IVB 0x61074 -#define PIPE_CRC_CTL(pipe) _PIPE(pipe, _PIPE_CRC_CTL_A, _PIPE_CRC_CTL_B) +#define PIPE_CRC_CTL(pipe) _PIPE_INC(pipe, _PIPE_CRC_CTL_A, 0x01000) #define PIPE_CRC_RES_1_IVB(pipe) \ _PIPE(pipe, _PIPE_CRC_RES_1_A_IVB, _PIPE_CRC_RES_1_B_IVB) #define PIPE_CRC_RES_2_IVB(pipe) \ -- cgit v1.2.3 From 3d099a05b121727bfa797391ea1da15eb33eac16 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 16 Oct 2013 22:55:58 +0200 Subject: drm/i915: Add new CRC sources MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On pre-gen5 and vlv we can't use the pipe source when TV-out or a DP port is connected to the pipe. Hence we need to expose new CRC sources. Also simplify the existing pipe source platform code a bit by rejecting all unhandled sources by default. Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 16 ++++++++++------ drivers/gpu/drm/i915/i915_drv.h | 5 +++++ 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 061182a0ce1b..d7ee350fc6a3 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1915,6 +1915,10 @@ static const char * const pipe_crc_sources[] = { "plane2", "pf", "pipe", + "TV", + "DP-B", + "DP-C", + "DP-D", }; static const char *pipe_crc_source_name(enum intel_pipe_crc_source source) @@ -1953,14 +1957,14 @@ static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source source, case INTEL_PIPE_CRC_SOURCE_PLANE2: *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_ILK; break; - case INTEL_PIPE_CRC_SOURCE_PF: - return -EINVAL; case INTEL_PIPE_CRC_SOURCE_PIPE: *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_ILK; break; - default: + case INTEL_PIPE_CRC_SOURCE_NONE: *val = 0; break; + default: + return -EINVAL; } return 0; @@ -1979,11 +1983,11 @@ static int ivb_pipe_crc_ctl_reg(enum intel_pipe_crc_source source, case INTEL_PIPE_CRC_SOURCE_PF: *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB; break; - case INTEL_PIPE_CRC_SOURCE_PIPE: - return -EINVAL; - default: + case INTEL_PIPE_CRC_SOURCE_NONE: *val = 0; break; + default: + return -EINVAL; } return 0; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index dee03325d596..07e4949c5f3c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1224,6 +1224,11 @@ enum intel_pipe_crc_source { INTEL_PIPE_CRC_SOURCE_PLANE2, INTEL_PIPE_CRC_SOURCE_PF, INTEL_PIPE_CRC_SOURCE_PIPE, + /* TV/DP on pre-gen5/vlv can't use the pipe source. */ + INTEL_PIPE_CRC_SOURCE_TV, + INTEL_PIPE_CRC_SOURCE_DP_B, + INTEL_PIPE_CRC_SOURCE_DP_C, + INTEL_PIPE_CRC_SOURCE_DP_D, INTEL_PIPE_CRC_SOURCE_MAX, }; -- cgit v1.2.3 From 4b79ebf7b2967e6e905e6e12e113a6ce9a86d045 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 16 Oct 2013 22:55:59 +0200 Subject: drm/i915: Wire up CRC support for gen3/4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 44 +++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d7ee350fc6a3..e3f09801b64d 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1947,6 +1947,44 @@ static int display_crc_ctl_open(struct inode *inode, struct file *file) return single_open(file, display_crc_ctl_show, dev); } +static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev, + enum intel_pipe_crc_source source, + uint32_t *val) +{ + switch (source) { + case INTEL_PIPE_CRC_SOURCE_PIPE: + *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_I9XX; + break; + case INTEL_PIPE_CRC_SOURCE_TV: + if (!SUPPORTS_TV(dev)) + return -EINVAL; + *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_TV_PRE; + break; + case INTEL_PIPE_CRC_SOURCE_DP_B: + if (!IS_G4X(dev)) + return -EINVAL; + *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_B_G4X; + break; + case INTEL_PIPE_CRC_SOURCE_DP_C: + if (!IS_G4X(dev)) + return -EINVAL; + *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_C_G4X; + break; + case INTEL_PIPE_CRC_SOURCE_DP_D: + if (!IS_G4X(dev)) + return -EINVAL; + *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_D_G4X; + break; + case INTEL_PIPE_CRC_SOURCE_NONE: + *val = 0; + break; + default: + return -EINVAL; + } + + return 0; +} + static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source source, uint32_t *val) { @@ -2001,7 +2039,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, u32 val; int ret; - if (!(INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev))) + if (!(INTEL_INFO(dev)->gen >= 3 && !IS_VALLEYVIEW(dev))) return -ENODEV; if (pipe_crc->source == source) @@ -2011,7 +2049,9 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, if (pipe_crc->source && source) return -EINVAL; - if (IS_GEN5(dev) || IS_GEN6(dev)) + if (INTEL_INFO(dev)->gen < 5) + ret = i9xx_pipe_crc_ctl_reg(dev, source, &val); + else if (IS_GEN5(dev) || IS_GEN6(dev)) ret = ilk_pipe_crc_ctl_reg(source, &val); else ret = ivb_pipe_crc_ctl_reg(source, &val); -- cgit v1.2.3 From 52f843f6ccbd73497c8e9acd9299ebf216d738be Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 21 Oct 2013 17:26:38 +0200 Subject: drm/i915: Wire up gen2 CRC support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Really simple, and we don't even have working frame numbers. v2: Actually enable it ... v3: Review from Ville: - Unconditionally enable the border in the CRC checksum for consistency with gen3+. - Handle the "none" source to be able to disable the CRC machinery again. Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 23 +++++++++++++++++++++-- drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e3f09801b64d..9a4f168c9e39 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1947,6 +1947,23 @@ static int display_crc_ctl_open(struct inode *inode, struct file *file) return single_open(file, display_crc_ctl_show, dev); } +static int i8xx_pipe_crc_ctl_reg(enum intel_pipe_crc_source source, + uint32_t *val) +{ + switch (source) { + case INTEL_PIPE_CRC_SOURCE_PIPE: + *val = PIPE_CRC_ENABLE | PIPE_CRC_INCLUDE_BORDER_I8XX; + break; + case INTEL_PIPE_CRC_SOURCE_NONE: + *val = 0; + break; + default: + return -EINVAL; + } + + return 0; +} + static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev, enum intel_pipe_crc_source source, uint32_t *val) @@ -2039,7 +2056,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, u32 val; int ret; - if (!(INTEL_INFO(dev)->gen >= 3 && !IS_VALLEYVIEW(dev))) + if (IS_VALLEYVIEW(dev)) return -ENODEV; if (pipe_crc->source == source) @@ -2049,7 +2066,9 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, if (pipe_crc->source && source) return -EINVAL; - if (INTEL_INFO(dev)->gen < 5) + if (IS_GEN2(dev)) + ret = i8xx_pipe_crc_ctl_reg(source, &val); + else if (INTEL_INFO(dev)->gen < 5) ret = i9xx_pipe_crc_ctl_reg(dev, source, &val); else if (IS_GEN5(dev) || IS_GEN6(dev)) ret = ilk_pipe_crc_ctl_reg(source, &val); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d0e61f0c34ce..d1fb06a6a3f0 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1873,6 +1873,7 @@ #define PIPE_CRC_SOURCE_DP_B_G4X (6 << 28) #define PIPE_CRC_SOURCE_DP_C_G4X (7 << 28) /* gen2 doesn't have source selection bits */ +#define PIPE_CRC_INCLUDE_BORDER_I8XX (1 << 30) #define _PIPE_CRC_RES_1_A_IVB 0x60064 #define _PIPE_CRC_RES_2_A_IVB 0x60068 -- cgit v1.2.3 From 7ac0129bbfe28b66ead21369398edc7f7482d46a Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 18 Oct 2013 16:37:06 +0200 Subject: drm/i915: Wire up CRC for vlv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v2: Actually enable it. Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 9a4f168c9e39..25fc3841a2b1 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1964,6 +1964,29 @@ static int i8xx_pipe_crc_ctl_reg(enum intel_pipe_crc_source source, return 0; } +static int vlv_pipe_crc_ctl_reg(enum intel_pipe_crc_source source, + uint32_t *val) +{ + switch (source) { + case INTEL_PIPE_CRC_SOURCE_PIPE: + *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_VLV; + break; + case INTEL_PIPE_CRC_SOURCE_DP_B: + *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_B_VLV; + break; + case INTEL_PIPE_CRC_SOURCE_DP_C: + *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_C_VLV; + break; + case INTEL_PIPE_CRC_SOURCE_NONE: + *val = 0; + break; + default: + return -EINVAL; + } + + return 0; +} + static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev, enum intel_pipe_crc_source source, uint32_t *val) @@ -2056,9 +2079,6 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, u32 val; int ret; - if (IS_VALLEYVIEW(dev)) - return -ENODEV; - if (pipe_crc->source == source) return 0; @@ -2070,6 +2090,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, ret = i8xx_pipe_crc_ctl_reg(source, &val); else if (INTEL_INFO(dev)->gen < 5) ret = i9xx_pipe_crc_ctl_reg(dev, source, &val); + else if (IS_VALLEYVIEW(dev)) + ret = vlv_pipe_crc_ctl_reg(source, &val); else if (IS_GEN5(dev) || IS_GEN6(dev)) ret = ilk_pipe_crc_ctl_reg(source, &val); else -- cgit v1.2.3 From 277de95e4e5ec39edab779efe388894d5cc06582 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 18 Oct 2013 16:37:07 +0200 Subject: drm/i915: bikeshed the pipe CRC irq functions a bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Give them an _irq_handler postfix, like all the other irq stuff. - Shuffle the DEBUG_FS=n dummy functions around a bit. This is prep work to extract all the crc debug stuff into intel_display_testing.c Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 71 +++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 34 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 5c3baa0ec049..8f7baad72316 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1190,10 +1190,10 @@ static void dp_aux_irq_handler(struct drm_device *dev) } #if defined(CONFIG_DEBUG_FS) -static void display_pipe_crc_update(struct drm_device *dev, enum pipe pipe, - uint32_t crc0, uint32_t crc1, - uint32_t crc2, uint32_t crc3, - uint32_t crc4) +static void display_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe, + uint32_t crc0, uint32_t crc1, + uint32_t crc2, uint32_t crc3, + uint32_t crc4) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; @@ -1227,29 +1227,37 @@ static void display_pipe_crc_update(struct drm_device *dev, enum pipe pipe, wake_up_interruptible(&pipe_crc->wq); } +#else +static inline void +display_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe, + uint32_t crc0, uint32_t crc1, + uint32_t crc2, uint32_t crc3, + uint32_t crc4) {} +#endif + -static void hsw_pipe_crc_update(struct drm_device *dev, enum pipe pipe) +static void hsw_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe) { struct drm_i915_private *dev_priv = dev->dev_private; - display_pipe_crc_update(dev, pipe, - I915_READ(PIPE_CRC_RES_1_IVB(pipe)), - 0, 0, 0, 0); + display_pipe_crc_irq_handler(dev, pipe, + I915_READ(PIPE_CRC_RES_1_IVB(pipe)), + 0, 0, 0, 0); } -static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe) +static void ivb_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe) { struct drm_i915_private *dev_priv = dev->dev_private; - display_pipe_crc_update(dev, pipe, - I915_READ(PIPE_CRC_RES_1_IVB(pipe)), - I915_READ(PIPE_CRC_RES_2_IVB(pipe)), - I915_READ(PIPE_CRC_RES_3_IVB(pipe)), - I915_READ(PIPE_CRC_RES_4_IVB(pipe)), - I915_READ(PIPE_CRC_RES_5_IVB(pipe))); + display_pipe_crc_irq_handler(dev, pipe, + I915_READ(PIPE_CRC_RES_1_IVB(pipe)), + I915_READ(PIPE_CRC_RES_2_IVB(pipe)), + I915_READ(PIPE_CRC_RES_3_IVB(pipe)), + I915_READ(PIPE_CRC_RES_4_IVB(pipe)), + I915_READ(PIPE_CRC_RES_5_IVB(pipe))); } -static void i9xx_pipe_crc_update(struct drm_device *dev, enum pipe pipe) +static void i9xx_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe) { struct drm_i915_private *dev_priv = dev->dev_private; uint32_t res1, res2; @@ -1264,17 +1272,12 @@ static void i9xx_pipe_crc_update(struct drm_device *dev, enum pipe pipe) else res2 = 0; - display_pipe_crc_update(dev, pipe, - I915_READ(PIPE_CRC_RES_RED(pipe)), - I915_READ(PIPE_CRC_RES_GREEN(pipe)), - I915_READ(PIPE_CRC_RES_BLUE(pipe)), - res1, res2); + display_pipe_crc_irq_handler(dev, pipe, + I915_READ(PIPE_CRC_RES_RED(pipe)), + I915_READ(PIPE_CRC_RES_GREEN(pipe)), + I915_READ(PIPE_CRC_RES_BLUE(pipe)), + res1, res2); } -#else -static inline void hsw_pipe_crc_update(struct drm_device *dev, int pipe) {} -static inline void ivb_pipe_crc_update(struct drm_device *dev, int pipe) {} -static inline void i9xx_pipe_crc_update(struct drm_device *dev, int pipe) {} -#endif /* The RPS events need forcewake, so we add them to a work queue and mask their * IMR bits until the work is done. Other interrupts can be processed without @@ -1352,7 +1355,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) } if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) - i9xx_pipe_crc_update(dev, pipe); + i9xx_pipe_crc_irq_handler(dev, pipe); } /* Consume port. Then clear IIR or we'll miss events */ @@ -1456,9 +1459,9 @@ static void ivb_err_int_handler(struct drm_device *dev) if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) { if (IS_IVYBRIDGE(dev)) - ivb_pipe_crc_update(dev, pipe); + ivb_pipe_crc_irq_handler(dev, pipe); else - hsw_pipe_crc_update(dev, pipe); + hsw_pipe_crc_irq_handler(dev, pipe); } } @@ -1556,10 +1559,10 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n"); if (de_iir & DE_PIPEA_CRC_DONE) - i9xx_pipe_crc_update(dev, PIPE_A); + i9xx_pipe_crc_irq_handler(dev, PIPE_A); if (de_iir & DE_PIPEB_CRC_DONE) - i9xx_pipe_crc_update(dev, PIPE_B); + i9xx_pipe_crc_irq_handler(dev, PIPE_B); if (de_iir & DE_PLANEA_FLIP_DONE) { intel_prepare_page_flip(dev, 0); @@ -2818,7 +2821,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe); if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) - i9xx_pipe_crc_update(dev, pipe); + i9xx_pipe_crc_irq_handler(dev, pipe); } iir = new_iir; @@ -3022,7 +3025,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) blc_event = true; if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) - i9xx_pipe_crc_update(dev, pipe); + i9xx_pipe_crc_irq_handler(dev, pipe); } if (blc_event || (iir & I915_ASLE_INTERRUPT)) @@ -3271,7 +3274,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) blc_event = true; if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) - i9xx_pipe_crc_update(dev, pipe); + i9xx_pipe_crc_irq_handler(dev, pipe); } -- cgit v1.2.3 From f52e353e193556044ae30622d50bd76802e9d859 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Oct 2013 17:25:48 +0300 Subject: drm/i915: make the intel_display_power_domain enum compact Upcoming patches will add tracking for a set of power domains via a bitmask; to make things simple there remove the current gap in the enum values. Signed-off-by: Imre Deak Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 07e4949c5f3c..87857d781ddf 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -98,14 +98,16 @@ enum intel_display_power_domain { POWER_DOMAIN_TRANSCODER_A, POWER_DOMAIN_TRANSCODER_B, POWER_DOMAIN_TRANSCODER_C, - POWER_DOMAIN_TRANSCODER_EDP = POWER_DOMAIN_TRANSCODER_A + 0xF, + POWER_DOMAIN_TRANSCODER_EDP, POWER_DOMAIN_VGA, }; #define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A) #define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \ ((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER) -#define POWER_DOMAIN_TRANSCODER(tran) ((tran) + POWER_DOMAIN_TRANSCODER_A) +#define POWER_DOMAIN_TRANSCODER(tran) \ + ((tran) == TRANSCODER_EDP ? POWER_DOMAIN_TRANSCODER_EDP : \ + (tran) + POWER_DOMAIN_TRANSCODER_A) enum hpd_pin { HPD_NONE = 0, -- cgit v1.2.3 From bddc76452d16cd1101ba29c0cff653cb8313b010 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Oct 2013 17:25:49 +0300 Subject: drm/i915: factor out is_always_on_domain It is just cleaner this way and makes it easier to add support for other HW generations with always-on power wells powering a different set of domains. Signed-off-by: Imre Deak Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 8 ++++ drivers/gpu/drm/i915/intel_pm.c | 84 +++++++++++++++-------------------------- 2 files changed, 38 insertions(+), 54 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 87857d781ddf..f3a930d3ade4 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -100,8 +100,12 @@ enum intel_display_power_domain { POWER_DOMAIN_TRANSCODER_C, POWER_DOMAIN_TRANSCODER_EDP, POWER_DOMAIN_VGA, + + POWER_DOMAIN_NUM, }; +#define POWER_DOMAIN_MASK (BIT(POWER_DOMAIN_NUM) - 1) + #define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A) #define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \ ((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER) @@ -109,6 +113,10 @@ enum intel_display_power_domain { ((tran) == TRANSCODER_EDP ? POWER_DOMAIN_TRANSCODER_EDP : \ (tran) + POWER_DOMAIN_TRANSCODER_A) +#define HSW_ALWAYS_ON_POWER_DOMAINS ( \ + BIT(POWER_DOMAIN_PIPE_A) | \ + BIT(POWER_DOMAIN_TRANSCODER_EDP)) + enum hpd_pin { HPD_NONE = 0, HPD_PORT_A = HPD_NONE, /* PORT_A is internal */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index bff5fa377039..97abb33e8c92 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5517,6 +5517,23 @@ void intel_suspend_hw(struct drm_device *dev) lpt_suspend_hw(dev); } +static bool is_always_on_power_domain(struct drm_device *dev, + enum intel_display_power_domain domain) +{ + unsigned long always_on_domains; + + BUG_ON(BIT(domain) & ~POWER_DOMAIN_MASK); + + if (IS_HASWELL(dev)) { + always_on_domains = HSW_ALWAYS_ON_POWER_DOMAINS; + } else { + WARN_ON(1); + return true; + } + + return BIT(domain) & always_on_domains; +} + /** * We should only use the power well if we explicitly asked the hardware to * enable it, so check if it's enabled and also check if we've requested it to @@ -5530,24 +5547,11 @@ bool intel_display_power_enabled(struct drm_device *dev, if (!HAS_POWER_WELL(dev)) return true; - switch (domain) { - case POWER_DOMAIN_PIPE_A: - case POWER_DOMAIN_TRANSCODER_EDP: + if (is_always_on_power_domain(dev, domain)) return true; - case POWER_DOMAIN_VGA: - case POWER_DOMAIN_PIPE_B: - case POWER_DOMAIN_PIPE_C: - case POWER_DOMAIN_PIPE_A_PANEL_FITTER: - case POWER_DOMAIN_PIPE_B_PANEL_FITTER: - case POWER_DOMAIN_PIPE_C_PANEL_FITTER: - case POWER_DOMAIN_TRANSCODER_A: - case POWER_DOMAIN_TRANSCODER_B: - case POWER_DOMAIN_TRANSCODER_C: - return I915_READ(HSW_PWR_WELL_DRIVER) == + + return I915_READ(HSW_PWR_WELL_DRIVER) == (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED); - default: - BUG(); - } } static void __intel_set_power_well(struct drm_device *dev, bool enable) @@ -5619,26 +5623,12 @@ void intel_display_power_get(struct drm_device *dev, if (!HAS_POWER_WELL(dev)) return; - switch (domain) { - case POWER_DOMAIN_PIPE_A: - case POWER_DOMAIN_TRANSCODER_EDP: + if (is_always_on_power_domain(dev, domain)) return; - case POWER_DOMAIN_VGA: - case POWER_DOMAIN_PIPE_B: - case POWER_DOMAIN_PIPE_C: - case POWER_DOMAIN_PIPE_A_PANEL_FITTER: - case POWER_DOMAIN_PIPE_B_PANEL_FITTER: - case POWER_DOMAIN_PIPE_C_PANEL_FITTER: - case POWER_DOMAIN_TRANSCODER_A: - case POWER_DOMAIN_TRANSCODER_B: - case POWER_DOMAIN_TRANSCODER_C: - spin_lock_irq(&power_well->lock); - __intel_power_well_get(power_well); - spin_unlock_irq(&power_well->lock); - return; - default: - BUG(); - } + + spin_lock_irq(&power_well->lock); + __intel_power_well_get(power_well); + spin_unlock_irq(&power_well->lock); } void intel_display_power_put(struct drm_device *dev, @@ -5650,26 +5640,12 @@ void intel_display_power_put(struct drm_device *dev, if (!HAS_POWER_WELL(dev)) return; - switch (domain) { - case POWER_DOMAIN_PIPE_A: - case POWER_DOMAIN_TRANSCODER_EDP: + if (is_always_on_power_domain(dev, domain)) return; - case POWER_DOMAIN_VGA: - case POWER_DOMAIN_PIPE_B: - case POWER_DOMAIN_PIPE_C: - case POWER_DOMAIN_PIPE_A_PANEL_FITTER: - case POWER_DOMAIN_PIPE_B_PANEL_FITTER: - case POWER_DOMAIN_PIPE_C_PANEL_FITTER: - case POWER_DOMAIN_TRANSCODER_A: - case POWER_DOMAIN_TRANSCODER_B: - case POWER_DOMAIN_TRANSCODER_C: - spin_lock_irq(&power_well->lock); - __intel_power_well_put(power_well); - spin_unlock_irq(&power_well->lock); - return; - default: - BUG(); - } + + spin_lock_irq(&power_well->lock); + __intel_power_well_put(power_well); + spin_unlock_irq(&power_well->lock); } static struct i915_power_well *hsw_pwr; -- cgit v1.2.3 From 959cbc1b8a2534bb930d237ee164893a4936a4d6 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Oct 2013 17:25:50 +0300 Subject: drm/i915: change power_well->lock to be mutex There is no hard need for this to be a spin lock, as we don't take these locks in irq context from anywhere. An upcoming patch will add calls to punit read/write functions from within regions protected by this lock and those functions need a mutex in turn. As a solution for that convert the spin lock to be a mutex. Signed-off-by: Imre Deak Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_pm.c | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f3a930d3ade4..faface98ba37 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -909,7 +909,7 @@ struct intel_ilk_power_mgmt { /* Power well structure for haswell */ struct i915_power_well { struct drm_device *device; - spinlock_t lock; + struct mutex lock; /* power well enable/disable usage count */ int count; int i915_request; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 97abb33e8c92..f3136659877a 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5626,9 +5626,9 @@ void intel_display_power_get(struct drm_device *dev, if (is_always_on_power_domain(dev, domain)) return; - spin_lock_irq(&power_well->lock); + mutex_lock(&power_well->lock); __intel_power_well_get(power_well); - spin_unlock_irq(&power_well->lock); + mutex_unlock(&power_well->lock); } void intel_display_power_put(struct drm_device *dev, @@ -5643,9 +5643,9 @@ void intel_display_power_put(struct drm_device *dev, if (is_always_on_power_domain(dev, domain)) return; - spin_lock_irq(&power_well->lock); + mutex_lock(&power_well->lock); __intel_power_well_put(power_well); - spin_unlock_irq(&power_well->lock); + mutex_unlock(&power_well->lock); } static struct i915_power_well *hsw_pwr; @@ -5656,9 +5656,9 @@ void i915_request_power_well(void) if (WARN_ON(!hsw_pwr)) return; - spin_lock_irq(&hsw_pwr->lock); + mutex_lock(&hsw_pwr->lock); __intel_power_well_get(hsw_pwr); - spin_unlock_irq(&hsw_pwr->lock); + mutex_unlock(&hsw_pwr->lock); } EXPORT_SYMBOL_GPL(i915_request_power_well); @@ -5668,9 +5668,9 @@ void i915_release_power_well(void) if (WARN_ON(!hsw_pwr)) return; - spin_lock_irq(&hsw_pwr->lock); + mutex_lock(&hsw_pwr->lock); __intel_power_well_put(hsw_pwr); - spin_unlock_irq(&hsw_pwr->lock); + mutex_unlock(&hsw_pwr->lock); } EXPORT_SYMBOL_GPL(i915_release_power_well); @@ -5681,7 +5681,7 @@ int i915_init_power_well(struct drm_device *dev) hsw_pwr = &dev_priv->power_well; hsw_pwr->device = dev; - spin_lock_init(&hsw_pwr->lock); + mutex_init(&hsw_pwr->lock); hsw_pwr->count = 0; return 0; @@ -5703,7 +5703,7 @@ void intel_set_power_well(struct drm_device *dev, bool enable) if (!i915_disable_power_well && !enable) return; - spin_lock_irq(&power_well->lock); + mutex_lock(&power_well->lock); /* * This function will only ever contribute one @@ -5722,7 +5722,7 @@ void intel_set_power_well(struct drm_device *dev, bool enable) __intel_power_well_put(power_well); out: - spin_unlock_irq(&power_well->lock); + mutex_unlock(&power_well->lock); } static void intel_resume_power_well(struct drm_device *dev) @@ -5733,9 +5733,9 @@ static void intel_resume_power_well(struct drm_device *dev) if (!HAS_POWER_WELL(dev)) return; - spin_lock_irq(&power_well->lock); + mutex_lock(&power_well->lock); __intel_set_power_well(dev, power_well->count > 0); - spin_unlock_irq(&power_well->lock); + mutex_unlock(&power_well->lock); } /* -- cgit v1.2.3 From 4f0741291eaad552ebfffc20770d494375507412 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Oct 2013 17:25:51 +0300 Subject: drm/i915: factor out modeset_update_power_wells We'll need the same functionality for other HW generations. The support for these will be added by upcoming patches. Signed-off-by: Imre Deak Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 181f4f8daa79..320c696374ac 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6557,7 +6557,7 @@ static void hsw_package_c8_gpu_busy(struct drm_i915_private *dev_priv) } } -static void haswell_modeset_global_resources(struct drm_device *dev) +static void modeset_update_power_wells(struct drm_device *dev) { bool enable = false; struct intel_crtc *crtc; @@ -6572,7 +6572,11 @@ static void haswell_modeset_global_resources(struct drm_device *dev) } intel_set_power_well(dev, enable); +} +static void haswell_modeset_global_resources(struct drm_device *dev) +{ + modeset_update_power_wells(dev); hsw_update_package_c8(dev); } -- cgit v1.2.3 From 6efdf354ddb186c6604d1692075421e8d2c740e9 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 16 Oct 2013 17:25:52 +0300 Subject: drm/i915: enable only the needed power domains during modeset So far the modeset code enabled all power domains if it needed any. It wasn't a problem since HW generations so far only had one always-on power well and one dynamic power well that can be enabled/disabled. For domains powered by always-on power wells (panel fitter on pipe A and the eDP transcoder) we didn't do anything, for all other domains we just enabled the single dynamic power well. Future HW generations will change this, as they add multiple dynamic power wells. Support for these will be added later, this patch prepares for those by making sure we only enable the required domains. Note that after this change on HSW we'll enable all power domains even if it was the domain for the panel fitter on pipe A or the eDP transcoder. This isn't a problem since the power domain framework already checks if the domain is on an always-on power well and doesn't do anything in this case. Signed-off-by: Imre Deak Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 46 ++++++++++++++++++++++++++++++++---- drivers/gpu/drm/i915/intel_drv.h | 1 + 2 files changed, 42 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 320c696374ac..cfe9e7093b2a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6557,21 +6557,57 @@ static void hsw_package_c8_gpu_busy(struct drm_i915_private *dev_priv) } } +#define for_each_power_domain(domain, mask) \ + for ((domain) = 0; (domain) < POWER_DOMAIN_NUM; (domain)++) \ + if ((1 << (domain)) & (mask)) + +static unsigned long get_pipe_power_domains(struct drm_device *dev, + enum pipe pipe, bool pfit_enabled) +{ + unsigned long mask; + enum transcoder transcoder; + + transcoder = intel_pipe_to_cpu_transcoder(dev->dev_private, pipe); + + mask = BIT(POWER_DOMAIN_PIPE(pipe)); + mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder)); + if (pfit_enabled) + mask |= BIT(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe)); + + return mask; +} + static void modeset_update_power_wells(struct drm_device *dev) { - bool enable = false; + unsigned long pipe_domains[I915_MAX_PIPES] = { 0, }; struct intel_crtc *crtc; + /* + * First get all needed power domains, then put all unneeded, to avoid + * any unnecessary toggling of the power wells. + */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { + enum intel_display_power_domain domain; + if (!crtc->base.enabled) continue; - if (crtc->pipe != PIPE_A || crtc->config.pch_pfit.enabled || - crtc->config.cpu_transcoder != TRANSCODER_EDP) - enable = true; + pipe_domains[crtc->pipe] = get_pipe_power_domains(dev, + crtc->pipe, + crtc->config.pch_pfit.enabled); + + for_each_power_domain(domain, pipe_domains[crtc->pipe]) + intel_display_power_get(dev, domain); } - intel_set_power_well(dev, enable); + list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) { + enum intel_display_power_domain domain; + + for_each_power_domain(domain, crtc->enabled_power_domains) + intel_display_power_put(dev, domain); + + crtc->enabled_power_domains = pipe_domains[crtc->pipe]; + } } static void haswell_modeset_global_resources(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index e33f387d4185..af1553ca0f4e 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -326,6 +326,7 @@ struct intel_crtc { * some outputs connected to this crtc. */ bool active; + unsigned long enabled_power_domains; bool eld_vld; bool primary_enabled; /* is the primary plane (partially) visible? */ bool lowfreq_avail; -- cgit v1.2.3 From c459787294e8375210a3d26fe8ed83f40eca3276 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 21 Oct 2013 21:04:07 +0200 Subject: drm/i915: Move the pipe CRC stuff to other pipe data Adding stuff to the bottom of struct drm_i915_driver_private is nowadays considered uncool. Cc: Damien Lespiau Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index faface98ba37..2e1e884ac86c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1380,6 +1380,10 @@ typedef struct drm_i915_private { struct drm_crtc *pipe_to_crtc_mapping[3]; wait_queue_head_t pending_flip_queue; +#ifdef CONFIG_DEBUG_FS + struct intel_pipe_crc pipe_crc[I915_MAX_PIPES]; +#endif + int num_shared_dpll; struct intel_shared_dpll shared_dplls[I915_NUM_PLLS]; struct intel_ddi_plls ddi_plls; @@ -1460,10 +1464,6 @@ typedef struct drm_i915_private { struct i915_dri1_state dri1; /* Old ums support infrastructure, same warning applies. */ struct i915_ums_state ums; - -#ifdef CONFIG_DEBUG_FS - struct intel_pipe_crc pipe_crc[I915_MAX_PIPES]; -#endif } drm_i915_private_t; static inline struct drm_i915_private *to_i915(const struct drm_device *dev) -- cgit v1.2.3 From d538bbdfde34028b5c5b0ba92b3c2096c5afb82c Mon Sep 17 00:00:00 2001 From: Damien Lespiau Date: Mon, 21 Oct 2013 14:29:30 +0100 Subject: drm/i915: Use a spin lock to protect the pipe crc struct Daniel pointed out that it was hard to get anything lockless to work correctly, so don't even try for this non critical piece of code and just use a spin lock. v2: Make intel_pipe_crc->opened a bool v3: Use assert_spin_locked() instead of a comment (Daniel Vetter) v4: Use spin_lock_irq() in the debugfs functions (they can only be called from process context), Use spin_lock() in the pipe_crc_update() function that can only be called from an interrupt handler, Use wait_event_interruptible_lock_irq() when waiting for data in the cicular buffer to ensure proper locking around the condition we are waiting for. (Daniel Vetter) Suggested-by: Daniel Vetter Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 66 ++++++++++++++++++++++++++----------- drivers/gpu/drm/i915/i915_drv.h | 5 +-- drivers/gpu/drm/i915/i915_irq.c | 12 +++++-- 3 files changed, 58 insertions(+), 25 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 25fc3841a2b1..5c45e9e598de 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1772,13 +1772,18 @@ static int i915_pipe_crc_open(struct inode *inode, struct file *filep) struct drm_i915_private *dev_priv = info->dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; - if (!atomic_dec_and_test(&pipe_crc->available)) { - atomic_inc(&pipe_crc->available); + spin_lock_irq(&pipe_crc->lock); + + if (pipe_crc->opened) { + spin_unlock_irq(&pipe_crc->lock); return -EBUSY; /* already open */ } + pipe_crc->opened = true; filep->private_data = inode->i_private; + spin_unlock_irq(&pipe_crc->lock); + return 0; } @@ -1788,7 +1793,9 @@ static int i915_pipe_crc_release(struct inode *inode, struct file *filep) struct drm_i915_private *dev_priv = info->dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; - atomic_inc(&pipe_crc->available); /* release the device */ + spin_lock_irq(&pipe_crc->lock); + pipe_crc->opened = false; + spin_unlock_irq(&pipe_crc->lock); return 0; } @@ -1800,12 +1807,9 @@ static int i915_pipe_crc_release(struct inode *inode, struct file *filep) static int pipe_crc_data_count(struct intel_pipe_crc *pipe_crc) { - int head, tail; - - head = atomic_read(&pipe_crc->head); - tail = atomic_read(&pipe_crc->tail); - - return CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR); + assert_spin_locked(&pipe_crc->lock); + return CIRC_CNT(pipe_crc->head, pipe_crc->tail, + INTEL_PIPE_CRC_ENTRIES_NR); } static ssize_t @@ -1831,20 +1835,30 @@ i915_pipe_crc_read(struct file *filep, char __user *user_buf, size_t count, return 0; /* nothing to read */ + spin_lock_irq(&pipe_crc->lock); while (pipe_crc_data_count(pipe_crc) == 0) { - if (filep->f_flags & O_NONBLOCK) + int ret; + + if (filep->f_flags & O_NONBLOCK) { + spin_unlock_irq(&pipe_crc->lock); return -EAGAIN; + } - if (wait_event_interruptible(pipe_crc->wq, - pipe_crc_data_count(pipe_crc))) - return -ERESTARTSYS; + ret = wait_event_interruptible_lock_irq(pipe_crc->wq, + pipe_crc_data_count(pipe_crc), pipe_crc->lock); + if (ret) { + spin_unlock_irq(&pipe_crc->lock); + return ret; + } } /* We now have one or more entries to read */ - head = atomic_read(&pipe_crc->head); - tail = atomic_read(&pipe_crc->tail); + head = pipe_crc->head; + tail = pipe_crc->tail; n_entries = min((size_t)CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR), count / PIPE_CRC_LINE_LEN); + spin_unlock_irq(&pipe_crc->lock); + bytes_read = 0; n = 0; do { @@ -1864,10 +1878,13 @@ i915_pipe_crc_read(struct file *filep, char __user *user_buf, size_t count, BUILD_BUG_ON_NOT_POWER_OF_2(INTEL_PIPE_CRC_ENTRIES_NR); tail = (tail + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); - atomic_set(&pipe_crc->tail, tail); n++; } while (--n_entries); + spin_lock_irq(&pipe_crc->lock); + pipe_crc->tail = tail; + spin_unlock_irq(&pipe_crc->lock); + return bytes_read; } @@ -2111,8 +2128,10 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, if (!pipe_crc->entries) return -ENOMEM; - atomic_set(&pipe_crc->head, 0); - atomic_set(&pipe_crc->tail, 0); + spin_lock_irq(&pipe_crc->lock); + pipe_crc->head = 0; + pipe_crc->tail = 0; + spin_unlock_irq(&pipe_crc->lock); } pipe_crc->source = source; @@ -2122,13 +2141,19 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, /* real source -> none transition */ if (source == INTEL_PIPE_CRC_SOURCE_NONE) { + struct intel_pipe_crc_entry *entries; + DRM_DEBUG_DRIVER("stopping CRCs for pipe %c\n", pipe_name(pipe)); intel_wait_for_vblank(dev, pipe); - kfree(pipe_crc->entries); + spin_lock_irq(&pipe_crc->lock); + entries = pipe_crc->entries; pipe_crc->entries = NULL; + spin_unlock_irq(&pipe_crc->lock); + + kfree(entries); } return 0; @@ -2823,7 +2848,8 @@ void intel_display_crc_init(struct drm_device *dev) for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) { struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[i]; - atomic_set(&pipe_crc->available, 1); + pipe_crc->opened = false; + spin_lock_init(&pipe_crc->lock); init_waitqueue_head(&pipe_crc->wq); } } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2e1e884ac86c..5bfcf0f91a51 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1249,10 +1249,11 @@ struct intel_pipe_crc_entry { #define INTEL_PIPE_CRC_ENTRIES_NR 128 struct intel_pipe_crc { - atomic_t available; /* exclusive access to the device */ + spinlock_t lock; + bool opened; /* exclusive access to the result file */ struct intel_pipe_crc_entry *entries; enum intel_pipe_crc_source source; - atomic_t head, tail; + int head, tail; wait_queue_head_t wq; }; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8f7baad72316..1a7dc7754e2f 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1200,15 +1200,19 @@ static void display_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe, struct intel_pipe_crc_entry *entry; int head, tail; + spin_lock(&pipe_crc->lock); + if (!pipe_crc->entries) { + spin_unlock(&pipe_crc->lock); DRM_ERROR("spurious interrupt\n"); return; } - head = atomic_read(&pipe_crc->head); - tail = atomic_read(&pipe_crc->tail); + head = pipe_crc->head; + tail = pipe_crc->tail; if (CIRC_SPACE(head, tail, INTEL_PIPE_CRC_ENTRIES_NR) < 1) { + spin_unlock(&pipe_crc->lock); DRM_ERROR("CRC buffer overflowing\n"); return; } @@ -1223,7 +1227,9 @@ static void display_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe, entry->crc[4] = crc4; head = (head + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); - atomic_set(&pipe_crc->head, head); + pipe_crc->head = head; + + spin_unlock(&pipe_crc->lock); wake_up_interruptible(&pipe_crc->wq); } -- cgit v1.2.3 From de926800b155886c61b06146e28c0ba2e6fafc39 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 22 Oct 2013 10:46:59 -0400 Subject: drm/radeon: use sw CTS/N values for audio on DCE4+ Use the driver calculated CTS and N values rather than having hardware generate them. This allows us to use the modeline pixel clock rather than the actual pll clock when setting up the dto for audio. Fixes problems with audio playback rate on certain asics if the pll clock does not match the pixel clock exactly. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/evergreen_hdmi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index fe1de855775e..57fcc4b16a52 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -291,6 +291,7 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode /* fglrx clears sth in AFMT_AUDIO_PACKET_CONTROL2 here */ WREG32(HDMI_ACR_PACKET_CONTROL + offset, + HDMI_ACR_SOURCE | /* select SW CTS value */ HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ evergreen_hdmi_update_ACR(encoder, mode->clock); -- cgit v1.2.3 From d48d88b21ede7990702b990bc36262c3d5fd7a1f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 23 Oct 2013 11:20:46 -0400 Subject: drm/radeon: disable bapm on KB May cause stability problems on some boards. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/kv_dpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c index 71399065db04..b41905573cd2 100644 --- a/drivers/gpu/drm/radeon/kv_dpm.c +++ b/drivers/gpu/drm/radeon/kv_dpm.c @@ -2635,7 +2635,7 @@ int kv_dpm_init(struct radeon_device *rdev) pi->caps_sclk_ds = true; pi->enable_auto_thermal_throttling = true; pi->disable_nb_ps3_in_battery = false; - pi->bapm_enable = true; + pi->bapm_enable = false; pi->voltage_drop_t = 0; pi->caps_sclk_throttle_low_notification = false; pi->caps_fps = false; /* true? */ -- cgit v1.2.3 From cdf6e8058415ba4d808537e30a0a6be9fb29e95a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 23 Oct 2013 16:13:42 -0400 Subject: drm/radeon/dpm: fix incompatible casting on big endian We use u16 for voltage values throughout the driver so switch the table values to a u16 as well. Fixes an incompatible cast error in ci_patch_clock_voltage_limits_with_vddc_leakage() picked up by coverity. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index a400ac1c4147..24f4960f59ee 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1272,8 +1272,8 @@ struct radeon_blacklist_clocks struct radeon_clock_and_voltage_limits { u32 sclk; u32 mclk; - u32 vddc; - u32 vddci; + u16 vddc; + u16 vddci; }; struct radeon_clock_array { -- cgit v1.2.3 From 153b4b9547965729120d427485e414855399acac Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Tue, 22 Oct 2013 22:05:09 -0700 Subject: drm/i915: Convert straggling MCHBAR registers All our registers which are written through the MCHBAR are defined descriptively as an offset to the MCHBAR. We had 3 outliers here. Convert these as well so all registers which are offsets are MCHBAR can be easily identified/found within the code. With this, convert DCLK to also follow this format. Signed-off-by: Ben Widawsky Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 8 ++++---- drivers/gpu/drm/i915/intel_pm.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d1fb06a6a3f0..e4fef047a069 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1476,7 +1476,7 @@ #define MCHBAR_MIRROR_BASE_SNB 0x140000 /* Memory controller frequency in MCHBAR for Haswell (possible SNB+) */ -#define DCLK 0x5e04 +#define DCLK (MCHBAR_MIRROR_BASE_SNB + 0x5e04) /** 915-945 and GM965 MCH register controlling DRAM channel access */ #define DCC 0x10200 @@ -1771,9 +1771,9 @@ #define GEN6_GT_THREAD_STATUS_CORE_MASK 0x7 #define GEN6_GT_THREAD_STATUS_CORE_MASK_HSW (0x7 | (0x07 << 16)) -#define GEN6_GT_PERF_STATUS 0x145948 -#define GEN6_RP_STATE_LIMITS 0x145994 -#define GEN6_RP_STATE_CAP 0x145998 +#define GEN6_GT_PERF_STATUS (MCHBAR_MIRROR_BASE_SNB + 0x5948) +#define GEN6_RP_STATE_LIMITS (MCHBAR_MIRROR_BASE_SNB + 0x5994) +#define GEN6_RP_STATE_CAP (MCHBAR_MIRROR_BASE_SNB + 0x5998) /* * Logical Context regs diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f3136659877a..2f26d6c2fc93 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3915,7 +3915,7 @@ void gen6_update_ring_freq(struct drm_device *dev) /* Convert from kHz to MHz */ max_ia_freq /= 1000; - min_ring_freq = I915_READ(MCHBAR_MIRROR_BASE_SNB + DCLK) & 0xf; + min_ring_freq = I915_READ(DCLK) & 0xf; /* convert DDR frequency from units of 266.6MHz to bandwidth */ min_ring_freq = mult_frac(min_ring_freq, 8, 3); -- cgit v1.2.3 From a74b0c481589762f28f35a26b2c77126f38de652 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 24 Oct 2013 09:59:11 -0700 Subject: drm/i915: Remove WaFbcDisableDpfcClockGating on IVB Production IVB does not need it. I confirmed this with Art. Signed-off-by: Ben Widawsky Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2f26d6c2fc93..c325a57b89b5 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -254,12 +254,6 @@ static void ironlake_disable_fbc(struct drm_device *dev) dpfc_ctl &= ~DPFC_CTL_EN; I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); - if (IS_IVYBRIDGE(dev)) - /* WaFbcDisableDpfcClockGating:ivb */ - I915_WRITE(ILK_DSPCLK_GATE_D, - I915_READ(ILK_DSPCLK_GATE_D) & - ~ILK_DPFCUNIT_CLOCK_GATE_DISABLE); - if (IS_HASWELL(dev)) /* WaFbcDisableDpfcClockGating:hsw */ I915_WRITE(HSW_CLKGATE_DISABLE_PART_1, @@ -295,10 +289,6 @@ static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval) if (IS_IVYBRIDGE(dev)) { /* WaFbcAsynchFlipDisableFbcQueue:ivb */ I915_WRITE(ILK_DISPLAY_CHICKEN1, ILK_FBCQ_DIS); - /* WaFbcDisableDpfcClockGating:ivb */ - I915_WRITE(ILK_DSPCLK_GATE_D, - I915_READ(ILK_DSPCLK_GATE_D) | - ILK_DPFCUNIT_CLOCK_GATE_DISABLE); } else { /* WaFbcAsynchFlipDisableFbcQueue:hsw */ I915_WRITE(HSW_PIPE_SLICE_CHICKEN_1(intel_crtc->pipe), -- cgit v1.2.3 From 8c7b72f20b5d197bf70e93e87046def20eaa3f36 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 24 Oct 2013 09:59:12 -0700 Subject: drm/i915: Remove WaFbcDisableDpfcClockGating on HSW Production HSW does not need it. I confirmed this with Art. Signed-off-by: Ben Widawsky Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 3 --- drivers/gpu/drm/i915/intel_pm.c | 10 ---------- 2 files changed, 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e4fef047a069..47de41f1d4b4 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1106,9 +1106,6 @@ _HSW_PIPE_SLICE_CHICKEN_1_A, + \ _HSW_PIPE_SLICE_CHICKEN_1_B) -#define HSW_CLKGATE_DISABLE_PART_1 0x46500 -#define HSW_DPFC_GATING_DISABLE (1<<23) - /* * GPIO regs */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index c325a57b89b5..03b5a01c2d55 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -254,12 +254,6 @@ static void ironlake_disable_fbc(struct drm_device *dev) dpfc_ctl &= ~DPFC_CTL_EN; I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl); - if (IS_HASWELL(dev)) - /* WaFbcDisableDpfcClockGating:hsw */ - I915_WRITE(HSW_CLKGATE_DISABLE_PART_1, - I915_READ(HSW_CLKGATE_DISABLE_PART_1) & - ~HSW_DPFC_GATING_DISABLE); - DRM_DEBUG_KMS("disabled FBC\n"); } } @@ -293,10 +287,6 @@ static void gen7_enable_fbc(struct drm_crtc *crtc, unsigned long interval) /* WaFbcAsynchFlipDisableFbcQueue:hsw */ I915_WRITE(HSW_PIPE_SLICE_CHICKEN_1(intel_crtc->pipe), HSW_BYPASS_FBC_QUEUE); - /* WaFbcDisableDpfcClockGating:hsw */ - I915_WRITE(HSW_CLKGATE_DISABLE_PART_1, - I915_READ(HSW_CLKGATE_DISABLE_PART_1) | - HSW_DPFC_GATING_DISABLE); } I915_WRITE(SNB_DPFC_CTL_SA, -- cgit v1.2.3 From 83c00f55302219fdac1f8628e61f2b63cffc58d5 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 25 Oct 2013 17:36:47 +0300 Subject: drm/i915: prepare for multiple power wells In the future we'll need to support multiple power wells, so prepare for that here. Create a new power domains struct which contains all power domain/well specific fields. Since we'll have one lock protecting all power wells, move power_well->lock to the new struct too. No functional change. Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 11 ++++++--- drivers/gpu/drm/i915/intel_pm.c | 55 +++++++++++++++++++++++++---------------- 2 files changed, 42 insertions(+), 24 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5bfcf0f91a51..8371182f7480 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -909,12 +909,18 @@ struct intel_ilk_power_mgmt { /* Power well structure for haswell */ struct i915_power_well { struct drm_device *device; - struct mutex lock; /* power well enable/disable usage count */ int count; int i915_request; }; +#define I915_MAX_POWER_WELLS 1 + +struct i915_power_domains { + struct mutex lock; + struct i915_power_well power_wells[I915_MAX_POWER_WELLS]; +}; + struct i915_dri1_state { unsigned allow_batchbuffer : 1; u32 __iomem *gfx_hws_cpu_addr; @@ -1410,8 +1416,7 @@ typedef struct drm_i915_private { * mchdev_lock in intel_pm.c */ struct intel_ilk_power_mgmt ips; - /* Haswell power well */ - struct i915_power_well power_well; + struct i915_power_domains power_domains; struct i915_psr psr; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 03b5a01c2d55..5869482f3f69 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5598,7 +5598,7 @@ void intel_display_power_get(struct drm_device *dev, enum intel_display_power_domain domain) { struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_power_well *power_well = &dev_priv->power_well; + struct i915_power_domains *power_domains; if (!HAS_POWER_WELL(dev)) return; @@ -5606,16 +5606,18 @@ void intel_display_power_get(struct drm_device *dev, if (is_always_on_power_domain(dev, domain)) return; - mutex_lock(&power_well->lock); - __intel_power_well_get(power_well); - mutex_unlock(&power_well->lock); + power_domains = &dev_priv->power_domains; + + mutex_lock(&power_domains->lock); + __intel_power_well_get(&power_domains->power_wells[0]); + mutex_unlock(&power_domains->lock); } void intel_display_power_put(struct drm_device *dev, enum intel_display_power_domain domain) { struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_power_well *power_well = &dev_priv->power_well; + struct i915_power_domains *power_domains; if (!HAS_POWER_WELL(dev)) return; @@ -5623,12 +5625,14 @@ void intel_display_power_put(struct drm_device *dev, if (is_always_on_power_domain(dev, domain)) return; - mutex_lock(&power_well->lock); - __intel_power_well_put(power_well); - mutex_unlock(&power_well->lock); + power_domains = &dev_priv->power_domains; + + mutex_lock(&power_domains->lock); + __intel_power_well_put(&power_domains->power_wells[0]); + mutex_unlock(&power_domains->lock); } -static struct i915_power_well *hsw_pwr; +static struct i915_power_domains *hsw_pwr; /* Display audio driver power well request */ void i915_request_power_well(void) @@ -5637,7 +5641,7 @@ void i915_request_power_well(void) return; mutex_lock(&hsw_pwr->lock); - __intel_power_well_get(hsw_pwr); + __intel_power_well_get(&hsw_pwr->power_wells[0]); mutex_unlock(&hsw_pwr->lock); } EXPORT_SYMBOL_GPL(i915_request_power_well); @@ -5649,7 +5653,7 @@ void i915_release_power_well(void) return; mutex_lock(&hsw_pwr->lock); - __intel_power_well_put(hsw_pwr); + __intel_power_well_put(&hsw_pwr->power_wells[0]); mutex_unlock(&hsw_pwr->lock); } EXPORT_SYMBOL_GPL(i915_release_power_well); @@ -5657,12 +5661,15 @@ EXPORT_SYMBOL_GPL(i915_release_power_well); int i915_init_power_well(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + struct i915_power_domains *power_domains = &dev_priv->power_domains; + struct i915_power_well *power_well; - hsw_pwr = &dev_priv->power_well; + mutex_init(&power_domains->lock); + hsw_pwr = power_domains; - hsw_pwr->device = dev; - mutex_init(&hsw_pwr->lock); - hsw_pwr->count = 0; + power_well = &power_domains->power_wells[0]; + power_well->device = dev; + power_well->count = 0; return 0; } @@ -5675,7 +5682,8 @@ void i915_remove_power_well(struct drm_device *dev) void intel_set_power_well(struct drm_device *dev, bool enable) { struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_power_well *power_well = &dev_priv->power_well; + struct i915_power_domains *power_domains = &dev_priv->power_domains; + struct i915_power_well *power_well; if (!HAS_POWER_WELL(dev)) return; @@ -5683,8 +5691,9 @@ void intel_set_power_well(struct drm_device *dev, bool enable) if (!i915_disable_power_well && !enable) return; - mutex_lock(&power_well->lock); + mutex_lock(&power_domains->lock); + power_well = &power_domains->power_wells[0]; /* * This function will only ever contribute one * to the power well reference count. i915_request @@ -5702,20 +5711,24 @@ void intel_set_power_well(struct drm_device *dev, bool enable) __intel_power_well_put(power_well); out: - mutex_unlock(&power_well->lock); + mutex_unlock(&power_domains->lock); } static void intel_resume_power_well(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_power_well *power_well = &dev_priv->power_well; + struct i915_power_domains *power_domains = &dev_priv->power_domains; + struct i915_power_well *power_well; if (!HAS_POWER_WELL(dev)) return; - mutex_lock(&power_well->lock); + mutex_lock(&power_domains->lock); + + power_well = &power_domains->power_wells[0]; __intel_set_power_well(dev, power_well->count > 0); - mutex_unlock(&power_well->lock); + + mutex_unlock(&power_domains->lock); } /* -- cgit v1.2.3 From baa707073b6f5374a917f86f4a681149cd39dc64 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 25 Oct 2013 17:36:48 +0300 Subject: drm/i915: use power get/put instead of set for power on after init Currently we make sure that all power domains are enabled during driver init and turn off unneded ones only after the first modeset. Similarly during suspend we enable all power domains, which will remain on through the following resume until the first modeset. This logic is supported by intel_set_power_well() in the power domain framework. It would be nice to simplify the API, so that we only have get/put functions and make it more explicit on the higher level how this "power well on during init" logic works. This will make it also easier if in the future we want to shorten the time the power wells are on. For this add a new device private flag tracking whether we have the power wells on because of init/suspend and use only intel_display_power_get()/put(). As nothing else uses intel_set_power_well() we can remove it. This also fixes commit 6efdf354ddb186c6604d1692075421e8d2c740e9 Author: Imre Deak Date: Wed Oct 16 17:25:52 2013 +0300 drm/i915: enable only the needed power domains during modeset where removing intel_set_power_well() resulted in not releasing the reference on the power well that was taken during init and thus leaving the power well on all the time. Regression reported by Paulo. v2: - move the init_power_on flag to the power_domains struct (Daniel) v3: - add note about this being a regression fix too (Paulo) Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 2 +- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 8 +++++++- drivers/gpu/drm/i915/intel_display.c | 17 +++++++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 37 +----------------------------------- 6 files changed, 28 insertions(+), 39 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 437886641d90..bec1fe93cf24 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1723,7 +1723,7 @@ int i915_driver_unload(struct drm_device *dev) /* The i915.ko module is still not prepared to be loaded when * the power well is not enabled, so just enable it in case * we're going to unload/reload. */ - intel_set_power_well(dev, true); + intel_display_set_init_power(dev, true); i915_remove_power_well(dev); } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 1060a96d2184..b764f7b7eb6b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -477,7 +477,7 @@ static int i915_drm_freeze(struct drm_device *dev) /* We do a lot of poking in a lot of registers, make sure they work * properly. */ hsw_disable_package_c8(dev_priv); - intel_set_power_well(dev, true); + intel_display_set_init_power(dev, true); drm_kms_helper_poll_disable(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8371182f7480..43dbf6a06a9d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -100,6 +100,7 @@ enum intel_display_power_domain { POWER_DOMAIN_TRANSCODER_C, POWER_DOMAIN_TRANSCODER_EDP, POWER_DOMAIN_VGA, + POWER_DOMAIN_INIT, POWER_DOMAIN_NUM, }; @@ -911,12 +912,17 @@ struct i915_power_well { struct drm_device *device; /* power well enable/disable usage count */ int count; - int i915_request; }; #define I915_MAX_POWER_WELLS 1 struct i915_power_domains { + /* + * Power wells needed for initialization at driver init and suspend + * time are on. They are kept on until after the first modeset. + */ + bool init_power_on; + struct mutex lock; struct i915_power_well power_wells[I915_MAX_POWER_WELLS]; }; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index cfe9e7093b2a..8c3bf8a89cb7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6577,6 +6577,21 @@ static unsigned long get_pipe_power_domains(struct drm_device *dev, return mask; } +void intel_display_set_init_power(struct drm_device *dev, bool enable) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (dev_priv->power_domains.init_power_on == enable) + return; + + if (enable) + intel_display_power_get(dev, POWER_DOMAIN_INIT); + else + intel_display_power_put(dev, POWER_DOMAIN_INIT); + + dev_priv->power_domains.init_power_on = enable; +} + static void modeset_update_power_wells(struct drm_device *dev) { unsigned long pipe_domains[I915_MAX_PIPES] = { 0, }; @@ -6608,6 +6623,8 @@ static void modeset_update_power_wells(struct drm_device *dev) crtc->enabled_power_domains = pipe_domains[crtc->pipe]; } + + intel_display_set_init_power(dev, false); } static void haswell_modeset_global_resources(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index af1553ca0f4e..bf4394a144a5 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -692,6 +692,7 @@ bool intel_crtc_active(struct drm_crtc *crtc); void i915_disable_vga_mem(struct drm_device *dev); void hsw_enable_ips(struct intel_crtc *crtc); void hsw_disable_ips(struct intel_crtc *crtc); +void intel_display_set_init_power(struct drm_device *dev, bool enable); /* intel_dp.c */ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5869482f3f69..5ae6d533ebcd 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5679,41 +5679,6 @@ void i915_remove_power_well(struct drm_device *dev) hsw_pwr = NULL; } -void intel_set_power_well(struct drm_device *dev, bool enable) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - struct i915_power_domains *power_domains = &dev_priv->power_domains; - struct i915_power_well *power_well; - - if (!HAS_POWER_WELL(dev)) - return; - - if (!i915_disable_power_well && !enable) - return; - - mutex_lock(&power_domains->lock); - - power_well = &power_domains->power_wells[0]; - /* - * This function will only ever contribute one - * to the power well reference count. i915_request - * is what tracks whether we have or have not - * added the one to the reference count. - */ - if (power_well->i915_request == enable) - goto out; - - power_well->i915_request = enable; - - if (enable) - __intel_power_well_get(power_well); - else - __intel_power_well_put(power_well); - - out: - mutex_unlock(&power_domains->lock); -} - static void intel_resume_power_well(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -5745,7 +5710,7 @@ void intel_init_power_well(struct drm_device *dev) return; /* For now, we need the power well to be always enabled. */ - intel_set_power_well(dev, true); + intel_display_set_init_power(dev, true); intel_resume_power_well(dev); /* We're taking over the BIOS, so clear any requests made by it since -- cgit v1.2.3 From b4ed448447970aab11ee33ac28716baaff68fbb8 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Fri, 25 Oct 2013 17:36:49 +0300 Subject: drm/i915: remove device field from struct power_well The only real need for this field was in i915_{request,release}_power_well, but there we can get at it by a container_of magic. Also since in the future we'll have multiple power wells each with its own power_well struct it makes sense to remove the field from there where it'd be just redundancy. Suggested-by: Paulo Zanoni Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/intel_pm.c | 29 ++++++++++++++++++++--------- 2 files changed, 20 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 43dbf6a06a9d..57715c8e59c6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -909,7 +909,6 @@ struct intel_ilk_power_mgmt { /* Power well structure for haswell */ struct i915_power_well { - struct drm_device *device; /* power well enable/disable usage count */ int count; }; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5ae6d533ebcd..235b39095550 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5581,17 +5581,19 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) } } -static void __intel_power_well_get(struct i915_power_well *power_well) +static void __intel_power_well_get(struct drm_device *dev, + struct i915_power_well *power_well) { if (!power_well->count++) - __intel_set_power_well(power_well->device, true); + __intel_set_power_well(dev, true); } -static void __intel_power_well_put(struct i915_power_well *power_well) +static void __intel_power_well_put(struct drm_device *dev, + struct i915_power_well *power_well) { WARN_ON(!power_well->count); if (!--power_well->count) - __intel_set_power_well(power_well->device, false); + __intel_set_power_well(dev, false); } void intel_display_power_get(struct drm_device *dev, @@ -5609,7 +5611,7 @@ void intel_display_power_get(struct drm_device *dev, power_domains = &dev_priv->power_domains; mutex_lock(&power_domains->lock); - __intel_power_well_get(&power_domains->power_wells[0]); + __intel_power_well_get(dev, &power_domains->power_wells[0]); mutex_unlock(&power_domains->lock); } @@ -5628,7 +5630,7 @@ void intel_display_power_put(struct drm_device *dev, power_domains = &dev_priv->power_domains; mutex_lock(&power_domains->lock); - __intel_power_well_put(&power_domains->power_wells[0]); + __intel_power_well_put(dev, &power_domains->power_wells[0]); mutex_unlock(&power_domains->lock); } @@ -5637,11 +5639,16 @@ static struct i915_power_domains *hsw_pwr; /* Display audio driver power well request */ void i915_request_power_well(void) { + struct drm_i915_private *dev_priv; + if (WARN_ON(!hsw_pwr)) return; + dev_priv = container_of(hsw_pwr, struct drm_i915_private, + power_domains); + mutex_lock(&hsw_pwr->lock); - __intel_power_well_get(&hsw_pwr->power_wells[0]); + __intel_power_well_get(dev_priv->dev, &hsw_pwr->power_wells[0]); mutex_unlock(&hsw_pwr->lock); } EXPORT_SYMBOL_GPL(i915_request_power_well); @@ -5649,11 +5656,16 @@ EXPORT_SYMBOL_GPL(i915_request_power_well); /* Display audio driver power well release */ void i915_release_power_well(void) { + struct drm_i915_private *dev_priv; + if (WARN_ON(!hsw_pwr)) return; + dev_priv = container_of(hsw_pwr, struct drm_i915_private, + power_domains); + mutex_lock(&hsw_pwr->lock); - __intel_power_well_put(&hsw_pwr->power_wells[0]); + __intel_power_well_put(dev_priv->dev, &hsw_pwr->power_wells[0]); mutex_unlock(&hsw_pwr->lock); } EXPORT_SYMBOL_GPL(i915_release_power_well); @@ -5668,7 +5680,6 @@ int i915_init_power_well(struct drm_device *dev) hsw_pwr = power_domains; power_well = &power_domains->power_wells[0]; - power_well->device = dev; power_well->count = 0; return 0; -- cgit v1.2.3 From 4f56d12ebb28fceac4c6e60c8993fbfc122e1399 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 21 Oct 2013 10:52:06 +0300 Subject: drm/i915: Add support for pipe_bpp readout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On CTG+ read out the pipe bpp setting from hardware and fill it into pipe config. Also check it appropriately. v2: Don't do the pipe_bpp extraction inside the PCH only code block on ILK+. Avoid the PIPECONF read as we already have read it for the PIPECONF_EANBLE check. Note: This is already in drm-intel-next-queued as commit 42571aefafb1d330ef84eb29418832f72e7dfb4c Author: Ville Syrjälä Date: Fri Sep 6 23:29:00 2013 +0300 drm/i915: Add support for pipe_bpp readout but is needed for the following bugfix. Signed-off-by: Ville Syrjälä Reviewed-by: Jani Nikula Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ddi.c | 17 +++++++++++++++++ drivers/gpu/drm/i915/intel_display.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 63de2701b974..beb7f65cd01f 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1268,6 +1268,23 @@ static void intel_ddi_get_config(struct intel_encoder *encoder, flags |= DRM_MODE_FLAG_NVSYNC; pipe_config->adjusted_mode.flags |= flags; + + switch (temp & TRANS_DDI_BPC_MASK) { + case TRANS_DDI_BPC_6: + pipe_config->pipe_bpp = 18; + break; + case TRANS_DDI_BPC_8: + pipe_config->pipe_bpp = 24; + break; + case TRANS_DDI_BPC_10: + pipe_config->pipe_bpp = 30; + break; + case TRANS_DDI_BPC_12: + pipe_config->pipe_bpp = 36; + break; + default: + break; + } } static void intel_ddi_destroy(struct drm_encoder *encoder) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 581fb4b2f766..725f0bea1e4c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4983,6 +4983,22 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, if (!(tmp & PIPECONF_ENABLE)) return false; + if (IS_G4X(dev) || IS_VALLEYVIEW(dev)) { + switch (tmp & PIPECONF_BPC_MASK) { + case PIPECONF_6BPC: + pipe_config->pipe_bpp = 18; + break; + case PIPECONF_8BPC: + pipe_config->pipe_bpp = 24; + break; + case PIPECONF_10BPC: + pipe_config->pipe_bpp = 30; + break; + default: + break; + } + } + intel_get_pipe_timings(crtc, pipe_config); i9xx_get_pfit_config(crtc, pipe_config); @@ -5881,6 +5897,23 @@ static bool ironlake_get_pipe_config(struct intel_crtc *crtc, if (!(tmp & PIPECONF_ENABLE)) return false; + switch (tmp & PIPECONF_BPC_MASK) { + case PIPECONF_6BPC: + pipe_config->pipe_bpp = 18; + break; + case PIPECONF_8BPC: + pipe_config->pipe_bpp = 24; + break; + case PIPECONF_10BPC: + pipe_config->pipe_bpp = 30; + break; + case PIPECONF_12BPC: + pipe_config->pipe_bpp = 36; + break; + default: + break; + } + if (I915_READ(PCH_TRANSCONF(crtc->pipe)) & TRANS_ENABLE) { struct intel_shared_dpll *pll; @@ -8612,6 +8645,9 @@ intel_pipe_config_compare(struct drm_device *dev, PIPE_CONF_CHECK_X(dpll_hw_state.fp0); PIPE_CONF_CHECK_X(dpll_hw_state.fp1); + if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) + PIPE_CONF_CHECK_I(pipe_bpp); + #undef PIPE_CONF_CHECK_X #undef PIPE_CONF_CHECK_I #undef PIPE_CONF_CHECK_FLAGS -- cgit v1.2.3 From 7195a50b5c7e00cc3312934fd022c3006b533d12 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 24 Sep 2013 14:24:05 +0300 Subject: drm/i915: Add HSW CRT output readout support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Call intel_ddi_get_config() to get the pipe_bpp settings from DDI. The sync polarity settings from DDI are irrelevant for CRT output, so override them with data from the ADPA register. Note: This is already merged in drm-intel-next-queued as commit 6801c18c0a43386bb44712cbc028a7e05adb9f0d Author: Ville Syrjälä Date: Tue Sep 24 14:24:05 2013 +0300 drm/i915: Add HSW CRT output readout support but is required for the following edp bpp bugfix. v2: Extract intel_crt_get_flags() Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=69691 Tested-by: Qingshuai Tian Signed-off-by: Ville Syrjälä Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_crt.c | 30 ++++++++++++++++++++++++++---- drivers/gpu/drm/i915/intel_ddi.c | 4 ++-- drivers/gpu/drm/i915/intel_drv.h | 2 ++ 3 files changed, 30 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index ea9022ef15d5..db59bb9fbe23 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -83,8 +83,7 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder, return true; } -static void intel_crt_get_config(struct intel_encoder *encoder, - struct intel_crtc_config *pipe_config) +static unsigned int intel_crt_get_flags(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_crt *crt = intel_encoder_to_crt(encoder); @@ -102,7 +101,27 @@ static void intel_crt_get_config(struct intel_encoder *encoder, else flags |= DRM_MODE_FLAG_NVSYNC; - pipe_config->adjusted_mode.flags |= flags; + return flags; +} + +static void intel_crt_get_config(struct intel_encoder *encoder, + struct intel_crtc_config *pipe_config) +{ + struct drm_device *dev = encoder->base.dev; + + pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder); +} + +static void hsw_crt_get_config(struct intel_encoder *encoder, + struct intel_crtc_config *pipe_config) +{ + intel_ddi_get_config(encoder, pipe_config); + + pipe_config->adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC | + DRM_MODE_FLAG_NHSYNC | + DRM_MODE_FLAG_PVSYNC | + DRM_MODE_FLAG_NVSYNC); + pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder); } /* Note: The caller is required to filter out dpms modes not supported by the @@ -799,7 +818,10 @@ void intel_crt_init(struct drm_device *dev) crt->base.mode_set = intel_crt_mode_set; crt->base.disable = intel_disable_crt; crt->base.enable = intel_enable_crt; - crt->base.get_config = intel_crt_get_config; + if (IS_HASWELL(dev)) + crt->base.get_config = hsw_crt_get_config; + else + crt->base.get_config = intel_crt_get_config; if (I915_HAS_HOTPLUG(dev)) crt->base.hpd_pin = HPD_CRT; if (HAS_DDI(dev)) diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index beb7f65cd01f..b53fff84a7d5 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -1249,8 +1249,8 @@ static void intel_ddi_hot_plug(struct intel_encoder *intel_encoder) intel_dp_check_link_status(intel_dp); } -static void intel_ddi_get_config(struct intel_encoder *encoder, - struct intel_crtc_config *pipe_config) +void intel_ddi_get_config(struct intel_encoder *encoder, + struct intel_crtc_config *pipe_config) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 9b7b68fd5d47..7f2b384ac939 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -765,6 +765,8 @@ extern void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder); extern bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector); extern void intel_ddi_fdi_disable(struct drm_crtc *crtc); +extern void intel_ddi_get_config(struct intel_encoder *encoder, + struct intel_crtc_config *pipe_config); extern void intel_display_handle_reset(struct drm_device *dev); extern bool intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, -- cgit v1.2.3 From c6cd2ee2d59111a07cd9199564c9bdcb2d11e5cf Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Oct 2013 10:52:07 +0300 Subject: drm/i915/dp: workaround BIOS eDP bpp clamping issue This isn't a real fix to the problem, but rather a stopgap measure while trying to find a proper solution. There are several laptops out there that fail to light up the eDP panel in UEFI boot mode. They seem to be mostly IVB machines, including but apparently not limited to Dell XPS 13, Asus TX300, Asus UX31A, Asus UX32VD, Acer Aspire S7. They seem to work in CSM or legacy boot. The difference between UEFI and CSM is that the BIOS provides a different VBT to the kernel. The UEFI VBT typically specifies 18 bpp and 1.62 GHz link for eDP, while CSM VBT has 24 bpp and 2.7 GHz link. We end up clamping to 18 bpp in UEFI mode, which we can fit in the 1.62 Ghz link, and for reasons yet unknown fail to light up the panel. Dithering from 24 to 18 bpp itself seems to work; if we use 18 bpp with 2.7 GHz link, the eDP panel lights up. So essentially this is a link speed issue, and *not* a bpp clamping issue. The bug raised its head since commit 657445fe8660100ad174600ebfa61536392b7624 Author: Daniel Vetter Date: Sat May 4 10:09:18 2013 +0200 Revert "drm/i915: revert eDP bpp clamping code changes" which started clamping bpp *before* computing the link requirements, and thus affecting the required bandwidth. Clamping after the computations kept the link at 2.7 GHz. Even though the BIOS tells us to use 18 bpp through the VBT, it happily boots up at 24 bpp and 2.7 GHz itself! Use this information to selectively ignore the VBT provided value. We can't ignore the VBT eDP bpp altogether, as there are other laptops that do require the clamping to be used due to EDID reporting higher bpp than the panel can support. Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=59841 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=67950 Tested-by: Ulf Winkelvos Tested-by: jkp CC: stable@vger.kernel.org Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 2c555f91bfae..1a431377d83b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1401,6 +1401,26 @@ static void intel_dp_get_config(struct intel_encoder *encoder, else pipe_config->port_clock = 270000; } + + if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp && + pipe_config->pipe_bpp > dev_priv->vbt.edp_bpp) { + /* + * This is a big fat ugly hack. + * + * Some machines in UEFI boot mode provide us a VBT that has 18 + * bpp and 1.62 GHz link bandwidth for eDP, which for reasons + * unknown we fail to light up. Yet the same BIOS boots up with + * 24 bpp and 2.7 GHz link. Use the same bpp as the BIOS uses as + * max, not what it tells us to use. + * + * Note: This will still be broken if the eDP panel is not lit + * up by the BIOS, and thus we can't get the mode at module + * load. + */ + DRM_DEBUG_KMS("pipe has %d bpp for eDP panel, overriding BIOS-provided max %d bpp\n", + pipe_config->pipe_bpp, dev_priv->vbt.edp_bpp); + dev_priv->vbt.edp_bpp = pipe_config->pipe_bpp; + } } static bool is_edp_psr(struct intel_dp *intel_dp) -- cgit v1.2.3 From 645378d85ee524e429aa4cf52806047b56cdc596 Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Sun, 27 Oct 2013 16:13:42 +0000 Subject: drm/i915: No LVDS hardware on Intel D410PT and D425KT The Intel D410PT(LW) and D425KT Mini-ITX desktop boards both show up as having LVDS but the hardware is not populated. This patch adds them to the list of such systems. Patch is against 3.11.4 v2: Patch revised to match the D425KT exactly as the D425KTW does have LVDS. According to Intel's documentation, the D410PTL and D410PLTW don't. Signed-off-by: Rob Pearce Cc: stable@vger.kernel.org [danvet: Pimp commit message to my liking and add cc: stable.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_lvds.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 831a5c021c4b..b8af94a5be39 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -698,6 +698,22 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Q900"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Intel D410PT", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Intel"), + DMI_MATCH(DMI_BOARD_NAME, "D410PT"), + }, + }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Intel D425KT", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Intel"), + DMI_EXACT_MATCH(DMI_BOARD_NAME, "D425KT"), + }, + }, { .callback = intel_no_lvds_dmi_callback, .ident = "Intel D510MO", -- cgit v1.2.3 From 92e76c8c7e436a07af3e0b594480ff8689add078 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 21 Oct 2013 19:01:58 +0300 Subject: drm/i915: Clamp cursor coordinates to int16_t range MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We store cursor_x/y as int16_t internally, but the user provided coordinates are int32_t. Clamp the coordinates so that they don't overflow the int16_t. Since the cursor is only 64x64 in size, the clamping can't cause any visual changes. Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8c3bf8a89cb7..c69a5b844f5a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7333,8 +7333,8 @@ static int intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) { struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - intel_crtc->cursor_x = x; - intel_crtc->cursor_y = y; + intel_crtc->cursor_x = clamp_t(int, x, SHRT_MIN, SHRT_MAX); + intel_crtc->cursor_y = clamp_t(int, y, SHRT_MIN, SHRT_MAX); if (intel_crtc->active) intel_crtc_update_cursor(crtc, intel_crtc->cursor_bo != NULL); -- cgit v1.2.3 From 1fbc0d789d12fec313c91912fc11733fdfbab863 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 29 Oct 2013 12:04:08 +0100 Subject: drm/i915: Fix the PPT fdi lane bifurcate state handling on ivb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Originally I've thought that this is leftover hw state dirt from the BIOS. But after way too much helpless flailing around on my part I've noticed that the actual bug is when we change the state of an already active pipe. For example when we change the fdi lines from 2 to 3 without switching off outputs in-between we'll never see the crucial on->off transition in the ->modeset_global_resources hook the current logic relies on. Patch version 2 got this right by instead also checking whether the pipe is indeed active. But that in turn broke things when pipes have been turned off through dpms since the bifurcate enabling is done in the ->crtc_mode_set callback. To address this issues discussed with Ville in the patch review move the setting of the bifurcate bit into the ->crtc_enable hook. That way we won't wreak havoc with this state when userspace puts all other outputs into dpms off state. This also moves us forward with our overall goal to unify the modeset and dpms on paths (which we need to have to allow runtime pm in the dpms off state). Unfortunately this requires us to move the bifurcate helpers around a bit. Also update the commit message, I've misanalyzed the bug rather badly. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70507 Tested-by: Jan-Michael Brummer Cc: stable@vger.kernel.org Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 95 ++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 47 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 725f0bea1e4c..d78d33f9337d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2327,9 +2327,10 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) FDI_FE_ERRC_ENABLE); } -static bool pipe_has_enabled_pch(struct intel_crtc *intel_crtc) +static bool pipe_has_enabled_pch(struct intel_crtc *crtc) { - return intel_crtc->base.enabled && intel_crtc->config.has_pch_encoder; + return crtc->base.enabled && crtc->active && + crtc->config.has_pch_encoder; } static void ivb_modeset_global_resources(struct drm_device *dev) @@ -2979,6 +2980,48 @@ static void ironlake_pch_transcoder_set_timings(struct intel_crtc *crtc, I915_READ(VSYNCSHIFT(cpu_transcoder))); } +static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t temp; + + temp = I915_READ(SOUTH_CHICKEN1); + if (temp & FDI_BC_BIFURCATION_SELECT) + return; + + WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE); + WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE); + + temp |= FDI_BC_BIFURCATION_SELECT; + DRM_DEBUG_KMS("enabling fdi C rx\n"); + I915_WRITE(SOUTH_CHICKEN1, temp); + POSTING_READ(SOUTH_CHICKEN1); +} + +static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc) +{ + struct drm_device *dev = intel_crtc->base.dev; + struct drm_i915_private *dev_priv = dev->dev_private; + + switch (intel_crtc->pipe) { + case PIPE_A: + break; + case PIPE_B: + if (intel_crtc->config.fdi_lanes > 2) + WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT); + else + cpt_enable_fdi_bc_bifurcation(dev); + + break; + case PIPE_C: + cpt_enable_fdi_bc_bifurcation(dev); + + break; + default: + BUG(); + } +} + /* * Enable PCH resources required for PCH ports: * - PCH PLLs @@ -2997,6 +3040,9 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) assert_pch_transcoder_disabled(dev_priv, pipe); + if (IS_IVYBRIDGE(dev)) + ivybridge_update_fdi_bc_bifurcation(intel_crtc); + /* Write the TU size bits before fdi link training, so that error * detection works. */ I915_WRITE(FDI_RX_TUSIZE1(pipe), @@ -5592,48 +5638,6 @@ static bool ironlake_compute_clocks(struct drm_crtc *crtc, return true; } -static void cpt_enable_fdi_bc_bifurcation(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - uint32_t temp; - - temp = I915_READ(SOUTH_CHICKEN1); - if (temp & FDI_BC_BIFURCATION_SELECT) - return; - - WARN_ON(I915_READ(FDI_RX_CTL(PIPE_B)) & FDI_RX_ENABLE); - WARN_ON(I915_READ(FDI_RX_CTL(PIPE_C)) & FDI_RX_ENABLE); - - temp |= FDI_BC_BIFURCATION_SELECT; - DRM_DEBUG_KMS("enabling fdi C rx\n"); - I915_WRITE(SOUTH_CHICKEN1, temp); - POSTING_READ(SOUTH_CHICKEN1); -} - -static void ivybridge_update_fdi_bc_bifurcation(struct intel_crtc *intel_crtc) -{ - struct drm_device *dev = intel_crtc->base.dev; - struct drm_i915_private *dev_priv = dev->dev_private; - - switch (intel_crtc->pipe) { - case PIPE_A: - break; - case PIPE_B: - if (intel_crtc->config.fdi_lanes > 2) - WARN_ON(I915_READ(SOUTH_CHICKEN1) & FDI_BC_BIFURCATION_SELECT); - else - cpt_enable_fdi_bc_bifurcation(dev); - - break; - case PIPE_C: - cpt_enable_fdi_bc_bifurcation(dev); - - break; - default: - BUG(); - } -} - int ironlake_get_lanes_required(int target_clock, int link_bw, int bpp) { /* @@ -5827,9 +5831,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, &intel_crtc->config.fdi_m_n); } - if (IS_IVYBRIDGE(dev)) - ivybridge_update_fdi_bc_bifurcation(intel_crtc); - ironlake_set_pipeconf(crtc); /* Set up the display plane register */ -- cgit v1.2.3 From ddb642fb0566758ace34384538720db0e24bcd4c Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Mon, 28 Oct 2013 17:20:35 +0200 Subject: drm/i915: rename i915_init_power_well to init_power_domains_init Similarly rename the other related functions in the power domain interface. Higher level driver code calling these functions knows only about power domains, not the underlying power wells which may be different on different platforms. Also these functions really init/cleanup/resume power domains and only through that all related power wells, so rename them accordingly. Note that I left i915_{request,release}_power_well as is, since that really changes the state only of a single power well (and is HSW specific). It should also get a better name once we make it more generic by controlling things through a new audio power domain. v4: - use intel prefix instead of i915 everywhere (Paulo) - use a $prefix_$block_$action format (Daniel) Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 8 ++++---- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/intel_drv.h | 6 +++--- drivers/gpu/drm/i915/intel_pm.c | 10 +++++----- 4 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index bec1fe93cf24..6eecce70fa72 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1314,7 +1314,7 @@ static int i915_load_modeset_init(struct drm_device *dev) if (ret) goto cleanup_gem_stolen; - intel_init_power_well(dev); + intel_power_domains_init_hw(dev); /* Keep VGA alive until i915_disable_vga_mem() */ intel_display_power_get(dev, POWER_DOMAIN_VGA); @@ -1653,7 +1653,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) } if (HAS_POWER_WELL(dev)) - i915_init_power_well(dev); + intel_power_domains_init(dev); if (drm_core_check_feature(dev, DRIVER_MODESET)) { ret = i915_load_modeset_init(dev); @@ -1681,7 +1681,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) out_power_well: if (HAS_POWER_WELL(dev)) - i915_remove_power_well(dev); + intel_power_domains_remove(dev); drm_vblank_cleanup(dev); out_gem_unload: if (dev_priv->mm.inactive_shrinker.scan_objects) @@ -1724,7 +1724,7 @@ int i915_driver_unload(struct drm_device *dev) * the power well is not enabled, so just enable it in case * we're going to unload/reload. */ intel_display_set_init_power(dev, true); - i915_remove_power_well(dev); + intel_power_domains_remove(dev); } i915_teardown_sysfs(dev); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index b764f7b7eb6b..1041644030b7 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -595,7 +595,7 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) mutex_unlock(&dev->struct_mutex); } - intel_init_power_well(dev); + intel_power_domains_init_hw(dev); i915_restore_state(dev); intel_opregion_setup(dev); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index bf4394a144a5..9d2624fd92c2 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -823,15 +823,15 @@ bool intel_fbc_enabled(struct drm_device *dev); void intel_update_fbc(struct drm_device *dev); void intel_gpu_ips_init(struct drm_i915_private *dev_priv); void intel_gpu_ips_teardown(void); -int i915_init_power_well(struct drm_device *dev); -void i915_remove_power_well(struct drm_device *dev); +int intel_power_domains_init(struct drm_device *dev); +void intel_power_domains_remove(struct drm_device *dev); bool intel_display_power_enabled(struct drm_device *dev, enum intel_display_power_domain domain); void intel_display_power_get(struct drm_device *dev, enum intel_display_power_domain domain); void intel_display_power_put(struct drm_device *dev, enum intel_display_power_domain domain); -void intel_init_power_well(struct drm_device *dev); +void intel_power_domains_init_hw(struct drm_device *dev); void intel_set_power_well(struct drm_device *dev, bool enable); void intel_enable_gt_powersave(struct drm_device *dev); void intel_disable_gt_powersave(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 235b39095550..222e47f1b538 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5670,7 +5670,7 @@ void i915_release_power_well(void) } EXPORT_SYMBOL_GPL(i915_release_power_well); -int i915_init_power_well(struct drm_device *dev) +int intel_power_domains_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_power_domains *power_domains = &dev_priv->power_domains; @@ -5685,12 +5685,12 @@ int i915_init_power_well(struct drm_device *dev) return 0; } -void i915_remove_power_well(struct drm_device *dev) +void intel_power_domains_remove(struct drm_device *dev) { hsw_pwr = NULL; } -static void intel_resume_power_well(struct drm_device *dev) +static void intel_power_domains_resume(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct i915_power_domains *power_domains = &dev_priv->power_domains; @@ -5713,7 +5713,7 @@ static void intel_resume_power_well(struct drm_device *dev) * to be enabled, and it will only be disabled if none of the registers is * requesting it to be enabled. */ -void intel_init_power_well(struct drm_device *dev) +void intel_power_domains_init_hw(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -5722,7 +5722,7 @@ void intel_init_power_well(struct drm_device *dev) /* For now, we need the power well to be always enabled. */ intel_display_set_init_power(dev, true); - intel_resume_power_well(dev); + intel_power_domains_resume(dev); /* We're taking over the BIOS, so clear any requests made by it since * the driver is in charge now. */ -- cgit v1.2.3 From 3d3b78c06c827bfc072a11056d7eb70aeb90e449 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Mon, 28 Oct 2013 10:55:49 +0100 Subject: drm: allow DRM_IOCTL_VERSION on render-nodes DRM_IOCTL_VERSION is a reliable way to get the driver-name and version information. It's not related to the interface-version (SET_VERSION ioctl) so we can safely enable it on render-nodes. Note that gbm uses udev-BUSID to load the correct mesa driver. However, the VERSION ioctl should be the more reliable way to do this (in case we add new DRM-bus drivers which have no BUSID or similar). Signed-off-by: David Herrmann Reviewed-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 05ad9ba0a67e..fe58d0833a11 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -61,7 +61,7 @@ static int drm_version(struct drm_device *dev, void *data, /** Ioctl table */ static const struct drm_ioctl_desc drm_ioctls[] = { - DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0), DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0), DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY), -- cgit v1.2.3 From f4adcd247766e5b914f861ed143ff328f869bf80 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 28 Oct 2013 09:24:13 +0100 Subject: drm/i915: handle faked missed interrupts as simulated hangs, too Otherwise QA will report this as a real hang when running igt ZZ_missed_irq. v2: Actually test the right stuff and really shut up the DRM_ERROR output ... Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70747 Tested-by: lu hua Acked-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 1a7dc7754e2f..68936da7c25d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -2258,8 +2258,12 @@ static void i915_hangcheck_elapsed(unsigned long data) if (waitqueue_active(&ring->irq_queue)) { /* Issue a wake-up to catch stuck h/w. */ if (!test_and_set_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings)) { - DRM_ERROR("Hangcheck timer elapsed... %s idle\n", - ring->name); + if (!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(ring))) + DRM_ERROR("Hangcheck timer elapsed... %s idle\n", + ring->name); + else + DRM_INFO("Fake missed irq on %s\n", + ring->name); wake_up_all(&ring->irq_queue); } /* Safeguard against driver failure */ -- cgit v1.2.3 From 94e39e282ecd299b095f37cd0f521d83bd799b14 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 30 Oct 2013 09:28:22 +0000 Subject: drm/i915: Capture batchbuffer state upon GPU hang The bbstate contains useful bits of debugging information such as whether the batch is being read from GTT or PPGTT, or whether it is allowed to execute privileged instructions. v2: Only record BB_STATE for gen4+ Signed-off-by: Chris Wilson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gpu_error.c | 4 +++- drivers/gpu/drm/i915/i915_reg.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 57715c8e59c6..8bc0b3b42183 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -299,6 +299,7 @@ struct drm_i915_error_state { u32 cpu_ring_tail[I915_NUM_RINGS]; u32 error; /* gen6+ */ u32 err_int; /* gen7 */ + u32 bbstate[I915_NUM_RINGS]; u32 instpm[I915_NUM_RINGS]; u32 instps[I915_NUM_RINGS]; u32 extra_instdone[I915_NUM_INSTDONE_REG]; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 5dde81026471..a8bb213da79f 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -249,7 +249,8 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m, err_printf(m, " INSTDONE: 0x%08x\n", error->instdone[ring]); if (ring == RCS && INTEL_INFO(dev)->gen >= 4) err_printf(m, " BBADDR: 0x%08llx\n", error->bbaddr); - + if (INTEL_INFO(dev)->gen >= 4) + err_printf(m, " BB_STATE: 0x%08x\n", error->bbstate[ring]); if (INTEL_INFO(dev)->gen >= 4) err_printf(m, " INSTPS: 0x%08x\n", error->instps[ring]); err_printf(m, " INSTPM: 0x%08x\n", error->instpm[ring]); @@ -725,6 +726,7 @@ static void i915_record_ring_state(struct drm_device *dev, error->instps[ring->id] = I915_READ(RING_INSTPS(ring->mmio_base)); if (ring->id == RCS) error->bbaddr = I915_READ64(BB_ADDR); + error->bbstate[ring->id] = I915_READ(RING_BBSTATE(ring->mmio_base)); } else { error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX); error->ipeir[ring->id] = I915_READ(IPEIR); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 47de41f1d4b4..9785f7d031a4 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -718,6 +718,7 @@ #define NOPID 0x02094 #define HWSTAM 0x02098 #define DMA_FADD_I8XX 0x020d0 +#define RING_BBSTATE(base) ((base)+0x110) #define ERROR_GEN6 0x040a0 #define GEN7_ERR_INT 0x44040 -- cgit v1.2.3 From 3b6c42e82c83da0ea9230c1bbd3390ab4ecf0cb6 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 21 Oct 2013 18:04:35 +0200 Subject: drm/i915: use enum pipe consistently in i915_irq.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Request by Ville in his review of the CRC stuff. This converts everything but ilk_display_irq_handler since that needs a bit more than a simple search&replace to look nice. Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- drivers/gpu/drm/i915/i915_irq.c | 37 +++++++++++++++++++------------------ 2 files changed, 21 insertions(+), 20 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8bc0b3b42183..0a886fd24936 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1884,10 +1884,10 @@ extern void intel_uncore_check_errors(struct drm_device *dev); extern void intel_uncore_fini(struct drm_device *dev); void -i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); +i915_enable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask); void -i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask); +i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask); /* i915_gem.c */ int i915_gem_init_ioctl(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 68936da7c25d..a8a258ed601a 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -442,7 +442,7 @@ done: void -i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) +i915_enable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask) { u32 reg = PIPESTAT(pipe); u32 pipestat = I915_READ(reg) & 0x7fff0000; @@ -459,7 +459,7 @@ i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) } void -i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask) +i915_disable_pipestat(drm_i915_private_t *dev_priv, enum pipe pipe, u32 mask) { u32 reg = PIPESTAT(pipe); u32 pipestat = I915_READ(reg) & 0x7fff0000; @@ -487,9 +487,10 @@ static void i915_enable_asle_pipestat(struct drm_device *dev) spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - i915_enable_pipestat(dev_priv, 1, PIPE_LEGACY_BLC_EVENT_ENABLE); + i915_enable_pipestat(dev_priv, PIPE_B, PIPE_LEGACY_BLC_EVENT_ENABLE); if (INTEL_INFO(dev)->gen >= 4) - i915_enable_pipestat(dev_priv, 0, PIPE_LEGACY_BLC_EVENT_ENABLE); + i915_enable_pipestat(dev_priv, PIPE_A, + PIPE_LEGACY_BLC_EVENT_ENABLE); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); } @@ -1600,7 +1601,7 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir) { struct drm_i915_private *dev_priv = dev->dev_private; - int i; + enum pipe i; if (de_iir & DE_ERR_INT_IVB) ivb_err_int_handler(dev); @@ -1611,7 +1612,7 @@ static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir) if (de_iir & DE_GSE_IVB) intel_opregion_asle_intr(dev); - for (i = 0; i < 3; i++) { + for_each_pipe(i) { if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i))) drm_handle_vblank(dev, i); if (de_iir & (DE_PLANEA_FLIP_DONE_IVB << (5 * i))) { @@ -2040,7 +2041,7 @@ static int valleyview_enable_vblank(struct drm_device *dev, int pipe) spin_lock_irqsave(&dev_priv->irq_lock, irqflags); imr = I915_READ(VLV_IMR); - if (pipe == 0) + if (pipe == PIPE_A) imr &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; else imr &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; @@ -2092,7 +2093,7 @@ static void valleyview_disable_vblank(struct drm_device *dev, int pipe) i915_disable_pipestat(dev_priv, pipe, PIPE_START_VBLANK_INTERRUPT_ENABLE); imr = I915_READ(VLV_IMR); - if (pipe == 0) + if (pipe == PIPE_A) imr |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; else imr |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; @@ -2618,9 +2619,9 @@ static int valleyview_irq_postinstall(struct drm_device *dev) /* Interrupt setup is already guaranteed to be single-threaded, this is * just to make the assert_spin_locked check happy. */ spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - i915_enable_pipestat(dev_priv, 0, pipestat_enable); - i915_enable_pipestat(dev_priv, 0, PIPE_GMBUS_EVENT_ENABLE); - i915_enable_pipestat(dev_priv, 1, pipestat_enable); + i915_enable_pipestat(dev_priv, PIPE_A, pipestat_enable); + i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_EVENT_ENABLE); + i915_enable_pipestat(dev_priv, PIPE_B, pipestat_enable); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); I915_WRITE(VLV_IIR, 0xffffffff); @@ -2735,8 +2736,8 @@ static int i8xx_irq_postinstall(struct drm_device *dev) /* Interrupt setup is already guaranteed to be single-threaded, this is * just to make the assert_spin_locked check happy. */ spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - i915_enable_pipestat(dev_priv, 0, PIPE_CRC_DONE_ENABLE); - i915_enable_pipestat(dev_priv, 1, PIPE_CRC_DONE_ENABLE); + i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_ENABLE); + i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_ENABLE); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); return 0; @@ -2918,8 +2919,8 @@ static int i915_irq_postinstall(struct drm_device *dev) /* Interrupt setup is already guaranteed to be single-threaded, this is * just to make the assert_spin_locked check happy. */ spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - i915_enable_pipestat(dev_priv, 0, PIPE_CRC_DONE_ENABLE); - i915_enable_pipestat(dev_priv, 1, PIPE_CRC_DONE_ENABLE); + i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_ENABLE); + i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_ENABLE); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); return 0; @@ -3134,9 +3135,9 @@ static int i965_irq_postinstall(struct drm_device *dev) /* Interrupt setup is already guaranteed to be single-threaded, this is * just to make the assert_spin_locked check happy. */ spin_lock_irqsave(&dev_priv->irq_lock, irqflags); - i915_enable_pipestat(dev_priv, 0, PIPE_GMBUS_EVENT_ENABLE); - i915_enable_pipestat(dev_priv, 0, PIPE_CRC_DONE_ENABLE); - i915_enable_pipestat(dev_priv, 1, PIPE_CRC_DONE_ENABLE); + i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_EVENT_ENABLE); + i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_ENABLE); + i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_ENABLE); spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); /* -- cgit v1.2.3 From 40da17c29be95acf5543c97c8bc2fbb5991c3e39 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 21 Oct 2013 18:04:36 +0200 Subject: drm/i915: refactor ilk display interrupt handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use a for_each_loop and add the corresponding #defines. - Drop the _ILK postfix on the existing DE_PIPE_VBLANK macro for consistency with everything else. - Also use macros (and add the missing one for plane flips) for the ivb display interrupt handler. Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä [danvet: Drop the useless parens that Ville spotted.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 50 +++++++++++++++++------------------------ drivers/gpu/drm/i915/i915_reg.h | 7 ++++-- 2 files changed, 26 insertions(+), 31 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a8a258ed601a..a228176676b2 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1541,6 +1541,7 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir) static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) { struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe; if (de_iir & DE_AUX_CHANNEL_A) dp_aux_irq_handler(dev); @@ -1548,37 +1549,26 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) if (de_iir & DE_GSE) intel_opregion_asle_intr(dev); - if (de_iir & DE_PIPEA_VBLANK) - drm_handle_vblank(dev, 0); - - if (de_iir & DE_PIPEB_VBLANK) - drm_handle_vblank(dev, 1); - if (de_iir & DE_POISON) DRM_ERROR("Poison interrupt\n"); - if (de_iir & DE_PIPEA_FIFO_UNDERRUN) - if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, false)) - DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n"); - - if (de_iir & DE_PIPEB_FIFO_UNDERRUN) - if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, false)) - DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n"); - - if (de_iir & DE_PIPEA_CRC_DONE) - i9xx_pipe_crc_irq_handler(dev, PIPE_A); + for_each_pipe(pipe) { + if (de_iir & DE_PIPE_VBLANK(pipe)) + drm_handle_vblank(dev, pipe); - if (de_iir & DE_PIPEB_CRC_DONE) - i9xx_pipe_crc_irq_handler(dev, PIPE_B); + if (de_iir & DE_PIPE_FIFO_UNDERRUN(pipe)) + if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, false)) + DRM_DEBUG_DRIVER("Pipe %c FIFO underrun\n", + pipe_name(pipe)); - if (de_iir & DE_PLANEA_FLIP_DONE) { - intel_prepare_page_flip(dev, 0); - intel_finish_page_flip_plane(dev, 0); - } + if (de_iir & DE_PIPE_CRC_DONE(pipe)) + i9xx_pipe_crc_irq_handler(dev, pipe); - if (de_iir & DE_PLANEB_FLIP_DONE) { - intel_prepare_page_flip(dev, 1); - intel_finish_page_flip_plane(dev, 1); + /* plane/pipes map 1:1 on ilk+ */ + if (de_iir & DE_PLANE_FLIP_DONE(pipe)) { + intel_prepare_page_flip(dev, pipe); + intel_finish_page_flip_plane(dev, pipe); + } } /* check event from PCH */ @@ -1613,9 +1603,11 @@ static void ivb_display_irq_handler(struct drm_device *dev, u32 de_iir) intel_opregion_asle_intr(dev); for_each_pipe(i) { - if (de_iir & (DE_PIPEA_VBLANK_IVB << (5 * i))) + if (de_iir & (DE_PIPE_VBLANK_IVB(i))) drm_handle_vblank(dev, i); - if (de_iir & (DE_PLANEA_FLIP_DONE_IVB << (5 * i))) { + + /* plane/pipes map 1:1 on ilk+ */ + if (de_iir & DE_PLANE_FLIP_DONE_IVB(i)) { intel_prepare_page_flip(dev, i); intel_finish_page_flip_plane(dev, i); } @@ -2018,7 +2010,7 @@ static int ironlake_enable_vblank(struct drm_device *dev, int pipe) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; uint32_t bit = (INTEL_INFO(dev)->gen >= 7) ? DE_PIPE_VBLANK_IVB(pipe) : - DE_PIPE_VBLANK_ILK(pipe); + DE_PIPE_VBLANK(pipe); if (!i915_pipe_enabled(dev, pipe)) return -EINVAL; @@ -2076,7 +2068,7 @@ static void ironlake_disable_vblank(struct drm_device *dev, int pipe) drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; unsigned long irqflags; uint32_t bit = (INTEL_INFO(dev)->gen >= 7) ? DE_PIPE_VBLANK_IVB(pipe) : - DE_PIPE_VBLANK_ILK(pipe); + DE_PIPE_VBLANK(pipe); spin_lock_irqsave(&dev_priv->irq_lock, irqflags); ironlake_disable_display_irq(dev_priv, bit); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9785f7d031a4..3591dbb58f7b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3926,6 +3926,7 @@ #define DE_SPRITEA_FLIP_DONE (1 << 28) #define DE_PLANEB_FLIP_DONE (1 << 27) #define DE_PLANEA_FLIP_DONE (1 << 26) +#define DE_PLANE_FLIP_DONE(plane) (1 << (26 + (plane))) #define DE_PCU_EVENT (1 << 25) #define DE_GTT_FAULT (1 << 24) #define DE_POISON (1 << 23) @@ -3942,12 +3943,15 @@ #define DE_PIPEB_CRC_DONE (1 << 10) #define DE_PIPEB_FIFO_UNDERRUN (1 << 8) #define DE_PIPEA_VBLANK (1 << 7) +#define DE_PIPE_VBLANK(pipe) (1 << (7 + 8*(pipe))) #define DE_PIPEA_EVEN_FIELD (1 << 6) #define DE_PIPEA_ODD_FIELD (1 << 5) #define DE_PIPEA_LINE_COMPARE (1 << 4) #define DE_PIPEA_VSYNC (1 << 3) #define DE_PIPEA_CRC_DONE (1 << 2) +#define DE_PIPE_CRC_DONE(pipe) (1 << (2 + 8*(pipe))) #define DE_PIPEA_FIFO_UNDERRUN (1 << 0) +#define DE_PIPE_FIFO_UNDERRUN(pipe) (1 << (8*(pipe))) /* More Ivybridge lolz */ #define DE_ERR_INT_IVB (1<<30) @@ -3963,9 +3967,8 @@ #define DE_PIPEB_VBLANK_IVB (1<<5) #define DE_SPRITEA_FLIP_DONE_IVB (1<<4) #define DE_PLANEA_FLIP_DONE_IVB (1<<3) +#define DE_PLANE_FLIP_DONE_IVB(plane) (1<< (3 + 5*(plane))) #define DE_PIPEA_VBLANK_IVB (1<<0) - -#define DE_PIPE_VBLANK_ILK(pipe) (1 << ((pipe * 8) + 7)) #define DE_PIPE_VBLANK_IVB(pipe) (1 << (pipe * 5)) #define VLV_MASTER_IER 0x4400c /* Gunit master IER */ -- cgit v1.2.3 From 8a5e6aeb30ecaf8f11a99c0d008c8935cd6fba9f Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Wed, 30 Oct 2013 19:50:26 -0200 Subject: drm/i915: turn the eDP VDD on for any i2c transactions If the eDP output is disabled, then we try to use /dev/i2c-X file to do i2c transations, we get a WARN from intel_dp_check_edp() saying we're trying to do AUX communication with the panel off. So this commit reorganizes the code so we enable the VDD at intel_dp_i2c_aux_ch() instead of just the callers inside i915.ko. This fixes the i2c subtest from the pc8 test of intel-gpu-tools on machines that have eDP panels. Signed-off-by: Paulo Zanoni Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index cea8624a0c1a..2dbdcd103ead 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -623,6 +623,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, int reply_bytes; int ret; + ironlake_edp_panel_vdd_on(intel_dp); intel_dp_check_edp(intel_dp); /* Set up the command byte */ if (mode & MODE_I2C_READ) @@ -665,7 +666,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, reply, reply_bytes); if (ret < 0) { DRM_DEBUG_KMS("aux_ch failed %d\n", ret); - return ret; + goto out; } switch (reply[0] & AUX_NATIVE_REPLY_MASK) { @@ -676,7 +677,8 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, break; case AUX_NATIVE_REPLY_NACK: DRM_DEBUG_KMS("aux_ch native nack\n"); - return -EREMOTEIO; + ret = -EREMOTEIO; + goto out; case AUX_NATIVE_REPLY_DEFER: /* * For now, just give more slack to branch devices. We @@ -694,7 +696,8 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, default: DRM_ERROR("aux_ch invalid native reply 0x%02x\n", reply[0]); - return -EREMOTEIO; + ret = -EREMOTEIO; + goto out; } switch (reply[0] & AUX_I2C_REPLY_MASK) { @@ -702,22 +705,29 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, if (mode == MODE_I2C_READ) { *read_byte = reply[1]; } - return reply_bytes - 1; + ret = reply_bytes - 1; + goto out; case AUX_I2C_REPLY_NACK: DRM_DEBUG_KMS("aux_i2c nack\n"); - return -EREMOTEIO; + ret = -EREMOTEIO; + goto out; case AUX_I2C_REPLY_DEFER: DRM_DEBUG_KMS("aux_i2c defer\n"); udelay(100); break; default: DRM_ERROR("aux_i2c invalid reply 0x%02x\n", reply[0]); - return -EREMOTEIO; + ret = -EREMOTEIO; + goto out; } } DRM_ERROR("too many retries, giving up\n"); - return -EREMOTEIO; + ret = -EREMOTEIO; + +out: + ironlake_edp_panel_vdd_off(intel_dp, false); + return ret; } static int @@ -739,9 +749,7 @@ intel_dp_i2c_init(struct intel_dp *intel_dp, intel_dp->adapter.algo_data = &intel_dp->algo; intel_dp->adapter.dev.parent = &intel_connector->base.kdev; - ironlake_edp_panel_vdd_on(intel_dp); ret = i2c_dp_aux_add_bus(&intel_dp->adapter); - ironlake_edp_panel_vdd_off(intel_dp, false); return ret; } @@ -3478,7 +3486,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, &power_seq); - ironlake_edp_panel_vdd_on(intel_dp); edid = drm_get_edid(connector, &intel_dp->adapter); if (edid) { if (drm_add_edid_modes(connector, edid)) { @@ -3510,8 +3517,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; } - ironlake_edp_panel_vdd_off(intel_dp, false); - intel_panel_init(&intel_connector->panel, fixed_mode); intel_panel_setup_backlight(connector); -- cgit v1.2.3 From b0665d57cfaf6dac5435fc5dcf0fd656b04eb8cc Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Wed, 30 Oct 2013 19:50:27 -0200 Subject: drm/i915: reduce eDP VDD message verbose Now we only print messages when we actually enable VDD and when we actually disable VDD. The changes in the last commit triggered a big number of messages while the driver was being initialized, and I thought we were toggling things on/off too many times, but that was not really true: we were just being too verbose. Signed-off-by: Paulo Zanoni Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 2dbdcd103ead..b91dc7457b4b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1077,17 +1077,16 @@ void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp) if (!is_edp(intel_dp)) return; - DRM_DEBUG_KMS("Turn eDP VDD on\n"); WARN(intel_dp->want_panel_vdd, "eDP VDD already requested on\n"); intel_dp->want_panel_vdd = true; - if (ironlake_edp_have_panel_vdd(intel_dp)) { - DRM_DEBUG_KMS("eDP VDD already on\n"); + if (ironlake_edp_have_panel_vdd(intel_dp)) return; - } + + DRM_DEBUG_KMS("Turning eDP VDD on\n"); if (!ironlake_edp_have_panel_power(intel_dp)) ironlake_wait_panel_power_cycle(intel_dp); @@ -1121,6 +1120,8 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp) WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) { + DRM_DEBUG_KMS("Turning eDP VDD off\n"); + pp = ironlake_get_pp_control(intel_dp); pp &= ~EDP_FORCE_VDD; @@ -1153,7 +1154,6 @@ void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync) if (!is_edp(intel_dp)) return; - DRM_DEBUG_KMS("Turn eDP VDD off %d\n", intel_dp->want_panel_vdd); WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on"); intel_dp->want_panel_vdd = false; -- cgit v1.2.3 From 93d1f99734296699c3194a17be28cf5e32991199 Mon Sep 17 00:00:00 2001 From: Chon Ming Lee Date: Wed, 30 Oct 2013 10:05:19 +0800 Subject: drm/i915/vlv: Fix typo in the DPIO register define. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Incorrect definition DPIO_TX3_SWING_CTL4. From Ville's review: "Based on the specs, the typo meant that HDMI B ended up using "incorrect" de-emphasis for the TMDS data lanes." Signed-off-by: Chon Ming Lee Reviewed-by: Ville Syrjälä [danvet: Add comment from Ville's review about the impact.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3591dbb58f7b..3dfcac7ef3c4 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -444,7 +444,7 @@ #define _DPIO_TX3_SWING_CTL4_A 0x690 #define _DPIO_TX3_SWING_CTL4_B 0x2a90 -#define DPIO_TX3_SWING_CTL4(pipe) _PIPE(pipe, _DPIO_TX_SWING_CTL4_A, \ +#define DPIO_TX3_SWING_CTL4(pipe) _PIPE(pipe, _DPIO_TX3_SWING_CTL4_A, \ _DPIO_TX3_SWING_CTL4_B) /* -- cgit v1.2.3 From 1ad577ac6e2c870d6a68f214c9208882eb8d8f00 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 29 Oct 2013 19:09:50 +0200 Subject: drm/i915: add back checking for i915_disable_power_well In commit 6efdf354ddb186c6604d1692075421e8d2c740e9 Author: Imre Deak Date: Wed Oct 16 17:25:52 2013 +0300 the check for i915_disable_power_well flag was removed by overlook, so add it back now. Reported-by: Paulo Zanoni Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 222e47f1b538..97009ee387c1 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5592,7 +5592,7 @@ static void __intel_power_well_put(struct drm_device *dev, struct i915_power_well *power_well) { WARN_ON(!power_well->count); - if (!--power_well->count) + if (!--power_well->count && i915_disable_power_well) __intel_set_power_well(dev, false); } -- cgit v1.2.3 From 9f08ef59a6f71249de8b4e8a26c27075b9e99f9c Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Thu, 31 Oct 2013 12:44:21 -0200 Subject: drm/i915: use the correct register when turning VDD off That explains why I was seeing 2 consecutive "Turning eDP VDD off" messages. Regression introduced by: commit bf13e81b904a37d94d83dd6c3b53a147719a3ead Author: Jani Nikula Date: Fri Sep 6 07:40:05 2013 +0300 drm/i915: add support for per-pipe power sequencing on vlv Signed-off-by: Paulo Zanoni Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index b91dc7457b4b..68357777e74f 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1125,8 +1125,8 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp) pp = ironlake_get_pp_control(intel_dp); pp &= ~EDP_FORCE_VDD; - pp_stat_reg = _pp_ctrl_reg(intel_dp); - pp_ctrl_reg = _pp_stat_reg(intel_dp); + pp_ctrl_reg = _pp_ctrl_reg(intel_dp); + pp_stat_reg = _pp_stat_reg(intel_dp); I915_WRITE(pp_ctrl_reg, pp); POSTING_READ(pp_ctrl_reg); -- cgit v1.2.3 From 0baab4fd6de4beb3393e173b392038d01da54bec Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 31 Oct 2013 15:28:23 -0700 Subject: i915: fix compiler warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The last i915 drm update brought with it this annoying warning drivers/gpu/drm/i915/intel_crt.c: In function ‘intel_crt_get_config’: drivers/gpu/drm/i915/intel_crt.c:110:21: warning: unused variable ‘dev’ [-Wunused-variable] struct drm_device *dev = encoder->base.dev; ^ introduced by commit 7195a50b5c7e ("drm/i915: Add HSW CRT output readout support"). Remove the offending pointless variable. Signed-off-by: Linus Torvalds --- drivers/gpu/drm/i915/intel_crt.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index db59bb9fbe23..10d1de5bce6f 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -107,8 +107,6 @@ static unsigned int intel_crt_get_flags(struct intel_encoder *encoder) static void intel_crt_get_config(struct intel_encoder *encoder, struct intel_crtc_config *pipe_config) { - struct drm_device *dev = encoder->base.dev; - pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder); } -- cgit v1.2.3 From 46a19188171179ba2d84e6de803ce7b1c54da474 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 1 Nov 2013 10:50:20 +0100 Subject: drm/i916: add "auto" pipe CRC source On gmch platforms the normal pipe source CRC registers don't work for DP and TV encoders. And on newer platforms the single pipe CRC has been replaced by a set of CRC at different stages in the platform. Now most of our userspace tests don't care one bit about the exact CRC, they simply want something that reflects any changes on the screen. Hence add a new auto target for platform agnostic tests to use. v2: Pass back the adjusted source so that it can be shown in debugfs. v3: I seem to be unable to get a stable CRC for DP ports. So let's just disable them for now when using the auto mode. Note that testcases need to be restructured so that they can dynamically skip connectors. They also first need to set up the desired mode configuration, since otherwise the auto mode won't do the right thing. v4: Don't leak the modeset mutex on error paths. v5: Spelling fix for the i9xx auto_source function. Cc: Damien Lespiau Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 91 +++++++++++++++++++++++++++++++------ drivers/gpu/drm/i915/i915_drv.h | 1 + 2 files changed, 77 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 5c45e9e598de..7c29a8827177 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1936,6 +1936,7 @@ static const char * const pipe_crc_sources[] = { "DP-B", "DP-C", "DP-D", + "auto", }; static const char *pipe_crc_source_name(enum intel_pipe_crc_source source) @@ -1964,10 +1965,13 @@ static int display_crc_ctl_open(struct inode *inode, struct file *file) return single_open(file, display_crc_ctl_show, dev); } -static int i8xx_pipe_crc_ctl_reg(enum intel_pipe_crc_source source, +static int i8xx_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, uint32_t *val) { - switch (source) { + if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) + *source = INTEL_PIPE_CRC_SOURCE_PIPE; + + switch (*source) { case INTEL_PIPE_CRC_SOURCE_PIPE: *val = PIPE_CRC_ENABLE | PIPE_CRC_INCLUDE_BORDER_I8XX; break; @@ -1981,10 +1985,54 @@ static int i8xx_pipe_crc_ctl_reg(enum intel_pipe_crc_source source, return 0; } -static int vlv_pipe_crc_ctl_reg(enum intel_pipe_crc_source source, +static int i9xx_pipe_crc_auto_source(struct drm_device *dev, enum pipe pipe, + enum intel_pipe_crc_source *source) +{ + struct intel_encoder *encoder; + struct intel_crtc *crtc; + int ret = 0; + + *source = INTEL_PIPE_CRC_SOURCE_PIPE; + + mutex_lock(&dev->mode_config.mutex); + list_for_each_entry(encoder, &dev->mode_config.encoder_list, + base.head) { + if (!encoder->base.crtc) + continue; + + crtc = to_intel_crtc(encoder->base.crtc); + + if (crtc->pipe != pipe) + continue; + + switch (encoder->type) { + case INTEL_OUTPUT_TVOUT: + *source = INTEL_PIPE_CRC_SOURCE_TV; + break; + case INTEL_OUTPUT_DISPLAYPORT: + case INTEL_OUTPUT_EDP: + /* We can't get stable CRCs for DP ports somehow. */ + ret = -ENODEV; + break; + } + } + mutex_unlock(&dev->mode_config.mutex); + + return ret; +} + +static int vlv_pipe_crc_ctl_reg(struct drm_device *dev, + enum pipe pipe, + enum intel_pipe_crc_source *source, uint32_t *val) { - switch (source) { + if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) { + int ret = i9xx_pipe_crc_auto_source(dev, pipe, source); + if (ret) + return ret; + } + + switch (*source) { case INTEL_PIPE_CRC_SOURCE_PIPE: *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_VLV; break; @@ -2005,10 +2053,17 @@ static int vlv_pipe_crc_ctl_reg(enum intel_pipe_crc_source source, } static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev, - enum intel_pipe_crc_source source, + enum pipe pipe, + enum intel_pipe_crc_source *source, uint32_t *val) { - switch (source) { + if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) { + int ret = i9xx_pipe_crc_auto_source(dev, pipe, source); + if (ret) + return ret; + } + + switch (*source) { case INTEL_PIPE_CRC_SOURCE_PIPE: *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_I9XX; break; @@ -2042,10 +2097,13 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev, return 0; } -static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source source, +static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, uint32_t *val) { - switch (source) { + if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) + *source = INTEL_PIPE_CRC_SOURCE_PIPE; + + switch (*source) { case INTEL_PIPE_CRC_SOURCE_PLANE1: *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PRIMARY_ILK; break; @@ -2065,10 +2123,13 @@ static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source source, return 0; } -static int ivb_pipe_crc_ctl_reg(enum intel_pipe_crc_source source, +static int ivb_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, uint32_t *val) { - switch (source) { + if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) + *source = INTEL_PIPE_CRC_SOURCE_PF; + + switch (*source) { case INTEL_PIPE_CRC_SOURCE_PLANE1: *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PRIMARY_IVB; break; @@ -2104,15 +2165,15 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, return -EINVAL; if (IS_GEN2(dev)) - ret = i8xx_pipe_crc_ctl_reg(source, &val); + ret = i8xx_pipe_crc_ctl_reg(&source, &val); else if (INTEL_INFO(dev)->gen < 5) - ret = i9xx_pipe_crc_ctl_reg(dev, source, &val); + ret = i9xx_pipe_crc_ctl_reg(dev, pipe, &source, &val); else if (IS_VALLEYVIEW(dev)) - ret = vlv_pipe_crc_ctl_reg(source, &val); + ret = vlv_pipe_crc_ctl_reg(dev,pipe, &source, &val); else if (IS_GEN5(dev) || IS_GEN6(dev)) - ret = ilk_pipe_crc_ctl_reg(source, &val); + ret = ilk_pipe_crc_ctl_reg(&source, &val); else - ret = ivb_pipe_crc_ctl_reg(source, &val); + ret = ivb_pipe_crc_ctl_reg(&source, &val); if (ret != 0) return ret; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0a886fd24936..f2324bc46800 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1251,6 +1251,7 @@ enum intel_pipe_crc_source { INTEL_PIPE_CRC_SOURCE_DP_B, INTEL_PIPE_CRC_SOURCE_DP_C, INTEL_PIPE_CRC_SOURCE_DP_D, + INTEL_PIPE_CRC_SOURCE_AUTO, INTEL_PIPE_CRC_SOURCE_MAX, }; -- cgit v1.2.3 From 8409360381ebaaab82c7ab502665a29423fcdfc2 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 1 Nov 2013 10:50:21 +0100 Subject: drm/i915: scramble reset support for DP port CRC on g4x We need to reset the DP scrambler on every vsync to get stable CRCs. And since we can't use the normal pipe CRC on DP ports on g4x we really need them to be able to test modesetting issues on (e)DP outputs. Note that the DC balance reset is for SDVO port CRCs so we don't strictly need it. But better safe than sorry (and it's a nice template in case we ever want to grab port CRCs for e.g. audio checking). v2: Apply the suggestions from Damien's review. Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 52 +++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_reg.h | 8 ++++++ 2 files changed, 60 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 7c29a8827177..881251611512 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2057,6 +2057,9 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev, enum intel_pipe_crc_source *source, uint32_t *val) { + struct drm_i915_private *dev_priv = dev->dev_private; + bool need_stable_symbols = false; + if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) { int ret = i9xx_pipe_crc_auto_source(dev, pipe, source); if (ret) @@ -2076,16 +2079,19 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev, if (!IS_G4X(dev)) return -EINVAL; *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_B_G4X; + need_stable_symbols = true; break; case INTEL_PIPE_CRC_SOURCE_DP_C: if (!IS_G4X(dev)) return -EINVAL; *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_C_G4X; + need_stable_symbols = true; break; case INTEL_PIPE_CRC_SOURCE_DP_D: if (!IS_G4X(dev)) return -EINVAL; *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_D_G4X; + need_stable_symbols = true; break; case INTEL_PIPE_CRC_SOURCE_NONE: *val = 0; @@ -2094,9 +2100,52 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev, return -EINVAL; } + /* + * When the pipe CRC tap point is after the transcoders we need + * to tweak symbol-level features to produce a deterministic series of + * symbols for a given frame. We need to reset those features only once + * a frame (instead of every nth symbol): + * - DC-balance: used to ensure a better clock recovery from the data + * link (SDVO) + * - DisplayPort scrambling: used for EMI reduction + */ + if (need_stable_symbols) { + uint32_t tmp = I915_READ(PORT_DFT2_G4X); + + WARN_ON(!IS_G4X(dev)); + + I915_WRITE(PORT_DFT_I9XX, + I915_READ(PORT_DFT_I9XX) | DC_BALANCE_RESET); + + if (pipe == PIPE_A) + tmp |= PIPE_A_SCRAMBLE_RESET; + else + tmp |= PIPE_B_SCRAMBLE_RESET; + + I915_WRITE(PORT_DFT2_G4X, tmp); + } + return 0; } +static void g4x_undo_pipe_scramble_reset(struct drm_device *dev, + enum pipe pipe) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t tmp = I915_READ(PORT_DFT2_G4X); + + if (pipe == PIPE_A) + tmp &= ~PIPE_A_SCRAMBLE_RESET; + else + tmp &= ~PIPE_B_SCRAMBLE_RESET; + I915_WRITE(PORT_DFT2_G4X, tmp); + + if (!(tmp & PIPE_SCRAMBLE_RESET_MASK)) { + I915_WRITE(PORT_DFT_I9XX, + I915_READ(PORT_DFT_I9XX) & ~DC_BALANCE_RESET); + } +} + static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source *source, uint32_t *val) { @@ -2215,6 +2264,9 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, spin_unlock_irq(&pipe_crc->lock); kfree(entries); + + if (IS_G4X(dev)) + g4x_undo_pipe_scramble_reset(dev, pipe); } return 0; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3dfcac7ef3c4..4328e3bd63b2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2150,6 +2150,14 @@ #define PCH_HDMIC 0xe1150 #define PCH_HDMID 0xe1160 +#define PORT_DFT_I9XX 0x61150 +#define DC_BALANCE_RESET (1 << 25) +#define PORT_DFT2_G4X 0x61154 +#define DC_BALANCE_RESET_VLV (1 << 31) +#define PIPE_SCRAMBLE_RESET_MASK (0x3 << 0) +#define PIPE_B_SCRAMBLE_RESET (1 << 1) +#define PIPE_A_SCRAMBLE_RESET (1 << 0) + /* Gen 3 SDVO bits: */ #define SDVO_ENABLE (1 << 31) #define SDVO_PIPE_SEL(pipe) ((pipe) << 30) -- cgit v1.2.3 From 8d2f24ca1f19e1e5ca6b941a3f6488f9ccae5390 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 1 Nov 2013 10:50:22 +0100 Subject: drm/i915: scramble reset support for DP port CRC on vlv They've moved the DC balance reset bit around. Again I don't think we need it, but better safe than sorry and maybe HDMI port CRC will prove useful for checking infoframes or hdmi audio. v2: Apply the suggestions from Damien's review. Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 881251611512..82c58eb1aa66 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2026,6 +2026,9 @@ static int vlv_pipe_crc_ctl_reg(struct drm_device *dev, enum intel_pipe_crc_source *source, uint32_t *val) { + struct drm_i915_private *dev_priv = dev->dev_private; + bool need_stable_symbols = false; + if (*source == INTEL_PIPE_CRC_SOURCE_AUTO) { int ret = i9xx_pipe_crc_auto_source(dev, pipe, source); if (ret) @@ -2038,9 +2041,11 @@ static int vlv_pipe_crc_ctl_reg(struct drm_device *dev, break; case INTEL_PIPE_CRC_SOURCE_DP_B: *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_B_VLV; + need_stable_symbols = true; break; case INTEL_PIPE_CRC_SOURCE_DP_C: *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_DP_C_VLV; + need_stable_symbols = true; break; case INTEL_PIPE_CRC_SOURCE_NONE: *val = 0; @@ -2049,6 +2054,29 @@ static int vlv_pipe_crc_ctl_reg(struct drm_device *dev, return -EINVAL; } + /* + * When the pipe CRC tap point is after the transcoders we need + * to tweak symbol-level features to produce a deterministic series of + * symbols for a given frame. We need to reset those features only once + * a frame (instead of every nth symbol): + * - DC-balance: used to ensure a better clock recovery from the data + * link (SDVO) + * - DisplayPort scrambling: used for EMI reduction + */ + if (need_stable_symbols) { + uint32_t tmp = I915_READ(PORT_DFT2_G4X); + + WARN_ON(!IS_G4X(dev)); + + tmp |= DC_BALANCE_RESET_VLV; + if (pipe == PIPE_A) + tmp |= PIPE_A_SCRAMBLE_RESET; + else + tmp |= PIPE_B_SCRAMBLE_RESET; + + I915_WRITE(PORT_DFT2_G4X, tmp); + } + return 0; } @@ -2128,6 +2156,22 @@ static int i9xx_pipe_crc_ctl_reg(struct drm_device *dev, return 0; } +static void vlv_undo_pipe_scramble_reset(struct drm_device *dev, + enum pipe pipe) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t tmp = I915_READ(PORT_DFT2_G4X); + + if (pipe == PIPE_A) + tmp &= ~PIPE_A_SCRAMBLE_RESET; + else + tmp &= ~PIPE_B_SCRAMBLE_RESET; + if (!(tmp & PIPE_SCRAMBLE_RESET_MASK)) + tmp &= ~DC_BALANCE_RESET_VLV; + I915_WRITE(PORT_DFT2_G4X, tmp); + +} + static void g4x_undo_pipe_scramble_reset(struct drm_device *dev, enum pipe pipe) { @@ -2267,6 +2311,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, if (IS_G4X(dev)) g4x_undo_pipe_scramble_reset(dev, pipe); + else if (IS_VALLEYVIEW(dev)) + vlv_undo_pipe_scramble_reset(dev, pipe); } return 0; -- cgit v1.2.3 From 26756809583c1023dcbc896261105c1e289d262b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 1 Nov 2013 10:50:23 +0100 Subject: drm/i915: Enable DP port CRC for the "auto" source on g4x/vlv Now that DP port CRCs are stable, we can use it for generic CRC tests. Yay, the auto CRC source should now work everywhere! Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 82c58eb1aa66..7008aacfc3c9 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1990,6 +1990,7 @@ static int i9xx_pipe_crc_auto_source(struct drm_device *dev, enum pipe pipe, { struct intel_encoder *encoder; struct intel_crtc *crtc; + struct intel_digital_port *dig_port; int ret = 0; *source = INTEL_PIPE_CRC_SOURCE_PIPE; @@ -2011,8 +2012,22 @@ static int i9xx_pipe_crc_auto_source(struct drm_device *dev, enum pipe pipe, break; case INTEL_OUTPUT_DISPLAYPORT: case INTEL_OUTPUT_EDP: - /* We can't get stable CRCs for DP ports somehow. */ - ret = -ENODEV; + dig_port = enc_to_dig_port(&encoder->base); + switch (dig_port->port) { + case PORT_B: + *source = INTEL_PIPE_CRC_SOURCE_DP_B; + break; + case PORT_C: + *source = INTEL_PIPE_CRC_SOURCE_DP_C; + break; + case PORT_D: + *source = INTEL_PIPE_CRC_SOURCE_DP_D; + break; + default: + WARN(1, "nonexisting DP port %c\n", + port_name(dig_port->port)); + break; + } break; } } -- cgit v1.2.3 From 9d1cb9147dbe45f6e94dc796518ecf67cb64b359 Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Fri, 1 Nov 2013 13:32:08 -0200 Subject: drm/i915: avoid unclaimed registers when capturing the error state Even though we only check for unclaimed registers while we're writing registers, if we read a bad register we'll still trigger a CPU error interrupt, and we'll print an "Unclaimed register" DRM_ERROR due to that. To avoid this error, just avoid touching power domains that are not enabled. Use kzalloc so we're sure all the disabled domains will be zeroed on the error state file. We already print the information that is enough to discover if the power well is enabled on the error state file, so this should not be a problem. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=69747 Signed-off-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c69a5b844f5a..40a8f59fa418 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11130,7 +11130,7 @@ intel_display_capture_error_state(struct drm_device *dev) if (INTEL_INFO(dev)->num_pipes == 0) return NULL; - error = kmalloc(sizeof(*error), GFP_ATOMIC); + error = kzalloc(sizeof(*error), GFP_ATOMIC); if (error == NULL) return NULL; @@ -11138,6 +11138,9 @@ intel_display_capture_error_state(struct drm_device *dev) error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER); for_each_pipe(i) { + if (!intel_display_power_enabled(dev, POWER_DOMAIN_PIPE(i))) + continue; + if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) { error->cursor[i].control = I915_READ(CURCNTR(i)); error->cursor[i].position = I915_READ(CURPOS(i)); @@ -11171,6 +11174,10 @@ intel_display_capture_error_state(struct drm_device *dev) for (i = 0; i < error->num_transcoders; i++) { enum transcoder cpu_transcoder = transcoders[i]; + if (!intel_display_power_enabled(dev, + POWER_DOMAIN_TRANSCODER(cpu_transcoder))) + continue; + error->transcoder[i].cpu_transcoder = cpu_transcoder; error->transcoder[i].conf = I915_READ(PIPECONF(cpu_transcoder)); @@ -11182,12 +11189,6 @@ intel_display_capture_error_state(struct drm_device *dev) error->transcoder[i].vsync = I915_READ(VSYNC(cpu_transcoder)); } - /* In the code above we read the registers without checking if the power - * well was on, so here we have to clear the FPGA_DBG_RM_NOCLAIM bit to - * prevent the next I915_WRITE from detecting it and printing an error - * message. */ - intel_uncore_clear_errors(dev); - return error; } -- cgit v1.2.3 From 48f34e10169dbb3dd7a19af64e328492b7f54af4 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 8 Oct 2013 12:25:42 +0200 Subject: drm/i915/dvo: call ->mode_set callback only when the port is running The ns2501 controller seems to need the dpll and dvo port to accept the timing update commands. Quick testing on my x30 here seems to indicate that other dvo controllers don't mind. So let's move the ->mode_set callback to a place where we have the port up and running already. Tested-by: Chris Wilson Tested-by: Thomas Richter Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dvo.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 1b64145c669a..3c7736546856 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -173,11 +173,16 @@ static void intel_enable_dvo(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; struct intel_dvo *intel_dvo = enc_to_dvo(encoder); + struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); u32 dvo_reg = intel_dvo->dev.dvo_reg; u32 temp = I915_READ(dvo_reg); I915_WRITE(dvo_reg, temp | DVO_ENABLE); I915_READ(dvo_reg); + intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, + &crtc->config.requested_mode, + &crtc->config.adjusted_mode); + intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true); } @@ -186,6 +191,7 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode) { struct intel_dvo *intel_dvo = intel_attached_dvo(connector); struct drm_crtc *crtc; + struct intel_crtc_config *config; /* dvo supports only 2 dpms states. */ if (mode != DRM_MODE_DPMS_ON) @@ -206,10 +212,16 @@ static void intel_dvo_dpms(struct drm_connector *connector, int mode) /* We call connector dpms manually below in case pipe dpms doesn't * change due to cloning. */ if (mode == DRM_MODE_DPMS_ON) { + config = &to_intel_crtc(crtc)->config; + intel_dvo->base.connectors_active = true; intel_crtc_update_dpms(crtc); + intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, + &config->requested_mode, + &config->adjusted_mode); + intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, true); } else { intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, false); @@ -296,10 +308,6 @@ static void intel_dvo_mode_set(struct intel_encoder *encoder) break; } - intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, - &crtc->config.requested_mode, - adjusted_mode); - /* Save the data order, since I don't know what it should be set to. */ dvo_val = I915_READ(dvo_reg) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG); -- cgit v1.2.3 From 9ca2fe731b3f12afbc97cf0050dfa4184bd2234c Mon Sep 17 00:00:00 2001 From: Mengdong Lin Date: Fri, 1 Nov 2013 00:17:03 -0400 Subject: drm/i915/vlv: enable HDA display audio for Valleyview2 This patch defines HD-Audio configuration registers and enables display audio from HDA controller for Valleyview2. v2: fix missing offset VLV_DISPLAY_BASE v3: rename patch from 'enable HDMI audio' to 'enable HDA display audio', since it's for both HDMI and DP audio v4: use enc_to_dig_port() to get port number, instead of using Haswell specific function intel_ddi_get_encoder_port() Signed-off-by: Mengdong Lin Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_reg.h | 18 ++++++++++++++++++ drivers/gpu/drm/i915/intel_display.c | 23 ++++++++++++++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3f303ba995c5..98d7263fba67 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4948,6 +4948,18 @@ CPT_AUD_CNTL_ST_B) #define CPT_AUD_CNTRL_ST2 0xE50C0 +#define VLV_HDMIW_HDMIEDID_A (VLV_DISPLAY_BASE + 0x62050) +#define VLV_HDMIW_HDMIEDID_B (VLV_DISPLAY_BASE + 0x62150) +#define VLV_HDMIW_HDMIEDID(pipe) _PIPE(pipe, \ + VLV_HDMIW_HDMIEDID_A, \ + VLV_HDMIW_HDMIEDID_B) +#define VLV_AUD_CNTL_ST_A (VLV_DISPLAY_BASE + 0x620B4) +#define VLV_AUD_CNTL_ST_B (VLV_DISPLAY_BASE + 0x621B4) +#define VLV_AUD_CNTL_ST(pipe) _PIPE(pipe, \ + VLV_AUD_CNTL_ST_A, \ + VLV_AUD_CNTL_ST_B) +#define VLV_AUD_CNTL_ST2 (VLV_DISPLAY_BASE + 0x620C0) + /* These are the 4 32-bit write offset registers for each stream * output buffer. It determines the offset from the * 3DSTATE_SO_BUFFERs that the next streamed vertex output goes to. @@ -4964,6 +4976,12 @@ #define CPT_AUD_CFG(pipe) _PIPE(pipe, \ CPT_AUD_CONFIG_A, \ CPT_AUD_CONFIG_B) +#define VLV_AUD_CONFIG_A (VLV_DISPLAY_BASE + 0x62000) +#define VLV_AUD_CONFIG_B (VLV_DISPLAY_BASE + 0x62100) +#define VLV_AUD_CFG(pipe) _PIPE(pipe, \ + VLV_AUD_CONFIG_A, \ + VLV_AUD_CONFIG_B) + #define AUD_CONFIG_N_VALUE_INDEX (1 << 29) #define AUD_CONFIG_N_PROG_ENABLE (1 << 28) #define AUD_CONFIG_UPPER_N_SHIFT 20 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f34252d134b6..e31a740e1663 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6989,6 +6989,11 @@ static void ironlake_write_eld(struct drm_connector *connector, aud_config = IBX_AUD_CFG(pipe); aud_cntl_st = IBX_AUD_CNTL_ST(pipe); aud_cntrl_st2 = IBX_AUD_CNTL_ST2; + } else if (IS_VALLEYVIEW(connector->dev)) { + hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); + aud_config = VLV_AUD_CFG(pipe); + aud_cntl_st = VLV_AUD_CNTL_ST(pipe); + aud_cntrl_st2 = VLV_AUD_CNTL_ST2; } else { hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe); aud_config = CPT_AUD_CFG(pipe); @@ -6998,8 +7003,19 @@ static void ironlake_write_eld(struct drm_connector *connector, DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(pipe)); - i = I915_READ(aud_cntl_st); - i = (i >> 29) & DIP_PORT_SEL_MASK; /* DIP_Port_Select, 0x1 = PortB */ + if (IS_VALLEYVIEW(connector->dev)) { + struct intel_encoder *intel_encoder; + struct intel_digital_port *intel_dig_port; + + intel_encoder = intel_attached_encoder(connector); + intel_dig_port = enc_to_dig_port(&intel_encoder->base); + i = intel_dig_port->port; + } else { + i = I915_READ(aud_cntl_st); + i = (i >> 29) & DIP_PORT_SEL_MASK; + /* DIP_Port_Select, 0x1 = PortB */ + } + if (!i) { DRM_DEBUG_DRIVER("Audio directed to unknown port\n"); /* operate blindly on all ports */ @@ -10317,7 +10333,8 @@ static void intel_init_display(struct drm_device *dev) } } else if (IS_G4X(dev)) { dev_priv->display.write_eld = g4x_write_eld; - } + } else if (IS_VALLEYVIEW(dev)) + dev_priv->display.write_eld = ironlake_write_eld; /* Default just returns -ENODEV to indicate unsupported */ dev_priv->display.queue_flip = intel_default_queue_flip; -- cgit v1.2.3 From 78eb06c394da002aa7e059e84aa6aa58880b4bba Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 1 Nov 2013 20:32:07 +0200 Subject: drm/i915: Give names to the VBT child device type bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ville Syrjälä Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_bios.c | 10 +++++----- drivers/gpu/drm/i915/intel_bios.h | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index e29bcae1ef81..6dd622d733b9 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -624,11 +624,11 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, aux_channel = child->raw[25]; - is_dvi = child->common.device_type & (1 << 4); - is_dp = child->common.device_type & (1 << 2); - is_crt = child->common.device_type & (1 << 0); - is_hdmi = is_dvi && (child->common.device_type & (1 << 11)) == 0; - is_edp = is_dp && (child->common.device_type & (1 << 12)); + is_dvi = child->common.device_type & DEVICE_TYPE_TMDS_DVI_SIGNALING; + is_dp = child->common.device_type & DEVICE_TYPE_DISPLAYPORT_OUTPUT; + is_crt = child->common.device_type & DEVICE_TYPE_ANALOG_OUTPUT; + is_hdmi = is_dvi && (child->common.device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT) == 0; + is_edp = is_dp && (child->common.device_type & DEVICE_TYPE_INTERNAL_CONNECTOR); info->supports_dvi = is_dvi; info->supports_hdmi = is_hdmi; diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 287cc5a21c2e..f439c147368a 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -638,6 +638,22 @@ int intel_parse_bios(struct drm_device *dev); #define DEVICE_TYPE_DP 0x68C6 #define DEVICE_TYPE_eDP 0x78C6 +#define DEVICE_TYPE_CLASS_EXTENSION (1 << 15) +#define DEVICE_TYPE_POWER_MANAGEMENT (1 << 14) +#define DEVICE_TYPE_HOTPLUG_SIGNALING (1 << 13) +#define DEVICE_TYPE_INTERNAL_CONNECTOR (1 << 12) +#define DEVICE_TYPE_NOT_HDMI_OUTPUT (1 << 11) +#define DEVICE_TYPE_MIPI_OUTPUT (1 << 10) +#define DEVICE_TYPE_COMPOSITE_OUTPUT (1 << 9) +#define DEVICE_TYPE_DUAL_CHANNEL (1 << 8) +#define DEVICE_TYPE_HIGH_SPEED_LINK (1 << 6) +#define DEVICE_TYPE_LVDS_SINGALING (1 << 5) +#define DEVICE_TYPE_TMDS_DVI_SIGNALING (1 << 4) +#define DEVICE_TYPE_VIDEO_SIGNALING (1 << 3) +#define DEVICE_TYPE_DISPLAYPORT_OUTPUT (1 << 2) +#define DEVICE_TYPE_DIGITAL_OUTPUT (1 << 1) +#define DEVICE_TYPE_ANALOG_OUTPUT (1 << 0) + /* define the DVO port for HDMI output type */ #define DVO_B 1 #define DVO_C 2 -- cgit v1.2.3 From f02586dfedf1dfae4f5ff7eb1990a2c4c56e1425 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 1 Nov 2013 20:32:08 +0200 Subject: drm/i915: Make intel_dp_is_edp() less specific MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the bits in the VBT child device type have some speciifc meaning, so looking for an exact match isn't always the right thing. On some VLVs for example the device type for eDP panels is 0x1806. If we mask out the bits that could concievably change between different eDP panels, we are left with the set of bits that should still tell us if the port is eDP or not. v2: Use the named bits for VBT child device type Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=71051 Tested-by: Robert Hooker Signed-off-by: Ville Syrjälä Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_bios.h | 18 ++++++++++++++++++ drivers/gpu/drm/i915/intel_dp.c | 3 ++- 2 files changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index f439c147368a..f580a2b0ddd3 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -654,6 +654,24 @@ int intel_parse_bios(struct drm_device *dev); #define DEVICE_TYPE_DIGITAL_OUTPUT (1 << 1) #define DEVICE_TYPE_ANALOG_OUTPUT (1 << 0) +/* + * Bits we care about when checking for DEVICE_TYPE_eDP + * Depending on the system, the other bits may or may not + * be set for eDP outputs. + */ +#define DEVICE_TYPE_eDP_BITS \ + (DEVICE_TYPE_INTERNAL_CONNECTOR | \ + DEVICE_TYPE_NOT_HDMI_OUTPUT | \ + DEVICE_TYPE_MIPI_OUTPUT | \ + DEVICE_TYPE_COMPOSITE_OUTPUT | \ + DEVICE_TYPE_DUAL_CHANNEL | \ + DEVICE_TYPE_LVDS_SINGALING | \ + DEVICE_TYPE_TMDS_DVI_SIGNALING | \ + DEVICE_TYPE_VIDEO_SIGNALING | \ + DEVICE_TYPE_DISPLAYPORT_OUTPUT | \ + DEVICE_TYPE_DIGITAL_OUTPUT | \ + DEVICE_TYPE_ANALOG_OUTPUT) + /* define the DVO port for HDMI output type */ #define DVO_B 1 #define DVO_C 2 diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 7619eae35b25..d58fbb6b5ffd 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -3284,7 +3284,8 @@ bool intel_dpd_is_edp(struct drm_device *dev) p_child = dev_priv->vbt.child_dev + i; if (p_child->common.dvo_port == PORT_IDPD && - p_child->common.device_type == DEVICE_TYPE_eDP) + (p_child->common.device_type & DEVICE_TYPE_eDP_BITS) == + (DEVICE_TYPE_eDP & DEVICE_TYPE_eDP_BITS)) return true; } return false; -- cgit v1.2.3 From 7b5562d401c760814110385baa574480e4ce12f9 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Tue, 5 Nov 2013 15:48:01 -0800 Subject: drm/i915/vlv: use PIPE_START_VBLANK interrupts on VLV MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a mismatch between our vblank enable code and our IRQ handler. Also, since vblank start events come in before page flips reliably, it also fixes the kms_flip plain-flip test on my BYT system. Spotted-by: Ville Syrjälä Signed-off-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a228176676b2..1b3f060e891c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1353,7 +1353,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); for_each_pipe(pipe) { - if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) + if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) drm_handle_vblank(dev, pipe); if (pipe_stats[pipe] & PLANE_FLIPDONE_INT_STATUS_VLV) { -- cgit v1.2.3 From 91a60f20712179e56b7a6c3d332a5f6f9a54aa11 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 31 Oct 2013 18:55:48 +0200 Subject: drm/i915: move opregion asle request handling to a work queue Doing this has been long overdue anyway, but now we really need it in preparation for per connector backlight handling. Signed-off-by: Jani Nikula Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_opregion.c | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b12d942ab09c..8b37b3531c27 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -242,6 +242,7 @@ struct intel_opregion { struct opregion_asle __iomem *asle; void __iomem *vbt; u32 __iomem *lid_state; + struct work_struct asle_work; }; #define OPREGION_SIZE (8*1024) diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index b82050c96f3e..892d520175d8 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -486,9 +486,13 @@ static u32 asle_isct_state(struct drm_device *dev) return ASLC_ISCT_STATE_FAILED; } -void intel_opregion_asle_intr(struct drm_device *dev) +static void asle_work(struct work_struct *work) { - struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_opregion *opregion = + container_of(work, struct intel_opregion, asle_work); + struct drm_i915_private *dev_priv = + container_of(opregion, struct drm_i915_private, opregion); + struct drm_device *dev = dev_priv->dev; struct opregion_asle __iomem *asle = dev_priv->opregion.asle; u32 aslc_stat = 0; u32 aslc_req; @@ -535,6 +539,14 @@ void intel_opregion_asle_intr(struct drm_device *dev) iowrite32(aslc_stat, &asle->aslc); } +void intel_opregion_asle_intr(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + if (dev_priv->opregion.asle) + schedule_work(&dev_priv->opregion.asle_work); +} + #define ACPI_EV_DISPLAY_SWITCH (1<<0) #define ACPI_EV_LID (1<<1) #define ACPI_EV_DOCK (1<<2) @@ -735,6 +747,8 @@ void intel_opregion_fini(struct drm_device *dev) if (opregion->asle) iowrite32(ASLE_ARDY_NOT_READY, &opregion->asle->ardy); + cancel_work_sync(&dev_priv->opregion.asle_work); + if (opregion->acpi) { iowrite32(0, &opregion->acpi->drdy); @@ -828,6 +842,8 @@ int intel_opregion_setup(struct drm_device *dev) return -ENOTSUPP; } + INIT_WORK(&opregion->asle_work, asle_work); + base = acpi_os_ioremap(asls, OPREGION_SIZE); if (!base) return -ENOMEM; -- cgit v1.2.3 From 752aa88a1e784c22d514db3b440e49427b58259e Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 31 Oct 2013 18:55:49 +0200 Subject: drm/i915: make backlight functions take a connector On VLV/BYT, backlight controls a per-pipe, so when adjusting the backlight we need to pass the correct info. So make the externally visible backlight functions take a connector argument, which can be used internally to figure out the pipe backlight to adjust. v2: make connector pipe lookup check for NULL crtc (Jani) fixup connector check in ASLE code (Jani) v3: make sure we take the mode config lock around lookups (Daniel) v4: fix double unlock in panel_get_brightness (Daniel) v5: push ASLE work into a work queue (Daniel) v6: separate ASLE work to a prep patch, rebase (Jani) Signed-off-by: Jesse Barnes Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_display.c | 12 +++++ drivers/gpu/drm/i915/intel_dp.c | 5 +- drivers/gpu/drm/i915/intel_drv.h | 8 ++-- drivers/gpu/drm/i915/intel_lvds.c | 9 ++-- drivers/gpu/drm/i915/intel_opregion.c | 38 +++++++++++++++- drivers/gpu/drm/i915/intel_panel.c | 86 ++++++++++++++++++++++++----------- 7 files changed, 122 insertions(+), 37 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8b37b3531c27..b2023d7c1d6b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -54,6 +54,7 @@ #define DRIVER_DATE "20080730" enum pipe { + INVALID_PIPE = -1, PIPE_A = 0, PIPE_B, PIPE_C, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e31a740e1663..73f036bddb6f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9874,6 +9874,18 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) drm_crtc_helper_add(&intel_crtc->base, &intel_helper_funcs); } +enum pipe intel_get_pipe_from_connector(struct intel_connector *connector) +{ + struct drm_encoder *encoder = connector->base.encoder; + + WARN_ON(!mutex_is_locked(&connector->base.dev->mode_config.mutex)); + + if (!encoder) + return INVALID_PIPE; + + return to_intel_crtc(encoder->crtc)->pipe; +} + int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, struct drm_file *file) { diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index d58fbb6b5ffd..4609eedf52aa 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1249,7 +1249,6 @@ void ironlake_edp_backlight_on(struct intel_dp *intel_dp) struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = dev->dev_private; - int pipe = to_intel_crtc(intel_dig_port->base.base.crtc)->pipe; u32 pp; u32 pp_ctrl_reg; @@ -1272,7 +1271,7 @@ void ironlake_edp_backlight_on(struct intel_dp *intel_dp) I915_WRITE(pp_ctrl_reg, pp); POSTING_READ(pp_ctrl_reg); - intel_panel_enable_backlight(dev, pipe); + intel_panel_enable_backlight(intel_dp->attached_connector); } void ironlake_edp_backlight_off(struct intel_dp *intel_dp) @@ -1285,7 +1284,7 @@ void ironlake_edp_backlight_off(struct intel_dp *intel_dp) if (!is_edp(intel_dp)) return; - intel_panel_disable_backlight(dev); + intel_panel_disable_backlight(intel_dp->attached_connector); DRM_DEBUG_KMS("\n"); pp = ironlake_get_pp_control(intel_dp); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 9d2624fd92c2..1e49aa8f5377 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -630,6 +630,7 @@ void intel_connector_attach_encoder(struct intel_connector *connector, struct drm_encoder *intel_best_encoder(struct drm_connector *connector); struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, struct drm_crtc *crtc); +enum pipe intel_get_pipe_from_connector(struct intel_connector *connector); int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, struct drm_file *file_priv); enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv, @@ -802,10 +803,11 @@ void intel_pch_panel_fitting(struct intel_crtc *crtc, void intel_gmch_panel_fitting(struct intel_crtc *crtc, struct intel_crtc_config *pipe_config, int fitting_mode); -void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max); +void intel_panel_set_backlight(struct intel_connector *connector, u32 level, + u32 max); int intel_panel_setup_backlight(struct drm_connector *connector); -void intel_panel_enable_backlight(struct drm_device *dev, enum pipe pipe); -void intel_panel_disable_backlight(struct drm_device *dev); +void intel_panel_enable_backlight(struct intel_connector *connector); +void intel_panel_disable_backlight(struct intel_connector *connector); void intel_panel_destroy_backlight(struct drm_device *dev); enum drm_connector_status intel_panel_detect(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index b0ef55833087..c3b4da7895ed 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -206,7 +206,8 @@ static void intel_enable_lvds(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); - struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); + struct intel_connector *intel_connector = + &lvds_encoder->attached_connector->base; struct drm_i915_private *dev_priv = dev->dev_private; u32 ctl_reg, stat_reg; @@ -225,13 +226,15 @@ static void intel_enable_lvds(struct intel_encoder *encoder) if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000)) DRM_ERROR("timed out waiting for panel to power on\n"); - intel_panel_enable_backlight(dev, intel_crtc->pipe); + intel_panel_enable_backlight(intel_connector); } static void intel_disable_lvds(struct intel_encoder *encoder) { struct drm_device *dev = encoder->base.dev; struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); + struct intel_connector *intel_connector = + &lvds_encoder->attached_connector->base; struct drm_i915_private *dev_priv = dev->dev_private; u32 ctl_reg, stat_reg; @@ -243,7 +246,7 @@ static void intel_disable_lvds(struct intel_encoder *encoder) stat_reg = PP_STATUS; } - intel_panel_disable_backlight(dev); + intel_panel_disable_backlight(intel_connector); I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON); if (wait_for((I915_READ(stat_reg) & PP_ON) == 0, 1000)) diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 892d520175d8..91b68dca0641 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -396,7 +396,13 @@ int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state) static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) { struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_encoder *encoder; + struct drm_connector *connector; + struct intel_connector *intel_connector = NULL; + struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[0]; struct opregion_asle __iomem *asle = dev_priv->opregion.asle; + u32 ret = 0; + bool found = false; DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp); @@ -407,11 +413,39 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) if (bclp > 255) return ASLC_BACKLIGHT_FAILED; + mutex_lock(&dev->mode_config.mutex); + /* + * Could match the OpRegion connector here instead, but we'd also need + * to verify the connector could handle a backlight call. + */ + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) + if (encoder->crtc == crtc) { + found = true; + break; + } + + if (!found) { + ret = ASLC_BACKLIGHT_FAILED; + goto out; + } + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) + if (connector->encoder == encoder) + intel_connector = to_intel_connector(connector); + + if (!intel_connector) { + ret = ASLC_BACKLIGHT_FAILED; + goto out; + } + DRM_DEBUG_KMS("updating opregion backlight %d/255\n", bclp); - intel_panel_set_backlight(dev, bclp, 255); + intel_panel_set_backlight(intel_connector, bclp, 255); iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv); - return 0; +out: + mutex_unlock(&dev->mode_config.mutex); + + return ret; } static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index de1518614827..17ddcb00bd26 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -341,7 +341,7 @@ static int is_backlight_combination_mode(struct drm_device *dev) /* XXX: query mode clock or hardware clock and program max PWM appropriately * when it's 0. */ -static u32 i915_read_blc_pwm_ctl(struct drm_device *dev) +static u32 i915_read_blc_pwm_ctl(struct drm_device *dev, enum pipe pipe) { struct drm_i915_private *dev_priv = dev->dev_private; u32 val; @@ -380,11 +380,12 @@ static u32 i915_read_blc_pwm_ctl(struct drm_device *dev) return val; } -static u32 intel_panel_get_max_backlight(struct drm_device *dev) +static u32 intel_panel_get_max_backlight(struct drm_device *dev, + enum pipe pipe) { u32 max; - max = i915_read_blc_pwm_ctl(dev); + max = i915_read_blc_pwm_ctl(dev, pipe); if (HAS_PCH_SPLIT(dev)) { max >>= 16; @@ -410,7 +411,8 @@ MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " "to dri-devel@lists.freedesktop.org, if your machine needs it. " "It will then be included in an upcoming module version."); module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600); -static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val) +static u32 intel_panel_compute_brightness(struct drm_device *dev, + enum pipe pipe, u32 val) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -419,7 +421,7 @@ static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val) if (i915_panel_invert_brightness > 0 || dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { - u32 max = intel_panel_get_max_backlight(dev); + u32 max = intel_panel_get_max_backlight(dev, pipe); if (max) return max - val; } @@ -427,7 +429,8 @@ static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val) return val; } -static u32 intel_panel_get_backlight(struct drm_device *dev) +static u32 intel_panel_get_backlight(struct drm_device *dev, + enum pipe pipe) { struct drm_i915_private *dev_priv = dev->dev_private; u32 val; @@ -450,7 +453,7 @@ static u32 intel_panel_get_backlight(struct drm_device *dev) } } - val = intel_panel_compute_brightness(dev, val); + val = intel_panel_compute_brightness(dev, pipe, val); spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); @@ -466,19 +469,19 @@ static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level) } static void intel_panel_actually_set_backlight(struct drm_device *dev, - u32 level) + enum pipe pipe, u32 level) { struct drm_i915_private *dev_priv = dev->dev_private; u32 tmp; DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); - level = intel_panel_compute_brightness(dev, level); + level = intel_panel_compute_brightness(dev, pipe, level); if (HAS_PCH_SPLIT(dev)) return intel_pch_panel_set_backlight(dev, level); if (is_backlight_combination_mode(dev)) { - u32 max = intel_panel_get_max_backlight(dev); + u32 max = intel_panel_get_max_backlight(dev, pipe); u8 lbpc; /* we're screwed, but keep behaviour backwards compatible */ @@ -498,15 +501,21 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, } /* set backlight brightness to level in range [0..max] */ -void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max) +void intel_panel_set_backlight(struct intel_connector *connector, u32 level, + u32 max) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe = intel_get_pipe_from_connector(connector); u32 freq; unsigned long flags; + if (pipe == INVALID_PIPE) + return; + spin_lock_irqsave(&dev_priv->backlight.lock, flags); - freq = intel_panel_get_max_backlight(dev); + freq = intel_panel_get_max_backlight(dev, pipe); if (!freq) { /* we are screwed, bail out */ goto out; @@ -523,16 +532,21 @@ void intel_panel_set_backlight(struct drm_device *dev, u32 level, u32 max) dev_priv->backlight.device->props.brightness = level; if (dev_priv->backlight.enabled) - intel_panel_actually_set_backlight(dev, level); + intel_panel_actually_set_backlight(dev, pipe, level); out: spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); } -void intel_panel_disable_backlight(struct drm_device *dev) +void intel_panel_disable_backlight(struct intel_connector *connector) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe = intel_get_pipe_from_connector(connector); unsigned long flags; + if (pipe == INVALID_PIPE) + return; + /* * Do not disable backlight on the vgaswitcheroo path. When switching * away from i915, the other client may depend on i915 to handle the @@ -547,7 +561,7 @@ void intel_panel_disable_backlight(struct drm_device *dev) spin_lock_irqsave(&dev_priv->backlight.lock, flags); dev_priv->backlight.enabled = false; - intel_panel_actually_set_backlight(dev, 0); + intel_panel_actually_set_backlight(dev, pipe, 0); if (INTEL_INFO(dev)->gen >= 4) { uint32_t reg, tmp; @@ -566,20 +580,25 @@ void intel_panel_disable_backlight(struct drm_device *dev) spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); } -void intel_panel_enable_backlight(struct drm_device *dev, - enum pipe pipe) +void intel_panel_enable_backlight(struct intel_connector *connector) { + struct drm_device *dev = connector->base.dev; struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe = intel_get_pipe_from_connector(connector); enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, pipe); unsigned long flags; + if (pipe == INVALID_PIPE) + return; + DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); spin_lock_irqsave(&dev_priv->backlight.lock, flags); if (dev_priv->backlight.level == 0) { - dev_priv->backlight.level = intel_panel_get_max_backlight(dev); + dev_priv->backlight.level = intel_panel_get_max_backlight(dev, + pipe); if (dev_priv->backlight.device) dev_priv->backlight.device->props.brightness = dev_priv->backlight.level; @@ -629,7 +648,8 @@ set_level: * registers are set. */ dev_priv->backlight.enabled = true; - intel_panel_actually_set_backlight(dev, dev_priv->backlight.level); + intel_panel_actually_set_backlight(dev, pipe, + dev_priv->backlight.level); spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); } @@ -652,7 +672,7 @@ static void intel_panel_init_backlight(struct drm_device *dev) intel_panel_init_backlight_regs(dev); - dev_priv->backlight.level = intel_panel_get_backlight(dev); + dev_priv->backlight.level = intel_panel_get_backlight(dev, 0); dev_priv->backlight.enabled = dev_priv->backlight.level != 0; } @@ -681,18 +701,31 @@ intel_panel_detect(struct drm_device *dev) #if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE) static int intel_panel_update_status(struct backlight_device *bd) { - struct drm_device *dev = bl_get_data(bd); + struct intel_connector *connector = bl_get_data(bd); + struct drm_device *dev = connector->base.dev; + + mutex_lock(&dev->mode_config.mutex); DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n", bd->props.brightness, bd->props.max_brightness); - intel_panel_set_backlight(dev, bd->props.brightness, + intel_panel_set_backlight(connector, bd->props.brightness, bd->props.max_brightness); + mutex_unlock(&dev->mode_config.mutex); return 0; } static int intel_panel_get_brightness(struct backlight_device *bd) { - struct drm_device *dev = bl_get_data(bd); - return intel_panel_get_backlight(dev); + struct intel_connector *connector = bl_get_data(bd); + struct drm_device *dev = connector->base.dev; + enum pipe pipe; + + mutex_lock(&dev->mode_config.mutex); + pipe = intel_get_pipe_from_connector(connector); + mutex_unlock(&dev->mode_config.mutex); + if (pipe == INVALID_PIPE) + return 0; + + return intel_panel_get_backlight(connector->base.dev, pipe); } static const struct backlight_ops intel_panel_bl_ops = { @@ -717,7 +750,7 @@ int intel_panel_setup_backlight(struct drm_connector *connector) props.brightness = dev_priv->backlight.level; spin_lock_irqsave(&dev_priv->backlight.lock, flags); - props.max_brightness = intel_panel_get_max_backlight(dev); + props.max_brightness = intel_panel_get_max_backlight(dev, 0); spin_unlock_irqrestore(&dev_priv->backlight.lock, flags); if (props.max_brightness == 0) { @@ -726,7 +759,8 @@ int intel_panel_setup_backlight(struct drm_connector *connector) } dev_priv->backlight.device = backlight_device_register("intel_backlight", - &connector->kdev, dev, + &connector->kdev, + to_intel_connector(connector), &intel_panel_bl_ops, &props); if (IS_ERR(dev_priv->backlight.device)) { -- cgit v1.2.3 From 07bf139b906013ecef0c5e0441564d1ae10e974a Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 31 Oct 2013 18:55:50 +0200 Subject: drm/i915/vlv: use per-pipe backlight controls v2 With the connector and pipe passed around, we can now set the backlight on the right pipe on VLV/BYT. v2: drop combination mode check for VLV (Jani) add save/restore code for VLV backlight regs (Jani) check for existing modulation freq when initializing backlight regs (Jani) Signed-off-by: Jesse Barnes Signed-off-by: Jani Nikula Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=67245 Tested-by: Joe Konno Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 3 ++ drivers/gpu/drm/i915/i915_reg.h | 15 +++++++++ drivers/gpu/drm/i915/i915_suspend.c | 29 ++++++++++++++++ drivers/gpu/drm/i915/intel_panel.c | 67 ++++++++++++++++++++++++++++++------- 4 files changed, 102 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b2023d7c1d6b..b0dd4ea8133f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -745,6 +745,9 @@ struct i915_suspend_saved_registers { u32 saveBLC_HIST_CTL; u32 saveBLC_PWM_CTL; u32 saveBLC_PWM_CTL2; + u32 saveBLC_HIST_CTL_B; + u32 saveBLC_PWM_CTL_B; + u32 saveBLC_PWM_CTL2_B; u32 saveBLC_CPU_PWM_CTL; u32 saveBLC_CPU_PWM_CTL2; u32 saveFPB0; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 98d7263fba67..04896da9001c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2395,6 +2395,21 @@ #define PFIT_AUTO_RATIOS (dev_priv->info->display_mmio_offset + 0x61238) +#define _VLV_BLC_PWM_CTL2_A (dev_priv->info->display_mmio_offset + 0x61250) +#define _VLV_BLC_PWM_CTL2_B (dev_priv->info->display_mmio_offset + 0x61350) +#define VLV_BLC_PWM_CTL2(pipe) _PIPE(pipe, _VLV_BLC_PWM_CTL2_A, \ + _VLV_BLC_PWM_CTL2_B) + +#define _VLV_BLC_PWM_CTL_A (dev_priv->info->display_mmio_offset + 0x61254) +#define _VLV_BLC_PWM_CTL_B (dev_priv->info->display_mmio_offset + 0x61354) +#define VLV_BLC_PWM_CTL(pipe) _PIPE(pipe, _VLV_BLC_PWM_CTL_A, \ + _VLV_BLC_PWM_CTL_B) + +#define _VLV_BLC_HIST_CTL_A (dev_priv->info->display_mmio_offset + 0x61260) +#define _VLV_BLC_HIST_CTL_B (dev_priv->info->display_mmio_offset + 0x61360) +#define VLV_BLC_HIST_CTL(pipe) _PIPE(pipe, _VLV_BLC_HIST_CTL_A, \ + _VLV_BLC_HIST_CTL_B) + /* Backlight control */ #define BLC_PWM_CTL2 (dev_priv->info->display_mmio_offset + 0x61250) /* 965+ only */ #define BLM_PWM_ENABLE (1 << 31) diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index a088f1f46bdb..98790c7cccb1 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -214,6 +214,22 @@ static void i915_save_display(struct drm_device *dev) dev_priv->regfile.saveBLC_CPU_PWM_CTL2 = I915_READ(BLC_PWM_CPU_CTL2); if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) dev_priv->regfile.saveLVDS = I915_READ(PCH_LVDS); + } else if (IS_VALLEYVIEW(dev)) { + dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL); + dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); + + dev_priv->regfile.saveBLC_PWM_CTL = + I915_READ(VLV_BLC_PWM_CTL(PIPE_A)); + dev_priv->regfile.saveBLC_HIST_CTL = + I915_READ(VLV_BLC_HIST_CTL(PIPE_A)); + dev_priv->regfile.saveBLC_PWM_CTL2 = + I915_READ(VLV_BLC_PWM_CTL2(PIPE_A)); + dev_priv->regfile.saveBLC_PWM_CTL_B = + I915_READ(VLV_BLC_PWM_CTL(PIPE_B)); + dev_priv->regfile.saveBLC_HIST_CTL_B = + I915_READ(VLV_BLC_HIST_CTL(PIPE_B)); + dev_priv->regfile.saveBLC_PWM_CTL2_B = + I915_READ(VLV_BLC_PWM_CTL2(PIPE_B)); } else { dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL); dev_priv->regfile.savePFIT_PGM_RATIOS = I915_READ(PFIT_PGM_RATIOS); @@ -302,6 +318,19 @@ static void i915_restore_display(struct drm_device *dev) I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL); I915_WRITE(RSTDBYCTL, dev_priv->regfile.saveMCHBAR_RENDER_STANDBY); + } else if (IS_VALLEYVIEW(dev)) { + I915_WRITE(VLV_BLC_PWM_CTL(PIPE_A), + dev_priv->regfile.saveBLC_PWM_CTL); + I915_WRITE(VLV_BLC_HIST_CTL(PIPE_A), + dev_priv->regfile.saveBLC_HIST_CTL); + I915_WRITE(VLV_BLC_PWM_CTL2(PIPE_A), + dev_priv->regfile.saveBLC_PWM_CTL2); + I915_WRITE(VLV_BLC_PWM_CTL(PIPE_B), + dev_priv->regfile.saveBLC_PWM_CTL); + I915_WRITE(VLV_BLC_HIST_CTL(PIPE_B), + dev_priv->regfile.saveBLC_HIST_CTL); + I915_WRITE(VLV_BLC_PWM_CTL2(PIPE_B), + dev_priv->regfile.saveBLC_PWM_CTL2); } else { I915_WRITE(PFIT_PGM_RATIOS, dev_priv->regfile.savePFIT_PGM_RATIOS); I915_WRITE(BLC_PWM_CTL, dev_priv->regfile.saveBLC_PWM_CTL); diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 17ddcb00bd26..cad41ac330e8 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -358,6 +358,21 @@ static u32 i915_read_blc_pwm_ctl(struct drm_device *dev, enum pipe pipe) val = dev_priv->regfile.saveBLC_PWM_CTL2; I915_WRITE(BLC_PWM_PCH_CTL2, val); } + } else if (IS_VALLEYVIEW(dev)) { + val = I915_READ(VLV_BLC_PWM_CTL(pipe)); + if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { + dev_priv->regfile.saveBLC_PWM_CTL = val; + dev_priv->regfile.saveBLC_PWM_CTL2 = + I915_READ(VLV_BLC_PWM_CTL2(pipe)); + } else if (val == 0) { + val = dev_priv->regfile.saveBLC_PWM_CTL; + I915_WRITE(VLV_BLC_PWM_CTL(pipe), val); + I915_WRITE(VLV_BLC_PWM_CTL2(pipe), + dev_priv->regfile.saveBLC_PWM_CTL2); + } + + if (!val) + val = 0x0f42ffff; } else { val = I915_READ(BLC_PWM_CTL); if (dev_priv->regfile.saveBLC_PWM_CTL == 0) { @@ -372,9 +387,6 @@ static u32 i915_read_blc_pwm_ctl(struct drm_device *dev, enum pipe pipe) I915_WRITE(BLC_PWM_CTL2, dev_priv->regfile.saveBLC_PWM_CTL2); } - - if (IS_VALLEYVIEW(dev) && !val) - val = 0x0f42ffff; } return val; @@ -435,13 +447,19 @@ static u32 intel_panel_get_backlight(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; u32 val; unsigned long flags; + int reg; spin_lock_irqsave(&dev_priv->backlight.lock, flags); if (HAS_PCH_SPLIT(dev)) { val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; } else { - val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; + if (IS_VALLEYVIEW(dev)) + reg = VLV_BLC_PWM_CTL(pipe); + else + reg = BLC_PWM_CTL; + + val = I915_READ(reg) & BACKLIGHT_DUTY_CYCLE_MASK; if (INTEL_INFO(dev)->gen < 4) val >>= 1; @@ -473,6 +491,7 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, { struct drm_i915_private *dev_priv = dev->dev_private; u32 tmp; + int reg; DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); level = intel_panel_compute_brightness(dev, pipe, level); @@ -493,11 +512,16 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc); } - tmp = I915_READ(BLC_PWM_CTL); + if (IS_VALLEYVIEW(dev)) + reg = VLV_BLC_PWM_CTL(pipe); + else + reg = BLC_PWM_CTL; + + tmp = I915_READ(reg); if (INTEL_INFO(dev)->gen < 4) level <<= 1; tmp &= ~BACKLIGHT_DUTY_CYCLE_MASK; - I915_WRITE(BLC_PWM_CTL, tmp | level); + I915_WRITE(reg, tmp | level); } /* set backlight brightness to level in range [0..max] */ @@ -566,7 +590,12 @@ void intel_panel_disable_backlight(struct intel_connector *connector) if (INTEL_INFO(dev)->gen >= 4) { uint32_t reg, tmp; - reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; + if (HAS_PCH_SPLIT(dev)) + reg = BLC_PWM_CPU_CTL2; + else if (IS_VALLEYVIEW(dev)) + reg = VLV_BLC_PWM_CTL2(pipe); + else + reg = BLC_PWM_CTL2; I915_WRITE(reg, I915_READ(reg) & ~BLM_PWM_ENABLE); @@ -607,8 +636,12 @@ void intel_panel_enable_backlight(struct intel_connector *connector) if (INTEL_INFO(dev)->gen >= 4) { uint32_t reg, tmp; - reg = HAS_PCH_SPLIT(dev) ? BLC_PWM_CPU_CTL2 : BLC_PWM_CTL2; - + if (HAS_PCH_SPLIT(dev)) + reg = BLC_PWM_CPU_CTL2; + else if (IS_VALLEYVIEW(dev)) + reg = VLV_BLC_PWM_CTL2(pipe); + else + reg = BLC_PWM_CTL2; tmp = I915_READ(reg); @@ -660,9 +693,19 @@ static void intel_panel_init_backlight_regs(struct drm_device *dev) struct drm_i915_private *dev_priv = dev->dev_private; if (IS_VALLEYVIEW(dev)) { - u32 cur_val = I915_READ(BLC_PWM_CTL) & - BACKLIGHT_DUTY_CYCLE_MASK; - I915_WRITE(BLC_PWM_CTL, (0xf42 << 16) | cur_val); + enum pipe pipe; + + for_each_pipe(pipe) { + u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe)); + + /* Skip if the modulation freq is already set */ + if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK) + continue; + + cur_val &= BACKLIGHT_DUTY_CYCLE_MASK; + I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) | + cur_val); + } } } -- cgit v1.2.3