Skip to content

Commit

Permalink
drm/i915: add opregion function to notify bios of encoder enable/disable
Browse files Browse the repository at this point in the history
The bios interface seems messy, and it's hard to tell what the bios
really wants. At first, only add support for DDI based machines (hsw+),
and see how it turns out.

The spec says to notify prior to power down and after power up. It is
unclear whether it makes a difference.

v2:
 - squash notification function and callers patches together (Daniel)
 - move callers to haswell_crtc_{enable,disable} (Daniel)
 - rename notification function (Chris)

v3:
 - separate notification function and callers again, as it's not clear
   whether the display power state notification is the right thing to do
   after all

v4: per Paulo's review:
 - drop LVDS
 - WARN on unsupported encoder types

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Jani Nikula authored and Daniel Vetter committed Sep 4, 2013
1 parent 20f4dbe commit 9c4b0a6
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 0 deletions.
8 changes: 8 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -2189,15 +2189,23 @@ static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
extern void intel_i2c_reset(struct drm_device *dev);

/* intel_opregion.c */
struct intel_encoder;
extern int intel_opregion_setup(struct drm_device *dev);
#ifdef CONFIG_ACPI
extern void intel_opregion_init(struct drm_device *dev);
extern void intel_opregion_fini(struct drm_device *dev);
extern void intel_opregion_asle_intr(struct drm_device *dev);
extern int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
bool enable);
#else
static inline void intel_opregion_init(struct drm_device *dev) { return; }
static inline void intel_opregion_fini(struct drm_device *dev) { return; }
static inline void intel_opregion_asle_intr(struct drm_device *dev) { return; }
static inline int
intel_opregion_notify_encoder(struct intel_encoder *intel_encoder, bool enable)
{
return 0;
}
#endif

/* intel_acpi.c */
Expand Down
51 changes: 51 additions & 0 deletions drivers/gpu/drm/i915/intel_opregion.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,57 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
#undef C
}

#define DISPLAY_TYPE_CRT 0
#define DISPLAY_TYPE_TV 1
#define DISPLAY_TYPE_EXTERNAL_FLAT_PANEL 2
#define DISPLAY_TYPE_INTERNAL_FLAT_PANEL 3

int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
bool enable)
{
struct drm_device *dev = intel_encoder->base.dev;
u32 parm = 0;
u32 type = 0;
u32 port;

/* don't care about old stuff for now */
if (!HAS_DDI(dev))
return 0;

port = intel_ddi_get_encoder_port(intel_encoder);
if (port == PORT_E) {
port = 0;
} else {
parm |= 1 << port;
port++;
}

if (!enable)
parm |= 4 << 8;

switch (intel_encoder->type) {
case INTEL_OUTPUT_ANALOG:
type = DISPLAY_TYPE_CRT;
break;
case INTEL_OUTPUT_UNKNOWN:
case INTEL_OUTPUT_DISPLAYPORT:
case INTEL_OUTPUT_HDMI:
type = DISPLAY_TYPE_EXTERNAL_FLAT_PANEL;
break;
case INTEL_OUTPUT_EDP:
type = DISPLAY_TYPE_INTERNAL_FLAT_PANEL;
break;
default:
WARN_ONCE(1, "unsupported intel_encoder type %d\n",
intel_encoder->type);
return -EINVAL;
}

parm |= type << (16 + port * 3);

return swsci(dev, SWSCI_SBCB_DISPLAY_POWER_STATE, parm, NULL);
}

static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
{
struct drm_i915_private *dev_priv = dev->dev_private;
Expand Down

0 comments on commit 9c4b0a6

Please sign in to comment.