提交 ea5b213a 编写于 作者: C Chris Wilson 提交者: Eric Anholt

drm/i915: Subclass intel_encoder.

Subclass intel_encoder to reduce the pointer dance through
intel_encoder->dev_priv.

10 files changed, 896 insertions(+), 997 deletions(-)
Signed-off-by: NChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: NEric Anholt <eric@anholt.net>
上级 94113cec
...@@ -30,20 +30,17 @@ ...@@ -30,20 +30,17 @@
#include "intel_drv.h" #include "intel_drv.h"
struct intel_dvo_device { struct intel_dvo_device {
char *name; const char *name;
int type; int type;
/* DVOA/B/C output register */ /* DVOA/B/C output register */
u32 dvo_reg; u32 dvo_reg;
/* GPIO register used for i2c bus to control this device */ /* GPIO register used for i2c bus to control this device */
u32 gpio; u32 gpio;
int slave_addr; int slave_addr;
struct i2c_adapter *i2c_bus;
const struct intel_dvo_dev_ops *dev_ops; const struct intel_dvo_dev_ops *dev_ops;
void *dev_priv; void *dev_priv;
struct i2c_adapter *i2c_bus;
struct drm_display_mode *panel_fixed_mode;
bool panel_wants_dither;
}; };
struct intel_dvo_dev_ops { struct intel_dvo_dev_ops {
......
...@@ -508,17 +508,8 @@ static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs ...@@ -508,17 +508,8 @@ static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs
.best_encoder = intel_attached_encoder, .best_encoder = intel_attached_encoder,
}; };
static void intel_crt_enc_destroy(struct drm_encoder *encoder)
{
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
intel_i2c_destroy(intel_encoder->ddc_bus);
drm_encoder_cleanup(encoder);
kfree(intel_encoder);
}
static const struct drm_encoder_funcs intel_crt_enc_funcs = { static const struct drm_encoder_funcs intel_crt_enc_funcs = {
.destroy = intel_crt_enc_destroy, .destroy = intel_encoder_destroy,
}; };
void intel_crt_init(struct drm_device *dev) void intel_crt_init(struct drm_device *dev)
......
...@@ -2537,6 +2537,20 @@ void intel_encoder_commit (struct drm_encoder *encoder) ...@@ -2537,6 +2537,20 @@ void intel_encoder_commit (struct drm_encoder *encoder)
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
} }
void intel_encoder_destroy(struct drm_encoder *encoder)
{
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
if (intel_encoder->ddc_bus)
intel_i2c_destroy(intel_encoder->ddc_bus);
if (intel_encoder->i2c_bus)
intel_i2c_destroy(intel_encoder->i2c_bus);
drm_encoder_cleanup(encoder);
kfree(intel_encoder);
}
static bool intel_crtc_mode_fixup(struct drm_crtc *crtc, static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
......
此差异已折叠。
...@@ -102,7 +102,6 @@ struct intel_encoder { ...@@ -102,7 +102,6 @@ struct intel_encoder {
struct i2c_adapter *ddc_bus; struct i2c_adapter *ddc_bus;
bool load_detect_temp; bool load_detect_temp;
bool needs_tv_clock; bool needs_tv_clock;
void *dev_priv;
void (*hot_plug)(struct intel_encoder *); void (*hot_plug)(struct intel_encoder *);
int crtc_mask; int crtc_mask;
int clone_mask; int clone_mask;
...@@ -192,6 +191,7 @@ extern int intel_panel_fitter_pipe (struct drm_device *dev); ...@@ -192,6 +191,7 @@ extern int intel_panel_fitter_pipe (struct drm_device *dev);
extern void intel_crtc_load_lut(struct drm_crtc *crtc); extern void intel_crtc_load_lut(struct drm_crtc *crtc);
extern void intel_encoder_prepare (struct drm_encoder *encoder); extern void intel_encoder_prepare (struct drm_encoder *encoder);
extern void intel_encoder_commit (struct drm_encoder *encoder); extern void intel_encoder_commit (struct drm_encoder *encoder);
extern void intel_encoder_destroy(struct drm_encoder *encoder);
extern struct drm_encoder *intel_attached_encoder(struct drm_connector *connector); extern struct drm_encoder *intel_attached_encoder(struct drm_connector *connector);
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#define CH7xxx_ADDR 0x76 #define CH7xxx_ADDR 0x76
#define TFP410_ADDR 0x38 #define TFP410_ADDR 0x38
static struct intel_dvo_device intel_dvo_devices[] = { static const struct intel_dvo_device intel_dvo_devices[] = {
{ {
.type = INTEL_DVO_CHIP_TMDS, .type = INTEL_DVO_CHIP_TMDS,
.name = "sil164", .name = "sil164",
...@@ -77,20 +77,33 @@ static struct intel_dvo_device intel_dvo_devices[] = { ...@@ -77,20 +77,33 @@ static struct intel_dvo_device intel_dvo_devices[] = {
} }
}; };
struct intel_dvo {
struct intel_encoder base;
struct intel_dvo_device dev;
struct drm_display_mode *panel_fixed_mode;
bool panel_wants_dither;
};
static struct intel_dvo *enc_to_intel_dvo(struct drm_encoder *encoder)
{
return container_of(enc_to_intel_encoder(encoder), struct intel_dvo, base);
}
static void intel_dvo_dpms(struct drm_encoder *encoder, int mode) static void intel_dvo_dpms(struct drm_encoder *encoder, int mode)
{ {
struct drm_i915_private *dev_priv = encoder->dev->dev_private; struct drm_i915_private *dev_priv = encoder->dev->dev_private;
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
struct intel_dvo_device *dvo = intel_encoder->dev_priv; u32 dvo_reg = intel_dvo->dev.dvo_reg;
u32 dvo_reg = dvo->dvo_reg;
u32 temp = I915_READ(dvo_reg); u32 temp = I915_READ(dvo_reg);
if (mode == DRM_MODE_DPMS_ON) { if (mode == DRM_MODE_DPMS_ON) {
I915_WRITE(dvo_reg, temp | DVO_ENABLE); I915_WRITE(dvo_reg, temp | DVO_ENABLE);
I915_READ(dvo_reg); I915_READ(dvo_reg);
dvo->dev_ops->dpms(dvo, mode); intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, mode);
} else { } else {
dvo->dev_ops->dpms(dvo, mode); intel_dvo->dev.dev_ops->dpms(&intel_dvo->dev, mode);
I915_WRITE(dvo_reg, temp & ~DVO_ENABLE); I915_WRITE(dvo_reg, temp & ~DVO_ENABLE);
I915_READ(dvo_reg); I915_READ(dvo_reg);
} }
...@@ -100,38 +113,36 @@ static int intel_dvo_mode_valid(struct drm_connector *connector, ...@@ -100,38 +113,36 @@ static int intel_dvo_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode) struct drm_display_mode *mode)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
struct intel_dvo_device *dvo = intel_encoder->dev_priv;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN) if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
return MODE_NO_DBLESCAN; return MODE_NO_DBLESCAN;
/* XXX: Validate clock range */ /* XXX: Validate clock range */
if (dvo->panel_fixed_mode) { if (intel_dvo->panel_fixed_mode) {
if (mode->hdisplay > dvo->panel_fixed_mode->hdisplay) if (mode->hdisplay > intel_dvo->panel_fixed_mode->hdisplay)
return MODE_PANEL; return MODE_PANEL;
if (mode->vdisplay > dvo->panel_fixed_mode->vdisplay) if (mode->vdisplay > intel_dvo->panel_fixed_mode->vdisplay)
return MODE_PANEL; return MODE_PANEL;
} }
return dvo->dev_ops->mode_valid(dvo, mode); return intel_dvo->dev.dev_ops->mode_valid(&intel_dvo->dev, mode);
} }
static bool intel_dvo_mode_fixup(struct drm_encoder *encoder, static bool intel_dvo_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
{ {
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
struct intel_dvo_device *dvo = intel_encoder->dev_priv;
/* If we have timings from the BIOS for the panel, put them in /* If we have timings from the BIOS for the panel, put them in
* to the adjusted mode. The CRTC will be set up for this mode, * to the adjusted mode. The CRTC will be set up for this mode,
* with the panel scaling set up to source from the H/VDisplay * with the panel scaling set up to source from the H/VDisplay
* of the original mode. * of the original mode.
*/ */
if (dvo->panel_fixed_mode != NULL) { if (intel_dvo->panel_fixed_mode != NULL) {
#define C(x) adjusted_mode->x = dvo->panel_fixed_mode->x #define C(x) adjusted_mode->x = intel_dvo->panel_fixed_mode->x
C(hdisplay); C(hdisplay);
C(hsync_start); C(hsync_start);
C(hsync_end); C(hsync_end);
...@@ -145,8 +156,8 @@ static bool intel_dvo_mode_fixup(struct drm_encoder *encoder, ...@@ -145,8 +156,8 @@ static bool intel_dvo_mode_fixup(struct drm_encoder *encoder,
#undef C #undef C
} }
if (dvo->dev_ops->mode_fixup) if (intel_dvo->dev.dev_ops->mode_fixup)
return dvo->dev_ops->mode_fixup(dvo, mode, adjusted_mode); return intel_dvo->dev.dev_ops->mode_fixup(&intel_dvo->dev, mode, adjusted_mode);
return true; return true;
} }
...@@ -158,11 +169,10 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder, ...@@ -158,11 +169,10 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
struct intel_dvo_device *dvo = intel_encoder->dev_priv;
int pipe = intel_crtc->pipe; int pipe = intel_crtc->pipe;
u32 dvo_val; u32 dvo_val;
u32 dvo_reg = dvo->dvo_reg, dvo_srcdim_reg; u32 dvo_reg = intel_dvo->dev.dvo_reg, dvo_srcdim_reg;
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
switch (dvo_reg) { switch (dvo_reg) {
...@@ -178,7 +188,7 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder, ...@@ -178,7 +188,7 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
break; break;
} }
dvo->dev_ops->mode_set(dvo, mode, adjusted_mode); intel_dvo->dev.dev_ops->mode_set(&intel_dvo->dev, mode, adjusted_mode);
/* Save the data order, since I don't know what it should be set to. */ /* Save the data order, since I don't know what it should be set to. */
dvo_val = I915_READ(dvo_reg) & dvo_val = I915_READ(dvo_reg) &
...@@ -214,40 +224,38 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder, ...@@ -214,40 +224,38 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector) static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
struct intel_dvo_device *dvo = intel_encoder->dev_priv;
return dvo->dev_ops->detect(dvo); return intel_dvo->dev.dev_ops->detect(&intel_dvo->dev);
} }
static int intel_dvo_get_modes(struct drm_connector *connector) static int intel_dvo_get_modes(struct drm_connector *connector)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
struct intel_dvo_device *dvo = intel_encoder->dev_priv;
/* We should probably have an i2c driver get_modes function for those /* We should probably have an i2c driver get_modes function for those
* devices which will have a fixed set of modes determined by the chip * devices which will have a fixed set of modes determined by the chip
* (TV-out, for example), but for now with just TMDS and LVDS, * (TV-out, for example), but for now with just TMDS and LVDS,
* that's not the case. * that's not the case.
*/ */
intel_ddc_get_modes(connector, intel_encoder->ddc_bus); intel_ddc_get_modes(connector, intel_dvo->base.ddc_bus);
if (!list_empty(&connector->probed_modes)) if (!list_empty(&connector->probed_modes))
return 1; return 1;
if (intel_dvo->panel_fixed_mode != NULL) {
if (dvo->panel_fixed_mode != NULL) {
struct drm_display_mode *mode; struct drm_display_mode *mode;
mode = drm_mode_duplicate(connector->dev, dvo->panel_fixed_mode); mode = drm_mode_duplicate(connector->dev, intel_dvo->panel_fixed_mode);
if (mode) { if (mode) {
drm_mode_probed_add(connector, mode); drm_mode_probed_add(connector, mode);
return 1; return 1;
} }
} }
return 0; return 0;
} }
static void intel_dvo_destroy (struct drm_connector *connector) static void intel_dvo_destroy(struct drm_connector *connector)
{ {
drm_sysfs_connector_remove(connector); drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
...@@ -277,28 +285,20 @@ static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs ...@@ -277,28 +285,20 @@ static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs
static void intel_dvo_enc_destroy(struct drm_encoder *encoder) static void intel_dvo_enc_destroy(struct drm_encoder *encoder)
{ {
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
struct intel_dvo_device *dvo = intel_encoder->dev_priv;
if (intel_dvo->dev.dev_ops->destroy)
if (dvo) { intel_dvo->dev.dev_ops->destroy(&intel_dvo->dev);
if (dvo->dev_ops->destroy)
dvo->dev_ops->destroy(dvo); kfree(intel_dvo->panel_fixed_mode);
if (dvo->panel_fixed_mode)
kfree(dvo->panel_fixed_mode); intel_encoder_destroy(encoder);
}
if (intel_encoder->i2c_bus)
intel_i2c_destroy(intel_encoder->i2c_bus);
if (intel_encoder->ddc_bus)
intel_i2c_destroy(intel_encoder->ddc_bus);
drm_encoder_cleanup(encoder);
kfree(intel_encoder);
} }
static const struct drm_encoder_funcs intel_dvo_enc_funcs = { static const struct drm_encoder_funcs intel_dvo_enc_funcs = {
.destroy = intel_dvo_enc_destroy, .destroy = intel_dvo_enc_destroy,
}; };
/** /**
* Attempts to get a fixed panel timing for LVDS (currently only the i830). * Attempts to get a fixed panel timing for LVDS (currently only the i830).
* *
...@@ -306,15 +306,13 @@ static const struct drm_encoder_funcs intel_dvo_enc_funcs = { ...@@ -306,15 +306,13 @@ static const struct drm_encoder_funcs intel_dvo_enc_funcs = {
* chip being on DVOB/C and having multiple pipes. * chip being on DVOB/C and having multiple pipes.
*/ */
static struct drm_display_mode * static struct drm_display_mode *
intel_dvo_get_current_mode (struct drm_connector *connector) intel_dvo_get_current_mode(struct drm_connector *connector)
{ {
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_encoder *encoder = intel_attached_encoder(connector); struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
struct intel_dvo_device *dvo = intel_encoder->dev_priv; uint32_t dvo_val = I915_READ(intel_dvo->dev.dvo_reg);
uint32_t dvo_reg = dvo->dvo_reg;
uint32_t dvo_val = I915_READ(dvo_reg);
struct drm_display_mode *mode = NULL; struct drm_display_mode *mode = NULL;
/* If the DVO port is active, that'll be the LVDS, so we can pull out /* If the DVO port is active, that'll be the LVDS, so we can pull out
...@@ -327,7 +325,6 @@ intel_dvo_get_current_mode (struct drm_connector *connector) ...@@ -327,7 +325,6 @@ intel_dvo_get_current_mode (struct drm_connector *connector)
crtc = intel_get_crtc_from_pipe(dev, pipe); crtc = intel_get_crtc_from_pipe(dev, pipe);
if (crtc) { if (crtc) {
mode = intel_crtc_mode_get(dev, crtc); mode = intel_crtc_mode_get(dev, crtc);
if (mode) { if (mode) {
mode->type |= DRM_MODE_TYPE_PREFERRED; mode->type |= DRM_MODE_TYPE_PREFERRED;
if (dvo_val & DVO_HSYNC_ACTIVE_HIGH) if (dvo_val & DVO_HSYNC_ACTIVE_HIGH)
...@@ -337,28 +334,32 @@ intel_dvo_get_current_mode (struct drm_connector *connector) ...@@ -337,28 +334,32 @@ intel_dvo_get_current_mode (struct drm_connector *connector)
} }
} }
} }
return mode; return mode;
} }
void intel_dvo_init(struct drm_device *dev) void intel_dvo_init(struct drm_device *dev)
{ {
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
struct intel_dvo *intel_dvo;
struct intel_connector *intel_connector; struct intel_connector *intel_connector;
struct intel_dvo_device *dvo;
struct i2c_adapter *i2cbus = NULL; struct i2c_adapter *i2cbus = NULL;
int ret = 0; int ret = 0;
int i; int i;
int encoder_type = DRM_MODE_ENCODER_NONE; int encoder_type = DRM_MODE_ENCODER_NONE;
intel_encoder = kzalloc (sizeof(struct intel_encoder), GFP_KERNEL);
if (!intel_encoder) intel_dvo = kzalloc(sizeof(struct intel_dvo), GFP_KERNEL);
if (!intel_dvo)
return; return;
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
if (!intel_connector) { if (!intel_connector) {
kfree(intel_encoder); kfree(intel_dvo);
return; return;
} }
intel_encoder = &intel_dvo->base;
/* Set up the DDC bus */ /* Set up the DDC bus */
intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "DVODDC_D"); intel_encoder->ddc_bus = intel_i2c_create(dev, GPIOD, "DVODDC_D");
if (!intel_encoder->ddc_bus) if (!intel_encoder->ddc_bus)
...@@ -367,10 +368,9 @@ void intel_dvo_init(struct drm_device *dev) ...@@ -367,10 +368,9 @@ void intel_dvo_init(struct drm_device *dev)
/* Now, try to find a controller */ /* Now, try to find a controller */
for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) { for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
struct drm_connector *connector = &intel_connector->base; struct drm_connector *connector = &intel_connector->base;
const struct intel_dvo_device *dvo = &intel_dvo_devices[i];
int gpio; int gpio;
dvo = &intel_dvo_devices[i];
/* Allow the I2C driver info to specify the GPIO to be used in /* Allow the I2C driver info to specify the GPIO to be used in
* special cases, but otherwise default to what's defined * special cases, but otherwise default to what's defined
* in the spec. * in the spec.
...@@ -393,11 +393,8 @@ void intel_dvo_init(struct drm_device *dev) ...@@ -393,11 +393,8 @@ void intel_dvo_init(struct drm_device *dev)
continue; continue;
} }
if (dvo->dev_ops!= NULL) intel_dvo->dev = *dvo;
ret = dvo->dev_ops->init(dvo, i2cbus); ret = dvo->dev_ops->init(&intel_dvo->dev, i2cbus);
else
ret = false;
if (!ret) if (!ret)
continue; continue;
...@@ -429,9 +426,6 @@ void intel_dvo_init(struct drm_device *dev) ...@@ -429,9 +426,6 @@ void intel_dvo_init(struct drm_device *dev)
connector->interlace_allowed = false; connector->interlace_allowed = false;
connector->doublescan_allowed = false; connector->doublescan_allowed = false;
intel_encoder->dev_priv = dvo;
intel_encoder->i2c_bus = i2cbus;
drm_encoder_init(dev, &intel_encoder->enc, drm_encoder_init(dev, &intel_encoder->enc,
&intel_dvo_enc_funcs, encoder_type); &intel_dvo_enc_funcs, encoder_type);
drm_encoder_helper_add(&intel_encoder->enc, drm_encoder_helper_add(&intel_encoder->enc,
...@@ -447,9 +441,9 @@ void intel_dvo_init(struct drm_device *dev) ...@@ -447,9 +441,9 @@ void intel_dvo_init(struct drm_device *dev)
* headers, likely), so for now, just get the current * headers, likely), so for now, just get the current
* mode being output through DVO. * mode being output through DVO.
*/ */
dvo->panel_fixed_mode = intel_dvo->panel_fixed_mode =
intel_dvo_get_current_mode(connector); intel_dvo_get_current_mode(connector);
dvo->panel_wants_dither = true; intel_dvo->panel_wants_dither = true;
} }
drm_sysfs_connector_add(connector); drm_sysfs_connector_add(connector);
...@@ -461,6 +455,6 @@ void intel_dvo_init(struct drm_device *dev) ...@@ -461,6 +455,6 @@ void intel_dvo_init(struct drm_device *dev)
if (i2cbus != NULL) if (i2cbus != NULL)
intel_i2c_destroy(i2cbus); intel_i2c_destroy(i2cbus);
free_intel: free_intel:
kfree(intel_encoder); kfree(intel_dvo);
kfree(intel_connector); kfree(intel_connector);
} }
...@@ -37,11 +37,17 @@ ...@@ -37,11 +37,17 @@
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_drv.h" #include "i915_drv.h"
struct intel_hdmi_priv { struct intel_hdmi {
struct intel_encoder base;
u32 sdvox_reg; u32 sdvox_reg;
bool has_hdmi_sink; bool has_hdmi_sink;
}; };
static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder)
{
return container_of(enc_to_intel_encoder(encoder), struct intel_hdmi, base);
}
static void intel_hdmi_mode_set(struct drm_encoder *encoder, static void intel_hdmi_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode) struct drm_display_mode *adjusted_mode)
...@@ -50,8 +56,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, ...@@ -50,8 +56,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = encoder->crtc; struct drm_crtc *crtc = encoder->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv;
u32 sdvox; u32 sdvox;
sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE; sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE;
...@@ -60,7 +65,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, ...@@ -60,7 +65,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
sdvox |= SDVO_HSYNC_ACTIVE_HIGH; sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
if (hdmi_priv->has_hdmi_sink) { if (intel_hdmi->has_hdmi_sink) {
sdvox |= SDVO_AUDIO_ENABLE; sdvox |= SDVO_AUDIO_ENABLE;
if (HAS_PCH_CPT(dev)) if (HAS_PCH_CPT(dev))
sdvox |= HDMI_MODE_SELECT; sdvox |= HDMI_MODE_SELECT;
...@@ -73,26 +78,25 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, ...@@ -73,26 +78,25 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
sdvox |= SDVO_PIPE_B_SELECT; sdvox |= SDVO_PIPE_B_SELECT;
} }
I915_WRITE(hdmi_priv->sdvox_reg, sdvox); I915_WRITE(intel_hdmi->sdvox_reg, sdvox);
POSTING_READ(hdmi_priv->sdvox_reg); POSTING_READ(intel_hdmi->sdvox_reg);
} }
static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv;
u32 temp; u32 temp;
temp = I915_READ(hdmi_priv->sdvox_reg); temp = I915_READ(intel_hdmi->sdvox_reg);
/* HW workaround, need to toggle enable bit off and on for 12bpc, but /* HW workaround, need to toggle enable bit off and on for 12bpc, but
* we do this anyway which shows more stable in testing. * we do this anyway which shows more stable in testing.
*/ */
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
I915_WRITE(hdmi_priv->sdvox_reg, temp & ~SDVO_ENABLE); I915_WRITE(intel_hdmi->sdvox_reg, temp & ~SDVO_ENABLE);
POSTING_READ(hdmi_priv->sdvox_reg); POSTING_READ(intel_hdmi->sdvox_reg);
} }
if (mode != DRM_MODE_DPMS_ON) { if (mode != DRM_MODE_DPMS_ON) {
...@@ -101,15 +105,15 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) ...@@ -101,15 +105,15 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
temp |= SDVO_ENABLE; temp |= SDVO_ENABLE;
} }
I915_WRITE(hdmi_priv->sdvox_reg, temp); I915_WRITE(intel_hdmi->sdvox_reg, temp);
POSTING_READ(hdmi_priv->sdvox_reg); POSTING_READ(intel_hdmi->sdvox_reg);
/* HW workaround, need to write this twice for issue that may result /* HW workaround, need to write this twice for issue that may result
* in first write getting masked. * in first write getting masked.
*/ */
if (HAS_PCH_SPLIT(dev)) { if (HAS_PCH_SPLIT(dev)) {
I915_WRITE(hdmi_priv->sdvox_reg, temp); I915_WRITE(intel_hdmi->sdvox_reg, temp);
POSTING_READ(hdmi_priv->sdvox_reg); POSTING_READ(intel_hdmi->sdvox_reg);
} }
} }
...@@ -138,19 +142,17 @@ static enum drm_connector_status ...@@ -138,19 +142,17 @@ static enum drm_connector_status
intel_hdmi_detect(struct drm_connector *connector) intel_hdmi_detect(struct drm_connector *connector)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv;
struct edid *edid = NULL; struct edid *edid = NULL;
enum drm_connector_status status = connector_status_disconnected; enum drm_connector_status status = connector_status_disconnected;
hdmi_priv->has_hdmi_sink = false; intel_hdmi->has_hdmi_sink = false;
edid = drm_get_edid(connector, edid = drm_get_edid(connector, intel_hdmi->base.ddc_bus);
intel_encoder->ddc_bus);
if (edid) { if (edid) {
if (edid->input & DRM_EDID_INPUT_DIGITAL) { if (edid->input & DRM_EDID_INPUT_DIGITAL) {
status = connector_status_connected; status = connector_status_connected;
hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); intel_hdmi->has_hdmi_sink = drm_detect_hdmi_monitor(edid);
} }
connector->display_info.raw_edid = NULL; connector->display_info.raw_edid = NULL;
kfree(edid); kfree(edid);
...@@ -162,13 +164,13 @@ intel_hdmi_detect(struct drm_connector *connector) ...@@ -162,13 +164,13 @@ intel_hdmi_detect(struct drm_connector *connector)
static int intel_hdmi_get_modes(struct drm_connector *connector) static int intel_hdmi_get_modes(struct drm_connector *connector)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
/* We should parse the EDID data and find out if it's an HDMI sink so /* We should parse the EDID data and find out if it's an HDMI sink so
* we can send audio to it. * we can send audio to it.
*/ */
return intel_ddc_get_modes(connector, intel_encoder->ddc_bus); return intel_ddc_get_modes(connector, intel_hdmi->base.ddc_bus);
} }
static void intel_hdmi_destroy(struct drm_connector *connector) static void intel_hdmi_destroy(struct drm_connector *connector)
...@@ -199,18 +201,8 @@ static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs ...@@ -199,18 +201,8 @@ static const struct drm_connector_helper_funcs intel_hdmi_connector_helper_funcs
.best_encoder = intel_attached_encoder, .best_encoder = intel_attached_encoder,
}; };
static void intel_hdmi_enc_destroy(struct drm_encoder *encoder)
{
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
if (intel_encoder->i2c_bus)
intel_i2c_destroy(intel_encoder->i2c_bus);
drm_encoder_cleanup(encoder);
kfree(intel_encoder);
}
static const struct drm_encoder_funcs intel_hdmi_enc_funcs = { static const struct drm_encoder_funcs intel_hdmi_enc_funcs = {
.destroy = intel_hdmi_enc_destroy, .destroy = intel_encoder_destroy,
}; };
void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
...@@ -219,21 +211,19 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) ...@@ -219,21 +211,19 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
struct drm_connector *connector; struct drm_connector *connector;
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector; struct intel_connector *intel_connector;
struct intel_hdmi_priv *hdmi_priv; struct intel_hdmi *intel_hdmi;
intel_encoder = kcalloc(sizeof(struct intel_encoder) + intel_hdmi = kzalloc(sizeof(struct intel_hdmi), GFP_KERNEL);
sizeof(struct intel_hdmi_priv), 1, GFP_KERNEL); if (!intel_hdmi)
if (!intel_encoder)
return; return;
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
if (!intel_connector) { if (!intel_connector) {
kfree(intel_encoder); kfree(intel_hdmi);
return; return;
} }
hdmi_priv = (struct intel_hdmi_priv *)(intel_encoder + 1); intel_encoder = &intel_hdmi->base;
connector = &intel_connector->base; connector = &intel_connector->base;
drm_connector_init(dev, connector, &intel_hdmi_connector_funcs, drm_connector_init(dev, connector, &intel_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA); DRM_MODE_CONNECTOR_HDMIA);
...@@ -274,8 +264,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) ...@@ -274,8 +264,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
if (!intel_encoder->ddc_bus) if (!intel_encoder->ddc_bus)
goto err_connector; goto err_connector;
hdmi_priv->sdvox_reg = sdvox_reg; intel_hdmi->sdvox_reg = sdvox_reg;
intel_encoder->dev_priv = hdmi_priv;
drm_encoder_init(dev, &intel_encoder->enc, &intel_hdmi_enc_funcs, drm_encoder_init(dev, &intel_encoder->enc, &intel_hdmi_enc_funcs,
DRM_MODE_ENCODER_TMDS); DRM_MODE_ENCODER_TMDS);
...@@ -298,7 +287,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) ...@@ -298,7 +287,7 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
err_connector: err_connector:
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
kfree(intel_encoder); kfree(intel_hdmi);
kfree(intel_connector); kfree(intel_connector);
return; return;
......
...@@ -41,12 +41,18 @@ ...@@ -41,12 +41,18 @@
#include <linux/acpi.h> #include <linux/acpi.h>
/* Private structure for the integrated LVDS support */ /* Private structure for the integrated LVDS support */
struct intel_lvds_priv { struct intel_lvds {
struct intel_encoder base;
int fitting_mode; int fitting_mode;
u32 pfit_control; u32 pfit_control;
u32 pfit_pgm_ratios; u32 pfit_pgm_ratios;
}; };
static struct intel_lvds *enc_to_intel_lvds(struct drm_encoder *encoder)
{
return container_of(enc_to_intel_encoder(encoder), struct intel_lvds, base);
}
/** /**
* Sets the backlight level. * Sets the backlight level.
* *
...@@ -219,9 +225,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, ...@@ -219,9 +225,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder);
struct drm_encoder *tmp_encoder; struct drm_encoder *tmp_encoder;
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv;
u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
/* Should never happen!! */ /* Should never happen!! */
...@@ -293,7 +298,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, ...@@ -293,7 +298,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
I915_WRITE(BCLRPAT_B, 0); I915_WRITE(BCLRPAT_B, 0);
} }
switch (lvds_priv->fitting_mode) { switch (intel_lvds->fitting_mode) {
case DRM_MODE_SCALE_CENTER: case DRM_MODE_SCALE_CENTER:
/* /*
* For centered modes, we have to calculate border widths & * For centered modes, we have to calculate border widths &
...@@ -378,8 +383,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, ...@@ -378,8 +383,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
} }
out: out:
lvds_priv->pfit_control = pfit_control; intel_lvds->pfit_control = pfit_control;
lvds_priv->pfit_pgm_ratios = pfit_pgm_ratios; intel_lvds->pfit_pgm_ratios = pfit_pgm_ratios;
dev_priv->lvds_border_bits = border; dev_priv->lvds_border_bits = border;
/* /*
...@@ -427,8 +432,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, ...@@ -427,8 +432,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder);
struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv;
/* /*
* The LVDS pin pair will already have been turned on in the * The LVDS pin pair will already have been turned on in the
...@@ -444,8 +448,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, ...@@ -444,8 +448,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
* screen. Should be enabled before the pipe is enabled, according to * screen. Should be enabled before the pipe is enabled, according to
* register description and PRM. * register description and PRM.
*/ */
I915_WRITE(PFIT_PGM_RATIOS, lvds_priv->pfit_pgm_ratios); I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios);
I915_WRITE(PFIT_CONTROL, lvds_priv->pfit_control); I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control);
} }
/** /**
...@@ -600,18 +604,17 @@ static int intel_lvds_set_property(struct drm_connector *connector, ...@@ -600,18 +604,17 @@ static int intel_lvds_set_property(struct drm_connector *connector,
connector->encoder) { connector->encoder) {
struct drm_crtc *crtc = connector->encoder->crtc; struct drm_crtc *crtc = connector->encoder->crtc;
struct drm_encoder *encoder = connector->encoder; struct drm_encoder *encoder = connector->encoder;
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder);
struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv;
if (value == DRM_MODE_SCALE_NONE) { if (value == DRM_MODE_SCALE_NONE) {
DRM_DEBUG_KMS("no scaling not supported\n"); DRM_DEBUG_KMS("no scaling not supported\n");
return 0; return 0;
} }
if (lvds_priv->fitting_mode == value) { if (intel_lvds->fitting_mode == value) {
/* the LVDS scaling property is not changed */ /* the LVDS scaling property is not changed */
return 0; return 0;
} }
lvds_priv->fitting_mode = value; intel_lvds->fitting_mode = value;
if (crtc && crtc->enabled) { if (crtc && crtc->enabled) {
/* /*
* If the CRTC is enabled, the display will be changed * If the CRTC is enabled, the display will be changed
...@@ -647,19 +650,8 @@ static const struct drm_connector_funcs intel_lvds_connector_funcs = { ...@@ -647,19 +650,8 @@ static const struct drm_connector_funcs intel_lvds_connector_funcs = {
.destroy = intel_lvds_destroy, .destroy = intel_lvds_destroy,
}; };
static void intel_lvds_enc_destroy(struct drm_encoder *encoder)
{
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
if (intel_encoder->ddc_bus)
intel_i2c_destroy(intel_encoder->ddc_bus);
drm_encoder_cleanup(encoder);
kfree(intel_encoder);
}
static const struct drm_encoder_funcs intel_lvds_enc_funcs = { static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
.destroy = intel_lvds_enc_destroy, .destroy = intel_encoder_destroy,
}; };
static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id) static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
...@@ -843,13 +835,13 @@ static int lvds_is_present_in_vbt(struct drm_device *dev) ...@@ -843,13 +835,13 @@ static int lvds_is_present_in_vbt(struct drm_device *dev)
void intel_lvds_init(struct drm_device *dev) void intel_lvds_init(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_lvds *intel_lvds;
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector; struct intel_connector *intel_connector;
struct drm_connector *connector; struct drm_connector *connector;
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct drm_display_mode *scan; /* *modes, *bios_mode; */ struct drm_display_mode *scan; /* *modes, *bios_mode; */
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct intel_lvds_priv *lvds_priv;
u32 lvds; u32 lvds;
int pipe, gpio = GPIOC; int pipe, gpio = GPIOC;
...@@ -872,20 +864,20 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -872,20 +864,20 @@ void intel_lvds_init(struct drm_device *dev)
gpio = PCH_GPIOC; gpio = PCH_GPIOC;
} }
intel_encoder = kzalloc(sizeof(struct intel_encoder) + intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL);
sizeof(struct intel_lvds_priv), GFP_KERNEL); if (!intel_lvds) {
if (!intel_encoder) {
return; return;
} }
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
if (!intel_connector) { if (!intel_connector) {
kfree(intel_encoder); kfree(intel_lvds);
return; return;
} }
connector = &intel_connector->base; intel_encoder = &intel_lvds->base;
encoder = &intel_encoder->enc; encoder = &intel_encoder->enc;
connector = &intel_connector->base;
drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs, drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs,
DRM_MODE_CONNECTOR_LVDS); DRM_MODE_CONNECTOR_LVDS);
...@@ -905,8 +897,6 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -905,8 +897,6 @@ void intel_lvds_init(struct drm_device *dev)
connector->interlace_allowed = false; connector->interlace_allowed = false;
connector->doublescan_allowed = false; connector->doublescan_allowed = false;
lvds_priv = (struct intel_lvds_priv *)(intel_encoder + 1);
intel_encoder->dev_priv = lvds_priv;
/* create the scaling mode property */ /* create the scaling mode property */
drm_mode_create_scaling_mode_property(dev); drm_mode_create_scaling_mode_property(dev);
/* /*
...@@ -916,7 +906,7 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -916,7 +906,7 @@ void intel_lvds_init(struct drm_device *dev)
drm_connector_attach_property(&intel_connector->base, drm_connector_attach_property(&intel_connector->base,
dev->mode_config.scaling_mode_property, dev->mode_config.scaling_mode_property,
DRM_MODE_SCALE_ASPECT); DRM_MODE_SCALE_ASPECT);
lvds_priv->fitting_mode = DRM_MODE_SCALE_ASPECT; intel_lvds->fitting_mode = DRM_MODE_SCALE_ASPECT;
/* /*
* LVDS discovery: * LVDS discovery:
* 1) check for EDID on DDC * 1) check for EDID on DDC
...@@ -1024,6 +1014,6 @@ void intel_lvds_init(struct drm_device *dev) ...@@ -1024,6 +1014,6 @@ void intel_lvds_init(struct drm_device *dev)
intel_i2c_destroy(intel_encoder->ddc_bus); intel_i2c_destroy(intel_encoder->ddc_bus);
drm_connector_cleanup(connector); drm_connector_cleanup(connector);
drm_encoder_cleanup(encoder); drm_encoder_cleanup(encoder);
kfree(intel_encoder); kfree(intel_lvds);
kfree(intel_connector); kfree(intel_connector);
} }
此差异已折叠。
...@@ -44,7 +44,9 @@ enum tv_margin { ...@@ -44,7 +44,9 @@ enum tv_margin {
}; };
/** Private structure for the integrated TV support */ /** Private structure for the integrated TV support */
struct intel_tv_priv { struct intel_tv {
struct intel_encoder base;
int type; int type;
char *tv_format; char *tv_format;
int margin[4]; int margin[4];
...@@ -896,6 +898,11 @@ static const struct tv_mode tv_modes[] = { ...@@ -896,6 +898,11 @@ static const struct tv_mode tv_modes[] = {
}, },
}; };
static struct intel_tv *enc_to_intel_tv(struct drm_encoder *encoder)
{
return container_of(enc_to_intel_encoder(encoder), struct intel_tv, base);
}
static void static void
intel_tv_dpms(struct drm_encoder *encoder, int mode) intel_tv_dpms(struct drm_encoder *encoder, int mode)
{ {
...@@ -929,19 +936,17 @@ intel_tv_mode_lookup (char *tv_format) ...@@ -929,19 +936,17 @@ intel_tv_mode_lookup (char *tv_format)
} }
static const struct tv_mode * static const struct tv_mode *
intel_tv_mode_find (struct intel_encoder *intel_encoder) intel_tv_mode_find (struct intel_tv *intel_tv)
{ {
struct intel_tv_priv *tv_priv = intel_encoder->dev_priv; return intel_tv_mode_lookup(intel_tv->tv_format);
return intel_tv_mode_lookup(tv_priv->tv_format);
} }
static enum drm_mode_status static enum drm_mode_status
intel_tv_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) intel_tv_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder); const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
/* Ensure TV refresh is close to desired refresh */ /* Ensure TV refresh is close to desired refresh */
if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000) if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode) * 1000)
...@@ -957,8 +962,8 @@ intel_tv_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -957,8 +962,8 @@ intel_tv_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_mode_config *drm_config = &dev->mode_config; struct drm_mode_config *drm_config = &dev->mode_config;
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find (intel_encoder); const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
struct drm_encoder *other_encoder; struct drm_encoder *other_encoder;
if (!tv_mode) if (!tv_mode)
...@@ -983,9 +988,8 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -983,9 +988,8 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = encoder->crtc; struct drm_crtc *crtc = encoder->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
struct intel_tv_priv *tv_priv = intel_encoder->dev_priv; const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
u32 tv_ctl; u32 tv_ctl;
u32 hctl1, hctl2, hctl3; u32 hctl1, hctl2, hctl3;
u32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7; u32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
...@@ -1001,7 +1005,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -1001,7 +1005,7 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
tv_ctl = I915_READ(TV_CTL); tv_ctl = I915_READ(TV_CTL);
tv_ctl &= TV_CTL_SAVE; tv_ctl &= TV_CTL_SAVE;
switch (tv_priv->type) { switch (intel_tv->type) {
default: default:
case DRM_MODE_CONNECTOR_Unknown: case DRM_MODE_CONNECTOR_Unknown:
case DRM_MODE_CONNECTOR_Composite: case DRM_MODE_CONNECTOR_Composite:
...@@ -1168,12 +1172,12 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, ...@@ -1168,12 +1172,12 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
else else
ysize = 2*tv_mode->nbr_end + 1; ysize = 2*tv_mode->nbr_end + 1;
xpos += tv_priv->margin[TV_MARGIN_LEFT]; xpos += intel_tv->margin[TV_MARGIN_LEFT];
ypos += tv_priv->margin[TV_MARGIN_TOP]; ypos += intel_tv->margin[TV_MARGIN_TOP];
xsize -= (tv_priv->margin[TV_MARGIN_LEFT] + xsize -= (intel_tv->margin[TV_MARGIN_LEFT] +
tv_priv->margin[TV_MARGIN_RIGHT]); intel_tv->margin[TV_MARGIN_RIGHT]);
ysize -= (tv_priv->margin[TV_MARGIN_TOP] + ysize -= (intel_tv->margin[TV_MARGIN_TOP] +
tv_priv->margin[TV_MARGIN_BOTTOM]); intel_tv->margin[TV_MARGIN_BOTTOM]);
I915_WRITE(TV_WIN_POS, (xpos<<16)|ypos); I915_WRITE(TV_WIN_POS, (xpos<<16)|ypos);
I915_WRITE(TV_WIN_SIZE, (xsize<<16)|ysize); I915_WRITE(TV_WIN_SIZE, (xsize<<16)|ysize);
...@@ -1222,9 +1226,9 @@ static const struct drm_display_mode reported_modes[] = { ...@@ -1222,9 +1226,9 @@ static const struct drm_display_mode reported_modes[] = {
* \return false if TV is disconnected. * \return false if TV is disconnected.
*/ */
static int static int
intel_tv_detect_type (struct drm_crtc *crtc, struct intel_encoder *intel_encoder) intel_tv_detect_type (struct intel_tv *intel_tv)
{ {
struct drm_encoder *encoder = &intel_encoder->enc; struct drm_encoder *encoder = &intel_tv->base.enc;
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long irqflags; unsigned long irqflags;
...@@ -1304,12 +1308,11 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_encoder *intel_encoder ...@@ -1304,12 +1308,11 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_encoder *intel_encoder
static void intel_tv_find_better_format(struct drm_connector *connector) static void intel_tv_find_better_format(struct drm_connector *connector)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
struct intel_tv_priv *tv_priv = intel_encoder->dev_priv; const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder);
int i; int i;
if ((tv_priv->type == DRM_MODE_CONNECTOR_Component) == if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
tv_mode->component_only) tv_mode->component_only)
return; return;
...@@ -1317,12 +1320,12 @@ static void intel_tv_find_better_format(struct drm_connector *connector) ...@@ -1317,12 +1320,12 @@ static void intel_tv_find_better_format(struct drm_connector *connector)
for (i = 0; i < sizeof(tv_modes) / sizeof(*tv_modes); i++) { for (i = 0; i < sizeof(tv_modes) / sizeof(*tv_modes); i++) {
tv_mode = tv_modes + i; tv_mode = tv_modes + i;
if ((tv_priv->type == DRM_MODE_CONNECTOR_Component) == if ((intel_tv->type == DRM_MODE_CONNECTOR_Component) ==
tv_mode->component_only) tv_mode->component_only)
break; break;
} }
tv_priv->tv_format = tv_mode->name; intel_tv->tv_format = tv_mode->name;
drm_connector_property_set_value(connector, drm_connector_property_set_value(connector,
connector->dev->mode_config.tv_mode_property, i); connector->dev->mode_config.tv_mode_property, i);
} }
...@@ -1336,31 +1339,31 @@ static void intel_tv_find_better_format(struct drm_connector *connector) ...@@ -1336,31 +1339,31 @@ static void intel_tv_find_better_format(struct drm_connector *connector)
static enum drm_connector_status static enum drm_connector_status
intel_tv_detect(struct drm_connector *connector) intel_tv_detect(struct drm_connector *connector)
{ {
struct drm_crtc *crtc;
struct drm_display_mode mode; struct drm_display_mode mode;
struct drm_encoder *encoder = intel_attached_encoder(connector); struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
struct intel_tv_priv *tv_priv = intel_encoder->dev_priv; int type;
int dpms_mode;
int type = tv_priv->type;
mode = reported_modes[0]; mode = reported_modes[0];
drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V); drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V);
if (encoder->crtc && encoder->crtc->enabled) { if (encoder->crtc && encoder->crtc->enabled) {
type = intel_tv_detect_type(encoder->crtc, intel_encoder); type = intel_tv_detect_type(intel_tv);
} else { } else {
crtc = intel_get_load_detect_pipe(intel_encoder, connector, struct drm_crtc *crtc;
int dpms_mode;
crtc = intel_get_load_detect_pipe(&intel_tv->base, connector,
&mode, &dpms_mode); &mode, &dpms_mode);
if (crtc) { if (crtc) {
type = intel_tv_detect_type(crtc, intel_encoder); type = intel_tv_detect_type(intel_tv);
intel_release_load_detect_pipe(intel_encoder, connector, intel_release_load_detect_pipe(&intel_tv->base, connector,
dpms_mode); dpms_mode);
} else } else
type = -1; type = -1;
} }
tv_priv->type = type; intel_tv->type = type;
if (type < 0) if (type < 0)
return connector_status_disconnected; return connector_status_disconnected;
...@@ -1391,8 +1394,8 @@ intel_tv_chose_preferred_modes(struct drm_connector *connector, ...@@ -1391,8 +1394,8 @@ intel_tv_chose_preferred_modes(struct drm_connector *connector,
struct drm_display_mode *mode_ptr) struct drm_display_mode *mode_ptr)
{ {
struct drm_encoder *encoder = intel_attached_encoder(connector); struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder); const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480) if (tv_mode->nbr_end < 480 && mode_ptr->vdisplay == 480)
mode_ptr->type |= DRM_MODE_TYPE_PREFERRED; mode_ptr->type |= DRM_MODE_TYPE_PREFERRED;
...@@ -1417,8 +1420,8 @@ intel_tv_get_modes(struct drm_connector *connector) ...@@ -1417,8 +1420,8 @@ intel_tv_get_modes(struct drm_connector *connector)
{ {
struct drm_display_mode *mode_ptr; struct drm_display_mode *mode_ptr;
struct drm_encoder *encoder = intel_attached_encoder(connector); struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_encoder); const struct tv_mode *tv_mode = intel_tv_mode_find(intel_tv);
int j, count = 0; int j, count = 0;
u64 tmp; u64 tmp;
...@@ -1483,8 +1486,7 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop ...@@ -1483,8 +1486,7 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
{ {
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct drm_encoder *encoder = intel_attached_encoder(connector); struct drm_encoder *encoder = intel_attached_encoder(connector);
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); struct intel_tv *intel_tv = enc_to_intel_tv(encoder);
struct intel_tv_priv *tv_priv = intel_encoder->dev_priv;
struct drm_crtc *crtc = encoder->crtc; struct drm_crtc *crtc = encoder->crtc;
int ret = 0; int ret = 0;
bool changed = false; bool changed = false;
...@@ -1494,30 +1496,30 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop ...@@ -1494,30 +1496,30 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
goto out; goto out;
if (property == dev->mode_config.tv_left_margin_property && if (property == dev->mode_config.tv_left_margin_property &&
tv_priv->margin[TV_MARGIN_LEFT] != val) { intel_tv->margin[TV_MARGIN_LEFT] != val) {
tv_priv->margin[TV_MARGIN_LEFT] = val; intel_tv->margin[TV_MARGIN_LEFT] = val;
changed = true; changed = true;
} else if (property == dev->mode_config.tv_right_margin_property && } else if (property == dev->mode_config.tv_right_margin_property &&
tv_priv->margin[TV_MARGIN_RIGHT] != val) { intel_tv->margin[TV_MARGIN_RIGHT] != val) {
tv_priv->margin[TV_MARGIN_RIGHT] = val; intel_tv->margin[TV_MARGIN_RIGHT] = val;
changed = true; changed = true;
} else if (property == dev->mode_config.tv_top_margin_property && } else if (property == dev->mode_config.tv_top_margin_property &&
tv_priv->margin[TV_MARGIN_TOP] != val) { intel_tv->margin[TV_MARGIN_TOP] != val) {
tv_priv->margin[TV_MARGIN_TOP] = val; intel_tv->margin[TV_MARGIN_TOP] = val;
changed = true; changed = true;
} else if (property == dev->mode_config.tv_bottom_margin_property && } else if (property == dev->mode_config.tv_bottom_margin_property &&
tv_priv->margin[TV_MARGIN_BOTTOM] != val) { intel_tv->margin[TV_MARGIN_BOTTOM] != val) {
tv_priv->margin[TV_MARGIN_BOTTOM] = val; intel_tv->margin[TV_MARGIN_BOTTOM] = val;
changed = true; changed = true;
} else if (property == dev->mode_config.tv_mode_property) { } else if (property == dev->mode_config.tv_mode_property) {
if (val >= ARRAY_SIZE(tv_modes)) { if (val >= ARRAY_SIZE(tv_modes)) {
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
if (!strcmp(tv_priv->tv_format, tv_modes[val].name)) if (!strcmp(intel_tv->tv_format, tv_modes[val].name))
goto out; goto out;
tv_priv->tv_format = tv_modes[val].name; intel_tv->tv_format = tv_modes[val].name;
changed = true; changed = true;
} else { } else {
ret = -EINVAL; ret = -EINVAL;
...@@ -1553,16 +1555,8 @@ static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = ...@@ -1553,16 +1555,8 @@ static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs =
.best_encoder = intel_attached_encoder, .best_encoder = intel_attached_encoder,
}; };
static void intel_tv_enc_destroy(struct drm_encoder *encoder)
{
struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
drm_encoder_cleanup(encoder);
kfree(intel_encoder);
}
static const struct drm_encoder_funcs intel_tv_enc_funcs = { static const struct drm_encoder_funcs intel_tv_enc_funcs = {
.destroy = intel_tv_enc_destroy, .destroy = intel_encoder_destroy,
}; };
/* /*
...@@ -1606,9 +1600,9 @@ intel_tv_init(struct drm_device *dev) ...@@ -1606,9 +1600,9 @@ intel_tv_init(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_connector *connector; struct drm_connector *connector;
struct intel_tv *intel_tv;
struct intel_encoder *intel_encoder; struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector; struct intel_connector *intel_connector;
struct intel_tv_priv *tv_priv;
u32 tv_dac_on, tv_dac_off, save_tv_dac; u32 tv_dac_on, tv_dac_off, save_tv_dac;
char **tv_format_names; char **tv_format_names;
int i, initial_mode = 0; int i, initial_mode = 0;
...@@ -1647,18 +1641,18 @@ intel_tv_init(struct drm_device *dev) ...@@ -1647,18 +1641,18 @@ intel_tv_init(struct drm_device *dev)
(tv_dac_off & TVDAC_STATE_CHG_EN) != 0) (tv_dac_off & TVDAC_STATE_CHG_EN) != 0)
return; return;
intel_encoder = kzalloc(sizeof(struct intel_encoder) + intel_tv = kzalloc(sizeof(struct intel_tv), GFP_KERNEL);
sizeof(struct intel_tv_priv), GFP_KERNEL); if (!intel_tv) {
if (!intel_encoder) {
return; return;
} }
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
if (!intel_connector) { if (!intel_connector) {
kfree(intel_encoder); kfree(intel_tv);
return; return;
} }
intel_encoder = &intel_tv->base;
connector = &intel_connector->base; connector = &intel_connector->base;
drm_connector_init(dev, connector, &intel_tv_connector_funcs, drm_connector_init(dev, connector, &intel_tv_connector_funcs,
...@@ -1668,22 +1662,20 @@ intel_tv_init(struct drm_device *dev) ...@@ -1668,22 +1662,20 @@ intel_tv_init(struct drm_device *dev)
DRM_MODE_ENCODER_TVDAC); DRM_MODE_ENCODER_TVDAC);
drm_mode_connector_attach_encoder(&intel_connector->base, &intel_encoder->enc); drm_mode_connector_attach_encoder(&intel_connector->base, &intel_encoder->enc);
tv_priv = (struct intel_tv_priv *)(intel_encoder + 1);
intel_encoder->type = INTEL_OUTPUT_TVOUT; intel_encoder->type = INTEL_OUTPUT_TVOUT;
intel_encoder->crtc_mask = (1 << 0) | (1 << 1); intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT); intel_encoder->clone_mask = (1 << INTEL_TV_CLONE_BIT);
intel_encoder->enc.possible_crtcs = ((1 << 0) | (1 << 1)); intel_encoder->enc.possible_crtcs = ((1 << 0) | (1 << 1));
intel_encoder->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT); intel_encoder->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
intel_encoder->dev_priv = tv_priv; intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
tv_priv->type = DRM_MODE_CONNECTOR_Unknown;
/* BIOS margin values */ /* BIOS margin values */
tv_priv->margin[TV_MARGIN_LEFT] = 54; intel_tv->margin[TV_MARGIN_LEFT] = 54;
tv_priv->margin[TV_MARGIN_TOP] = 36; intel_tv->margin[TV_MARGIN_TOP] = 36;
tv_priv->margin[TV_MARGIN_RIGHT] = 46; intel_tv->margin[TV_MARGIN_RIGHT] = 46;
tv_priv->margin[TV_MARGIN_BOTTOM] = 37; intel_tv->margin[TV_MARGIN_BOTTOM] = 37;
tv_priv->tv_format = kstrdup(tv_modes[initial_mode].name, GFP_KERNEL); intel_tv->tv_format = kstrdup(tv_modes[initial_mode].name, GFP_KERNEL);
drm_encoder_helper_add(&intel_encoder->enc, &intel_tv_helper_funcs); drm_encoder_helper_add(&intel_encoder->enc, &intel_tv_helper_funcs);
drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs); drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
...@@ -1703,16 +1695,16 @@ intel_tv_init(struct drm_device *dev) ...@@ -1703,16 +1695,16 @@ intel_tv_init(struct drm_device *dev)
initial_mode); initial_mode);
drm_connector_attach_property(connector, drm_connector_attach_property(connector,
dev->mode_config.tv_left_margin_property, dev->mode_config.tv_left_margin_property,
tv_priv->margin[TV_MARGIN_LEFT]); intel_tv->margin[TV_MARGIN_LEFT]);
drm_connector_attach_property(connector, drm_connector_attach_property(connector,
dev->mode_config.tv_top_margin_property, dev->mode_config.tv_top_margin_property,
tv_priv->margin[TV_MARGIN_TOP]); intel_tv->margin[TV_MARGIN_TOP]);
drm_connector_attach_property(connector, drm_connector_attach_property(connector,
dev->mode_config.tv_right_margin_property, dev->mode_config.tv_right_margin_property,
tv_priv->margin[TV_MARGIN_RIGHT]); intel_tv->margin[TV_MARGIN_RIGHT]);
drm_connector_attach_property(connector, drm_connector_attach_property(connector,
dev->mode_config.tv_bottom_margin_property, dev->mode_config.tv_bottom_margin_property,
tv_priv->margin[TV_MARGIN_BOTTOM]); intel_tv->margin[TV_MARGIN_BOTTOM]);
out: out:
drm_sysfs_connector_add(connector); drm_sysfs_connector_add(connector);
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册