Merge branch 'modesetting-101-encoders' into modesetting-101

This commit is contained in:
Dave Airlie 2008-06-02 12:58:10 +10:00
commit eba6cdc936
29 changed files with 1932 additions and 1478 deletions

View file

@ -109,7 +109,7 @@ void drmModeFreeCrtc(drmModeCrtcPtr ptr)
}
void drmModeFreeOutput(drmModeOutputPtr ptr)
void drmModeFreeConnector(drmModeConnectorPtr ptr)
{
if (!ptr)
return;
@ -119,6 +119,11 @@ void drmModeFreeOutput(drmModeOutputPtr ptr)
}
void drmModeFreeEncoder(drmModeEncoderPtr ptr)
{
drmFree(ptr);
}
/*
* ModeSetting functions.
*/
@ -137,8 +142,10 @@ drmModeResPtr drmModeGetResources(int fd)
res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t)));
if (res.count_crtcs)
res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t)));
if (res.count_outputs)
res.output_id_ptr = VOID2U64(drmMalloc(res.count_outputs*sizeof(uint32_t)));
if (res.count_connectors)
res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t)));
if (res.count_encoders)
res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t)));
if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) {
r = NULL;
@ -159,16 +166,19 @@ drmModeResPtr drmModeGetResources(int fd)
r->max_height = res.max_height;
r->count_fbs = res.count_fbs;
r->count_crtcs = res.count_crtcs;
r->count_outputs = res.count_outputs;
r->count_connectors = res.count_connectors;
r->count_encoders = res.count_encoders;
/* TODO we realy should test if these allocs fails. */
r->fbs = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t));
r->crtcs = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t));
r->outputs = drmAllocCpy(U642VOID(res.output_id_ptr), res.count_outputs, sizeof(uint32_t));
r->connectors = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t));
r->encoders = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t));
err_allocs:
drmFree(U642VOID(res.fb_id_ptr));
drmFree(U642VOID(res.crtc_id_ptr));
drmFree(U642VOID(res.output_id_ptr));
drmFree(U642VOID(res.connector_id_ptr));
drmFree(U642VOID(res.encoder_id_ptr));
return r;
}
@ -244,10 +254,6 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
struct drm_mode_crtc crtc;
drmModeCrtcPtr r;
crtc.count_outputs = 0;
crtc.outputs = 0;
crtc.count_possibles = 0;
crtc.possibles = 0;
crtc.crtc_id = crtcId;
if (ioctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc))
@ -268,24 +274,18 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo));
r->buffer_id = crtc.fb_id;
r->gamma_size = crtc.gamma_size;
r->count_outputs = crtc.count_outputs;
r->count_possibles = crtc.count_possibles;
/* TODO we realy should test if these alloc & cpy fails. */
r->outputs = crtc.outputs;
r->possibles = crtc.possibles;
return r;
}
int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
uint32_t x, uint32_t y, uint32_t *outputs, int count,
uint32_t x, uint32_t y, uint32_t *connectors, int count,
struct drm_mode_modeinfo *mode)
{
struct drm_mode_crtc crtc;
crtc.count_outputs = 0;
crtc.outputs = 0;
crtc.count_connectors = 0;
crtc.connectors = 0;
crtc.count_possibles = 0;
crtc.possibles = 0;
@ -293,8 +293,8 @@ int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
crtc.y = y;
crtc.crtc_id = crtcId;
crtc.fb_id = bufferId;
crtc.set_outputs_ptr = VOID2U64(outputs);
crtc.count_outputs = count;
crtc.set_connectors_ptr = VOID2U64(connectors);
crtc.count_connectors = count;
if (mode) {
memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo));
crtc.mode_valid = 1;
@ -334,88 +334,116 @@ int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y)
}
/*
* Output manipulation
* Encoder get
*/
drmModeOutputPtr drmModeGetOutput(int fd, uint32_t output_id)
drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id)
{
struct drm_mode_get_output out;
drmModeOutputPtr r = NULL;
struct drm_mode_get_encoder enc;
drmModeEncoderPtr r = NULL;
out.output = output_id;
out.output_type_id = 0;
out.output_type = 0;
out.count_crtcs = 0;
out.crtcs = 0;
out.count_clones = 0;
out.clones = 0;
out.count_modes = 0;
out.modes_ptr = 0;
out.count_props = 0;
out.props_ptr = 0;
out.prop_values_ptr = 0;
enc.encoder_id = encoder_id;
enc.encoder_type = 0;
enc.crtcs = 0;
enc.clones = 0;
if (ioctl(fd, DRM_IOCTL_MODE_GETOUTPUT, &out))
if (ioctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc))
return 0;
if (out.count_props) {
out.props_ptr = VOID2U64(drmMalloc(out.count_props*sizeof(uint32_t)));
out.prop_values_ptr = VOID2U64(drmMalloc(out.count_props*sizeof(uint64_t)));
if (!(r = drmMalloc(sizeof(*r))))
return 0;
r->encoder_id = enc.encoder_id;
r->crtc = enc.crtc;
r->encoder_type = enc.encoder_type;
r->crtcs = enc.crtcs;
r->clones = enc.clones;
return r;
}
/*
* Connector manipulation
*/
drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
{
struct drm_mode_get_connector conn;
drmModeConnectorPtr r = NULL;
conn.connector = connector_id;
conn.connector_type_id = 0;
conn.connector_type = 0;
conn.count_modes = 0;
conn.modes_ptr = 0;
conn.count_props = 0;
conn.props_ptr = 0;
conn.prop_values_ptr = 0;
conn.count_encoders = 0;
conn.encoders_ptr = 0;
if (ioctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
return 0;
if (conn.count_props) {
conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t)));
conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t)));
}
if (out.count_modes)
out.modes_ptr = VOID2U64(drmMalloc(out.count_modes*sizeof(struct drm_mode_modeinfo)));
if (conn.count_modes)
conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo)));
if (ioctl(fd, DRM_IOCTL_MODE_GETOUTPUT, &out))
if (conn.count_encoders)
conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t)));
if (ioctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
goto err_allocs;
if(!(r = drmMalloc(sizeof(*r)))) {
goto err_allocs;
}
r->output_id = out.output;
r->crtc = out.crtc;
r->connection = out.connection;
r->mmWidth = out.mm_width;
r->mmHeight = out.mm_height;
r->subpixel = out.subpixel;
r->count_crtcs = out.count_crtcs;
r->count_clones = out.count_clones;
r->count_modes = out.count_modes;
r->connector_id = conn.connector;
r->encoder = conn.encoder;
r->connection = conn.connection;
r->mmWidth = conn.mm_width;
r->mmHeight = conn.mm_height;
r->subpixel = conn.subpixel;
r->count_modes = conn.count_modes;
/* TODO we should test if these alloc & cpy fails. */
r->crtcs = out.crtcs;
r->clones = out.clones;
r->count_props = out.count_props;
r->props = drmAllocCpy(U642VOID(out.props_ptr), out.count_props, sizeof(uint32_t));
r->prop_values = drmAllocCpy(U642VOID(out.prop_values_ptr), out.count_props, sizeof(uint64_t));
r->modes = drmAllocCpy(U642VOID(out.modes_ptr), out.count_modes, sizeof(struct drm_mode_modeinfo));
r->output_type = out.output_type;
r->output_type_id = out.output_type_id;
r->count_props = conn.count_props;
r->props = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t));
r->prop_values = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t));
r->modes = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo));
r->count_encoders = conn.count_encoders;
r->encoders = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t));
r->connector_type = conn.connector_type;
r->connector_type_id = conn.connector_type_id;
err_allocs:
drmFree(U642VOID(out.prop_values_ptr));
drmFree(U642VOID(out.props_ptr));
drmFree(U642VOID(out.modes_ptr));
drmFree(U642VOID(conn.prop_values_ptr));
drmFree(U642VOID(conn.props_ptr));
drmFree(U642VOID(conn.modes_ptr));
drmFree(U642VOID(conn.encoders_ptr));
return r;
}
int drmModeAttachMode(int fd, uint32_t output_id, struct drm_mode_modeinfo *mode_info)
int drmModeAttachMode(int fd, uint32_t connector_id, struct drm_mode_modeinfo *mode_info)
{
struct drm_mode_mode_cmd res;
memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
res.output_id = output_id;
res.connector_id = connector_id;
return ioctl(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
}
int drmModeDetachMode(int fd, uint32_t output_id, struct drm_mode_modeinfo *mode_info)
int drmModeDetachMode(int fd, uint32_t connector_id, struct drm_mode_modeinfo *mode_info)
{
struct drm_mode_mode_cmd res;
memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
res.output_id = output_id;
res.connector_id = connector_id;
return ioctl(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
}
@ -530,13 +558,13 @@ void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)
drmFree(ptr);
}
int drmModeOutputSetProperty(int fd, uint32_t output_id, uint32_t property_id,
int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id,
uint64_t value)
{
struct drm_mode_output_set_property osp;
struct drm_mode_connector_set_property osp;
int ret;
osp.output_id = output_id;
osp.connector_id = connector_id;
osp.prop_id = property_id;
osp.value = value;

View file

@ -60,8 +60,11 @@ typedef struct _drmModeRes {
int count_crtcs;
uint32_t *crtcs;
int count_outputs;
uint32_t *outputs;
int count_connectors;
uint32_t *connectors;
int count_encoders;
uint32_t *encoders;
uint32_t min_width, max_width;
uint32_t min_height, max_height;
@ -96,16 +99,24 @@ typedef struct _drmModeCrtc {
int mode_valid;
struct drm_mode_modeinfo mode;
int count_outputs;
uint32_t outputs; /**< Outputs that are connected */
int count_connectors;
uint32_t connectors; /**< Connectors that are connected */
int count_possibles;
uint32_t possibles; /**< Outputs that can be connected */
uint32_t possibles; /**< Connectors that can be connected */
int gamma_size; /**< Number of gamma stops */
} drmModeCrtc, *drmModeCrtcPtr;
typedef struct _drmModeEncoder {
unsigned int encoder_id;
unsigned int encoder_type;
uint32_t crtc;
uint32_t crtcs;
uint32_t clones;
} drmModeEncoder, *drmModeEncoderPtr;
typedef enum {
DRM_MODE_CONNECTED = 1,
DRM_MODE_DISCONNECTED = 2,
@ -121,22 +132,16 @@ typedef enum {
DRM_MODE_SUBPIXEL_NONE = 6
} drmModeSubPixel;
typedef struct _drmModeOutput {
unsigned int output_id;
typedef struct _drmModeConnector {
unsigned int connector_id;
unsigned int crtc; /**< Crtc currently connected to */
unsigned int output_type;
unsigned int output_type_id;
unsigned int encoder; /**< Crtc currently connected to */
unsigned int connector_type;
unsigned int connector_type_id;
drmModeConnection connection;
uint32_t mmWidth, mmHeight; /**< HxW in millimeters */
drmModeSubPixel subpixel;
int count_crtcs;
uint32_t crtcs; /**< Possible crtc to connect to */
int count_clones;
uint32_t clones; /**< Mask of clones */
int count_modes;
struct drm_mode_modeinfo *modes;
@ -144,7 +149,9 @@ typedef struct _drmModeOutput {
uint32_t *props; /**< List of property ids */
uint64_t *prop_values; /**< List of property values */
} drmModeOutput, *drmModeOutputPtr;
int count_encoders;
uint32_t *encoders; /**< List of encoder ids */
} drmModeConnector, *drmModeConnectorPtr;
@ -152,7 +159,8 @@ extern void drmModeFreeModeInfo( struct drm_mode_modeinfo *ptr );
extern void drmModeFreeResources( drmModeResPtr ptr );
extern void drmModeFreeFB( drmModeFBPtr ptr );
extern void drmModeFreeCrtc( drmModeCrtcPtr ptr );
extern void drmModeFreeOutput( drmModeOutputPtr ptr );
extern void drmModeFreeConnector( drmModeConnectorPtr ptr );
extern void drmModeFreeEncoder( drmModeEncoderPtr ptr );
/**
* Retrives all of the resources associated with a card.
@ -204,7 +212,7 @@ extern drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId);
* Set the mode on a crtc crtcId with the given mode modeId.
*/
int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
uint32_t x, uint32_t y, uint32_t *outputs, int count,
uint32_t x, uint32_t y, uint32_t *connectors, int count,
struct drm_mode_modeinfo *mode);
/*
@ -221,32 +229,37 @@ int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width
*/
int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y);
/**
* Encoder functions
*/
drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id);
/*
* Output manipulation
* Connector manipulation
*/
/**
* Retrive information about the output outputId.
* Retrive information about the connector connectorId.
*/
extern drmModeOutputPtr drmModeGetOutput(int fd,
uint32_t outputId);
extern drmModeConnectorPtr drmModeGetConnector(int fd,
uint32_t connectorId);
/**
* Attaches the given mode to an output.
* Attaches the given mode to an connector.
*/
extern int drmModeAttachMode(int fd, uint32_t outputId, struct drm_mode_modeinfo *mode_info);
extern int drmModeAttachMode(int fd, uint32_t connectorId, struct drm_mode_modeinfo *mode_info);
/**
* Detaches a mode from the output
* Detaches a mode from the connector
* must be unused, by the given mode.
*/
extern int drmModeDetachMode(int fd, uint32_t outputId, struct drm_mode_modeinfo *mode_info);
extern int drmModeDetachMode(int fd, uint32_t connectorId, struct drm_mode_modeinfo *mode_info);
extern drmModePropertyPtr drmModeGetProperty(int fd, uint32_t propertyId);
extern void drmModeFreeProperty(drmModePropertyPtr ptr);
extern drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id);
extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr);
extern int drmModeOutputSetProperty(int fd, uint32_t output_id, uint32_t property_id,
extern int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id,
uint64_t value);
extern int drmCheckModesettingSupported(const char *busid);

View file

@ -743,7 +743,7 @@ struct drm_driver {
struct drm_set_version *sv);
/* FB routines, if present */
int (*fb_probe)(struct drm_device *dev, struct drm_crtc *crtc, struct drm_output *output);
int (*fb_probe)(struct drm_device *dev, struct drm_crtc *crtc, struct drm_connector *connector);
int (*fb_remove)(struct drm_device *dev, struct drm_framebuffer *fb);
int (*fb_resize)(struct drm_device *dev, struct drm_crtc *crtc);
@ -1317,9 +1317,9 @@ extern void drm_sysfs_destroy(void);
extern int drm_sysfs_device_add(struct drm_minor *minor);
extern void drm_sysfs_hotplug_event(struct drm_device *dev);
extern void drm_sysfs_device_remove(struct drm_minor *minor);
extern char *drm_get_output_status_name(enum drm_output_status status);
extern int drm_sysfs_output_add(struct drm_output *output);
extern void drm_sysfs_output_remove(struct drm_output *output);
extern char *drm_get_connector_status_name(enum drm_connector_status status);
extern int drm_sysfs_connector_add(struct drm_connector *connector);
extern void drm_sysfs_connector_remove(struct drm_connector *connector);
/*
* Basic memory manager support (drm_mm.c)

File diff suppressed because it is too large Load diff

View file

@ -17,10 +17,10 @@ struct drm_device;
struct drm_mode_set;
/*
* Note on terminology: here, for brevity and convenience, we refer to output
* control chips as 'CRTCs'. They can control any type of output, VGA, LVDS,
* Note on terminology: here, for brevity and convenience, we refer to connector
* control chips as 'CRTCs'. They can control any type of connector, VGA, LVDS,
* DVI, etc. And 'screen' refers to the whole of the visible display, which
* may span multiple monitors (and therefore multiple CRTC and output
* may span multiple monitors (and therefore multiple CRTC and connector
* structures).
*/
@ -80,7 +80,7 @@ struct drm_display_mode {
struct list_head head;
char name[DRM_DISPLAY_MODE_LEN];
int mode_id;
int output_count;
int connector_count;
enum drm_mode_status status;
int type;
@ -149,24 +149,24 @@ struct drm_display_mode {
#define DPMSModeSuspend 2
#define DPMSModeOff 3
#define ConnectorUnknown 0
#define ConnectorVGA 1
#define ConnectorDVII 2
#define ConnectorDVID 3
#define ConnectorDVIA 4
#define ConnectorComposite 5
#define ConnectorSVIDEO 6
#define ConnectorLVDS 7
#define ConnectorComponent 8
#define Connector9PinDIN 9
#define ConnectorDisplayPort 10
#define ConnectorHDMIA 11
#define ConnectorHDMIB 12
#define DRM_MODE_CONNECTOR_Unknown 0
#define DRM_MODE_CONNECTOR_VGA 1
#define DRM_MODE_CONNECTOR_DVII 2
#define DRM_MODE_CONNECTOR_DVID 3
#define DRM_MODE_CONNECTOR_DVIA 4
#define DRM_MODE_CONNECTOR_Composite 5
#define DRM_MODE_CONNECTOR_SVIDEO 6
#define DRM_MODE_CONNECTOR_LVDS 7
#define DRM_MODE_CONNECTOR_Component 8
#define DRM_MODE_CONNECTOR_9PinDIN 9
#define DRM_MODE_CONNECTOR_DisplayPort 10
#define DRM_MODE_CONNECTOR_HDMIA 11
#define DRM_MODE_CONNECTOR_HDMIB 12
enum drm_output_status {
output_status_connected = 1,
output_status_disconnected = 2,
output_status_unknown = 3,
enum drm_connector_status {
connector_status_connected = 1,
connector_status_disconnected = 2,
connector_status_unknown = 3,
};
enum subpixel_order {
@ -276,7 +276,8 @@ struct drm_property {
};
struct drm_crtc;
struct drm_output;
struct drm_connector;
struct drm_encoder;
/**
* drm_crtc_funcs - control CRTCs for a given device
@ -294,21 +295,15 @@ struct drm_output;
* @destroy: deinit and free object.
*
* The drm_crtc_funcs structure is the central CRTC management structure
* in the DRM. Each CRTC controls one or more outputs (note that the name
* in the DRM. Each CRTC controls one or more connectors (note that the name
* CRTC is simply historical, a CRTC may control LVDS, VGA, DVI, TV out, etc.
* outputs, not just CRTs).
* connectors, not just CRTs).
*
* Each driver is responsible for filling out this structure at startup time,
* in addition to providing other modesetting features, like i2c and DDC
* bus accessors.
*/
struct drm_crtc_funcs {
/*
* Control power levels on the CRTC. If the mode passed in is
* unsupported, the provider must use the next lowest power level.
*/
void (*dpms)(struct drm_crtc *crtc, int mode);
/* Save CRTC state */
void (*save)(struct drm_crtc *crtc); /* suspend? */
/* Restore CRTC state */
@ -338,7 +333,7 @@ struct drm_crtc_funcs {
* @desired_y: desired y for desired_mode
* @funcs: CRTC control functions
*
* Each CRTC may have one or more outputs associated with it. This structure
* Each CRTC may have one or more connectors associated with it. This structure
* allows the CRTC to be controlled.
*/
struct drm_crtc {
@ -347,7 +342,7 @@ struct drm_crtc {
int id; /* idr assigned */
/* framebuffer the output is currently bound to */
/* framebuffer the connector is currently bound to */
struct drm_framebuffer *fb;
bool enabled;
@ -364,96 +359,113 @@ struct drm_crtc {
};
/**
* drm_output_funcs - control outputs on a given device
* @init: setup this output
* drm_connector_funcs - control connectors on a given device
* @dpms: set power state (see drm_crtc_funcs above)
* @save: save output state
* @restore: restore output state
* @mode_valid: is this mode valid on the given output?
* @mode_fixup: try to fixup proposed mode for this output
* @save: save connector state
* @restore: restore connector state
* @mode_valid: is this mode valid on the given connector?
* @mode_fixup: try to fixup proposed mode for this connector
* @mode_set: set this mode
* @detect: is this output active?
* @get_modes: get mode list for this output
* @set_property: property for this output may need update
* @detect: is this connector active?
* @get_modes: get mode list for this connector
* @set_property: property for this connector may need update
* @destroy: make object go away
*
* Each CRTC may have one or more outputs attached to it. The functions
* below allow the core DRM code to control outputs, enumerate available modes,
* Each CRTC may have one or more connectors attached to it. The functions
* below allow the core DRM code to control connectors, enumerate available modes,
* etc.
*/
struct drm_output_funcs {
void (*init)(struct drm_output *output);
void (*dpms)(struct drm_output *output, int mode);
void (*save)(struct drm_output *output);
void (*restore)(struct drm_output *output);
enum drm_output_status (*detect)(struct drm_output *output);
int (*get_modes)(struct drm_output *output);
bool (*set_property)(struct drm_output *output, struct drm_property *property,
struct drm_connector_funcs {
void (*dpms)(struct drm_connector *connector, int mode);
void (*save)(struct drm_connector *connector);
void (*restore)(struct drm_connector *connector);
enum drm_connector_status (*detect)(struct drm_connector *connector);
void (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
bool (*set_property)(struct drm_connector *connector, struct drm_property *property,
uint64_t val);
void (*destroy)(struct drm_output *output);
int (*mode_valid)(struct drm_output *output,
struct drm_display_mode *mode);
void (*destroy)(struct drm_connector *connector);
};
#define DRM_OUTPUT_MAX_UMODES 16
#define DRM_OUTPUT_MAX_PROPERTY 16
#define DRM_OUTPUT_LEN 32
struct drm_encoder_funcs {
void (*destroy)(struct drm_encoder *encoder);
};
#define DRM_CONNECTOR_MAX_UMODES 16
#define DRM_CONNECTOR_MAX_PROPERTY 16
#define DRM_CONNECTOR_LEN 32
#define DRM_CONNECTOR_MAX_ENCODER 2
/**
* drm_output - central DRM output control structure
* @crtc: CRTC this output is currently connected to, NULL if none
* @possible_crtcs: bitmap of CRTCS this output could be attached to
* @possible_clones: bitmap of possible outputs this output could clone
* @interlace_allowed: can this output handle interlaced modes?
* @doublescan_allowed: can this output handle doublescan?
* @available_modes: modes available on this output (from get_modes() + user)
* @initial_x: initial x position for this output
* @initial_y: initial y position for this output
* @status: output connected?
* @funcs: output control functions
* drm_encoder - central DRM encoder structure
*/
struct drm_encoder {
struct drm_device *dev;
struct list_head head;
int id;
int encoder_type;
uint32_t possible_crtcs;
uint32_t possible_clones;
struct drm_crtc *crtc;
const struct drm_encoder_funcs *funcs;
void *helper_private;
};
/**
* drm_connector - central DRM connector control structure
* @crtc: CRTC this connector is currently connected to, NULL if none
* @interlace_allowed: can this connector handle interlaced modes?
* @doublescan_allowed: can this connector handle doublescan?
* @available_modes: modes available on this connector (from get_modes() + user)
* @initial_x: initial x position for this connector
* @initial_y: initial y position for this connector
* @status: connector connected?
* @funcs: connector control functions
*
* Each output may be connected to one or more CRTCs, or may be clonable by
* another output if they can share a CRTC. Each output also has a specific
* Each connector may be connected to one or more CRTCs, or may be clonable by
* another connector if they can share a CRTC. Each connector also has a specific
* position in the broader display (referred to as a 'screen' though it could
* span multiple monitors).
*/
struct drm_output {
struct drm_connector {
struct drm_device *dev;
struct device kdev;
struct device_attribute *attr;
struct list_head head;
struct drm_crtc *crtc;
int id; /* idr assigned */
int output_type;
int output_type_id;
unsigned long possible_crtcs;
unsigned long possible_clones;
int connector_type;
int connector_type_id;
bool interlace_allowed;
bool doublescan_allowed;
struct list_head modes; /* list of modes on this output */
struct list_head modes; /* list of modes on this connector */
int initial_x, initial_y;
enum drm_output_status status;
enum drm_connector_status status;
/* these are modes added by probing with DDC or the BIOS */
struct list_head probed_modes;
struct drm_display_info display_info;
const struct drm_output_funcs *funcs;
const struct drm_connector_funcs *funcs;
struct list_head user_modes;
struct drm_property_blob *edid_blob_ptr;
u32 property_ids[DRM_OUTPUT_MAX_PROPERTY];
uint64_t property_values[DRM_OUTPUT_MAX_PROPERTY];
u32 property_ids[DRM_CONNECTOR_MAX_PROPERTY];
uint64_t property_values[DRM_CONNECTOR_MAX_PROPERTY];
void *helper_private;
uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
uint32_t force_encoder_id;
struct drm_encoder *encoder; /* currently active encoder */
};
/**
* struct drm_mode_set
*
* Represents a single crtc the outputs that it drives with what mode
* Represents a single crtc the connectors that it drives with what mode
* and from which framebuffer it scans out from.
*
* This is used to set modes.
@ -467,8 +479,8 @@ struct drm_mode_set
uint32_t x;
uint32_t y;
struct drm_output **outputs;
size_t num_outputs;
struct drm_connector **connectors;
size_t num_connectors;
};
/**
@ -478,7 +490,7 @@ struct drm_mode_set
* Currently only a resize hook is available. DRM will call back into the
* driver with a new screen width and height. If the driver can't support
* the proposed size, it can return false. Otherwise it should adjust
* the CRTC<->output mappings as needed and update its view of the screen.
* the CRTC<->connector mappings as needed and update its view of the screen.
*/
struct drm_mode_config_funcs {
bool (*resize_fb)(struct drm_device *dev, struct drm_framebuffer *fb);
@ -490,12 +502,14 @@ struct drm_mode_config_funcs {
*/
struct drm_mode_config {
struct mutex mutex; /* protects configuration and IDR */
struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, output, modes - just makes life easier */
struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */
/* this is limited to one for now */
int num_fb;
struct list_head fb_list;
int num_output;
struct list_head output_list;
int num_connector;
struct list_head connector_list;
int num_encoder;
struct list_head encoder_list;
int num_crtc;
struct list_head crtc_list;
@ -511,8 +525,6 @@ struct drm_mode_config {
struct list_head property_blob_list;
struct drm_property *edid_property;
struct drm_property *dpms_property;
struct drm_property *connector_type_property;
struct drm_property *connector_num_property;
/* TV properties */
struct drm_property *tv_mode_property;
@ -531,22 +543,29 @@ extern void drm_crtc_init(struct drm_device *dev,
const struct drm_crtc_funcs *funcs);
extern void drm_crtc_cleanup(struct drm_crtc *crtc);
void drm_output_init(struct drm_device *dev,
struct drm_output *output,
const struct drm_output_funcs *funcs,
int output_type);
extern void drm_connector_init(struct drm_device *dev,
struct drm_connector *connector,
const struct drm_connector_funcs *funcs,
int connector_type);
void drm_output_cleanup(struct drm_output *output);
extern void drm_connector_cleanup(struct drm_connector *connector);
extern char *drm_get_output_name(struct drm_output *output);
extern void drm_encoder_init(struct drm_device *dev,
struct drm_encoder *encoder,
const struct drm_encoder_funcs *funcs,
int encoder_type);
extern void drm_encoder_cleanup(struct drm_encoder *encoder);
extern char *drm_get_connector_name(struct drm_connector *connector);
extern char *drm_get_dpms_name(int val);
extern void drm_fb_release(struct file *filp);
extern struct edid *drm_get_edid(struct drm_output *output,
extern struct edid *drm_get_edid(struct drm_connector *connector,
struct i2c_adapter *adapter);
extern int drm_add_edid_modes(struct drm_output *output, struct edid *edid);
extern void drm_mode_probed_add(struct drm_output *output, struct drm_display_mode *mode);
extern void drm_mode_remove(struct drm_output *output, struct drm_display_mode *mode);
extern int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid);
extern void drm_mode_probed_add(struct drm_connector *connector, struct drm_display_mode *mode);
extern void drm_mode_remove(struct drm_connector *connector, struct drm_display_mode *mode);
extern struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
struct drm_display_mode *mode);
extern void drm_mode_debug_printmodeline(struct drm_display_mode *mode);
@ -554,7 +573,6 @@ extern void drm_mode_config_init(struct drm_device *dev);
extern void drm_mode_config_cleanup(struct drm_device *dev);
extern void drm_mode_set_name(struct drm_display_mode *mode);
extern bool drm_mode_equal(struct drm_display_mode *mode1, struct drm_display_mode *mode2);
extern void drm_disable_unused_functions(struct drm_device *dev);
/* for us by fb module */
extern int drm_mode_attachmode_crtc(struct drm_device *dev,
@ -575,13 +593,13 @@ extern void drm_mode_sort(struct list_head *mode_list);
extern int drm_mode_vrefresh(struct drm_display_mode *mode);
extern void drm_mode_set_crtcinfo(struct drm_display_mode *p,
int adjust_flags);
extern void drm_mode_output_list_update(struct drm_output *output);
extern int drm_mode_output_update_edid_property(struct drm_output *output,
extern void drm_mode_connector_list_update(struct drm_connector *connector);
extern int drm_mode_connector_update_edid_property(struct drm_connector *connector,
struct edid *edid);
extern int drm_output_property_set_value(struct drm_output *output,
extern int drm_connector_property_set_value(struct drm_connector *connector,
struct drm_property *property,
uint64_t value);
extern int drm_output_property_get_value(struct drm_output *output,
extern int drm_connector_property_get_value(struct drm_connector *connector,
struct drm_property *property,
uint64_t *value);
extern struct drm_display_mode *drm_crtc_mode_create(struct drm_device *dev);
@ -591,10 +609,10 @@ extern struct drm_framebuffer *drm_framebuffer_create(struct drm_device *dev);
extern void drm_framebuffer_destroy(struct drm_framebuffer *fb);
extern int drmfb_probe(struct drm_device *dev, struct drm_crtc *crtc);
extern int drmfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
extern void drm_crtc_probe_output_modes(struct drm_device *dev, int maxX, int maxY);
extern void drm_crtc_probe_connector_modes(struct drm_device *dev, int maxX, int maxY);
extern bool drm_crtc_in_use(struct drm_crtc *crtc);
extern int drm_output_attach_property(struct drm_output *output,
extern int drm_connector_attach_property(struct drm_connector *connector,
struct drm_property *property, uint64_t init_val);
extern struct drm_property *drm_property_create(struct drm_device *dev, int flags,
const char *name, int num_values);
@ -603,6 +621,12 @@ extern int drm_property_add_enum(struct drm_property *property, int index,
uint64_t value, const char *name);
extern bool drm_create_tv_properties(struct drm_device *dev, int num_formats,
char *formats[]);
extern char *drm_get_encoder_name(struct drm_encoder *encoder);
extern int drm_mode_connector_attach_encoder(struct drm_connector *connector,
struct drm_encoder *encoder);
extern void drm_mode_connector_detach_encoder(struct drm_connector *connector,
struct drm_encoder *encoder);
/* IOCTLs */
extern int drm_mode_getresources(struct drm_device *dev,
@ -610,7 +634,7 @@ extern int drm_mode_getresources(struct drm_device *dev,
extern int drm_mode_getcrtc(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_getoutput(struct drm_device *dev,
extern int drm_mode_getconnector(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_setcrtc(struct drm_device *dev,
void *data, struct drm_file *file_priv);
@ -635,11 +659,13 @@ extern int drm_mode_getproperty_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_getblob_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_output_property_set_ioctl(struct drm_device *dev,
extern int drm_mode_connector_property_set_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_hotplug_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_replacefb(struct drm_device *dev,
void *data, struct drm_file *file_priv);
int drm_mode_getencoder(struct drm_device *dev,
void *data, struct drm_file *file_priv);
#endif /* __DRM_CRTC_H__ */

View file

@ -34,9 +34,168 @@
#include "drm_crtc.h"
#include "drm_crtc_helper.h"
/*
* Detailed mode info for a standard 640x480@60Hz monitor
*/
static struct drm_display_mode std_mode[] = {
{ DRM_MODE("640x480", DRM_MODE_TYPE_DEFAULT, 25200, 640, 656,
752, 800, 0, 480, 490, 492, 525, 0,
V_NHSYNC | V_NVSYNC) }, /* 640x480@60Hz */
};
/**
* drm_pick_crtcs - pick crtcs for output devices
* drm_helper_probe_connector_modes - get complete set of display modes
* @dev: DRM device
* @maxX: max width for modes
* @maxY: max height for modes
*
* LOCKING:
* Caller must hold mode config lock.
*
* Based on @dev's mode_config layout, scan all the connectors and try to detect
* modes on them. Modes will first be added to the connector's probed_modes
* list, then culled (based on validity and the @maxX, @maxY parameters) and
* put into the normal modes list.
*
* Intended to be used either at bootup time or when major configuration
* changes have occurred.
*
* FIXME: take into account monitor limits
*/
void drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY)
{
struct drm_device *dev = connector->dev;
struct drm_display_mode *mode, *t;
struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
int ret;
/* set all modes to the unverified state */
list_for_each_entry_safe(mode, t, &connector->modes, head)
mode->status = MODE_UNVERIFIED;
connector->status = (*connector->funcs->detect)(connector);
if (connector->status == connector_status_disconnected) {
DRM_DEBUG("%s is disconnected\n", drm_get_connector_name(connector));
/* TODO set EDID to NULL */
return;
}
ret = (*connector_funcs->get_modes)(connector);
if (ret) {
drm_mode_connector_list_update(connector);
}
if (maxX && maxY)
drm_mode_validate_size(dev, &connector->modes, maxX,
maxY, 0);
list_for_each_entry_safe(mode, t, &connector->modes, head) {
if (mode->status == MODE_OK)
mode->status = (*connector_funcs->mode_valid)(connector,mode);
}
drm_mode_prune_invalid(dev, &connector->modes, TRUE);
if (list_empty(&connector->modes)) {
struct drm_display_mode *stdmode;
DRM_DEBUG("No valid modes on %s\n", drm_get_connector_name(connector));
/* Should we do this here ???
* When no valid EDID modes are available we end up
* here and bailed in the past, now we add a standard
* 640x480@60Hz mode and carry on.
*/
stdmode = drm_mode_duplicate(dev, &std_mode[0]);
drm_mode_probed_add(connector, stdmode);
drm_mode_list_concat(&connector->probed_modes,
&connector->modes);
DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n",
drm_get_connector_name(connector));
}
drm_mode_sort(&connector->modes);
DRM_DEBUG("Probed modes for %s\n", drm_get_connector_name(connector));
list_for_each_entry_safe(mode, t, &connector->modes, head) {
mode->vrefresh = drm_mode_vrefresh(mode);
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
drm_mode_debug_printmodeline(mode);
}
}
EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
void drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX, uint32_t maxY)
{
struct drm_connector *connector;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
drm_helper_probe_single_connector_modes(connector, maxX, maxY);
}
}
EXPORT_SYMBOL(drm_helper_probe_connector_modes);
/**
* drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
* @crtc: CRTC to check
*
* LOCKING:
* Caller must hold mode config lock.
*
* Walk @crtc's DRM device's mode_config and see if it's in use.
*
* RETURNS:
* True if @crtc is part of the mode_config, false otherwise.
*/
bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
{
struct drm_encoder *encoder;
struct drm_device *dev = crtc->dev;
/* FIXME: Locking around list access? */
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
if (encoder->crtc == crtc)
return true;
return false;
}
EXPORT_SYMBOL(drm_helper_crtc_in_use);
/**
* drm_disable_unused_functions - disable unused objects
* @dev: DRM device
*
* LOCKING:
* Caller must hold mode config lock.
*
* If an connector or CRTC isn't part of @dev's mode_config, it can be disabled
* by calling its dpms function, which should power it off.
*/
void drm_helper_disable_unused_functions(struct drm_device *dev)
{
struct drm_encoder *encoder;
struct drm_encoder_helper_funcs *encoder_funcs;
struct drm_crtc *crtc;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
encoder_funcs = encoder->helper_private;
if (!encoder->crtc)
(*encoder_funcs->dpms)(encoder, DPMSModeOff);
}
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
if (!crtc->enabled)
crtc_funcs->dpms(crtc, DPMSModeOff);
}
}
EXPORT_SYMBOL(drm_helper_disable_unused_functions);
/**
* drm_pick_crtcs - pick crtcs for connector devices
* @dev: DRM device
*
* LOCKING:
@ -45,36 +204,44 @@
static void drm_pick_crtcs (struct drm_device *dev)
{
int c, o, assigned;
struct drm_output *output, *output_equal;
struct drm_connector *connector, *connector_equal;
struct drm_encoder *encoder, *encoder_equal;
struct drm_crtc *crtc;
struct drm_display_mode *des_mode = NULL, *modes, *modes_equal;
struct drm_connector_helper_funcs *connector_funcs;
int found;
list_for_each_entry(output, &dev->mode_config.output_list, head) {
output->crtc = NULL;
/* Don't hook up outputs that are disconnected ??
/* clean out all the encoder/crtc combos */
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
encoder->crtc = NULL;
}
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
connector_funcs = connector->helper_private;
connector->encoder = NULL;
/* Don't hook up connectors that are disconnected ??
*
* This is debateable. Do we want fixed /dev/fbX or
* dynamic on hotplug (need mode code for that though) ?
*
* If we don't hook up outputs now, then we only create
* /dev/fbX for the output that's enabled, that's good as
* the users console will be on that output.
* If we don't hook up connectors now, then we only create
* /dev/fbX for the connector that's enabled, that's good as
* the users console will be on that connector.
*
* If we do hook up outputs that are disconnected now, then
* If we do hook up connectors that are disconnected now, then
* the user may end up having to muck about with the fbcon
* map flags to assign his console to the enabled output. Ugh.
* map flags to assign his console to the enabled connector. Ugh.
*/
if (output->status != output_status_connected)
if (connector->status != connector_status_connected)
continue;
if (list_empty(&output->modes))
if (list_empty(&connector->modes))
continue;
des_mode = NULL;
found = 0;
list_for_each_entry(des_mode, &output->modes, head) {
list_for_each_entry(des_mode, &connector->modes, head) {
if (des_mode->type & DRM_MODE_TYPE_PREFERRED) {
found = 1;
break;
@ -84,25 +251,31 @@ static void drm_pick_crtcs (struct drm_device *dev)
/* No preferred mode, let's just select the first available */
if (!found) {
des_mode = NULL;
list_for_each_entry(des_mode, &output->modes, head) {
list_for_each_entry(des_mode, &connector->modes, head) {
break;
}
}
encoder = connector_funcs->best_encoder(connector);
if (!encoder)
continue;
connector->encoder = encoder;
c = -1;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
assigned = 0;
c++;
if ((output->possible_crtcs & (1 << c)) == 0)
if ((encoder->possible_crtcs & (1 << c)) == 0)
continue;
list_for_each_entry(output_equal, &dev->mode_config.output_list, head) {
if (output->id == output_equal->id)
list_for_each_entry(encoder_equal, &dev->mode_config.encoder_list, head) {
if (encoder->id == encoder_equal->id)
continue;
/* Find out if crtc has been assigned before */
if (output_equal->crtc == crtc)
if (encoder_equal->crtc == crtc)
assigned = 1;
}
@ -112,16 +285,21 @@ static void drm_pick_crtcs (struct drm_device *dev)
#endif
o = -1;
list_for_each_entry(output_equal, &dev->mode_config.output_list, head) {
list_for_each_entry(connector_equal, &dev->mode_config.connector_list, head) {
o++;
if (output->id == output_equal->id)
if (connector->id == connector_equal->id)
continue;
list_for_each_entry(modes, &output->modes, head) {
list_for_each_entry(modes_equal, &output_equal->modes, head) {
encoder_equal = connector_equal->encoder;
if (!encoder_equal)
continue;
list_for_each_entry(modes, &connector->modes, head) {
list_for_each_entry(modes_equal, &connector_equal->modes, head) {
if (drm_mode_equal (modes, modes_equal)) {
if ((output->possible_clones & output_equal->possible_clones) && (output_equal->crtc == crtc)) {
printk("Cloning %s (0x%lx) to %s (0x%lx)\n",drm_get_output_name(output),output->possible_clones,drm_get_output_name(output_equal),output_equal->possible_clones);
if ((encoder->possible_clones & encoder_equal->possible_clones) && (connector_equal->encoder->crtc == crtc)) {
printk("Cloning %s (0x%lx) to %s (0x%lx)\n",drm_get_connector_name(connector),encoder->possible_clones,drm_get_connector_name(connector_equal),encoder_equal->possible_clones);
des_mode = modes;
assigned = 0;
goto clone;
@ -137,10 +315,10 @@ clone:
continue;
/* Found a CRTC to attach to, do it ! */
output->crtc = crtc;
output->crtc->desired_mode = des_mode;
output->initial_x = 0;
output->initial_y = 0;
encoder->crtc = crtc;
encoder->crtc->desired_mode = des_mode;
connector->initial_x = 0;
connector->initial_y = 0;
DRM_DEBUG("Desired mode for CRTC %d is 0x%x:%s\n",c,des_mode->mode_id, des_mode->name);
break;
}
@ -158,7 +336,7 @@ EXPORT_SYMBOL(drm_pick_crtcs);
* LOCKING:
* Caller must hold mode config lock.
*
* Try to set @mode on @crtc. Give @crtc and its associated outputs a chance
* Try to set @mode on @crtc. Give @crtc and its associated connectors a chance
* to fixup or reject the mode prior to trying to set it.
*
* RETURNS:
@ -170,14 +348,14 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mo
struct drm_device *dev = crtc->dev;
struct drm_display_mode *adjusted_mode, saved_mode;
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
struct drm_output_helper_funcs *output_funcs;
struct drm_encoder_helper_funcs *encoder_funcs;
int saved_x, saved_y;
struct drm_output *output;
struct drm_encoder *encoder;
bool ret = true;
adjusted_mode = drm_mode_duplicate(dev, mode);
crtc->enabled = drm_crtc_in_use(crtc);
crtc->enabled = drm_helper_crtc_in_use(crtc);
if (!crtc->enabled)
return true;
@ -200,16 +378,16 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mo
}
}
/* Pass our mode to the outputs and the CRTC to give them a chance to
* adjust it according to limitations or output properties, and also
/* Pass our mode to the connectors and the CRTC to give them a chance to
* adjust it according to limitations or connector properties, and also
* a chance to reject the mode entirely.
*/
list_for_each_entry(output, &dev->mode_config.output_list, head) {
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (output->crtc != crtc)
if (encoder->crtc != crtc)
continue;
output_funcs = output->helper_private;
if (!(ret = output_funcs->mode_fixup(output, mode, adjusted_mode))) {
encoder_funcs = encoder->helper_private;
if (!(ret = encoder_funcs->mode_fixup(encoder, mode, adjusted_mode))) {
goto done;
}
}
@ -218,48 +396,44 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mo
goto done;
}
/* Prepare the outputs and CRTCs before setting the mode. */
list_for_each_entry(output, &dev->mode_config.output_list, head) {
/* Prepare the encoders and CRTCs before setting the mode. */
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (output->crtc != crtc)
if (encoder->crtc != crtc)
continue;
output_funcs = output->helper_private;
/* Disable the output as the first thing we do. */
output_funcs->prepare(output);
encoder_funcs = encoder->helper_private;
/* Disable the encoders as the first thing we do. */
encoder_funcs->prepare(encoder);
}
crtc_funcs->prepare(crtc);
/* Set up the DPLL and any output state that needs to adjust or depend
/* Set up the DPLL and any encoders state that needs to adjust or depend
* on the DPLL.
*/
crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y);
list_for_each_entry(output, &dev->mode_config.output_list, head) {
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (output->crtc != crtc)
if (encoder->crtc != crtc)
continue;
DRM_INFO("%s: set mode %s %x\n", drm_get_output_name(output), mode->name, mode->mode_id);
output_funcs = output->helper_private;
output_funcs->mode_set(output, mode, adjusted_mode);
DRM_INFO("%s: set mode %s %x\n", drm_get_encoder_name(encoder), mode->name, mode->mode_id);
encoder_funcs = encoder->helper_private;
encoder_funcs->mode_set(encoder, mode, adjusted_mode);
}
/* Now, enable the clocks, plane, pipe, and outputs that we set up. */
/* Now, enable the clocks, plane, pipe, and connectors that we set up. */
crtc_funcs->commit(crtc);
list_for_each_entry(output, &dev->mode_config.output_list, head) {
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (output->crtc != crtc)
if (encoder->crtc != crtc)
continue;
output_funcs = output->helper_private;
output_funcs->commit(output);
encoder_funcs = encoder->helper_private;
encoder_funcs->commit(encoder);
#if 0 // TODO def RANDR_12_INTERFACE
if (output->randr_output)
RRPostPendingProperties (output->randr_output);
#endif
}
/* XXX free adjustedmode */
@ -285,7 +459,7 @@ EXPORT_SYMBOL(drm_crtc_helper_set_mode);
* @crtc: CRTC to setup
* @crtc_info: user provided configuration
* @new_mode: new mode to set
* @output_set: set of outputs for the new config
* @connector_set: set of connectors for the new config
* @fb: new framebuffer
*
* LOCKING:
@ -301,12 +475,14 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
{
struct drm_device *dev;
struct drm_crtc **save_crtcs, *new_crtc;
struct drm_encoder **save_encoders, *new_encoder;
bool save_enabled;
bool changed = false;
bool flip_or_move = false;
struct drm_output *output;
int count = 0, ro;
struct drm_connector *connector;
int count = 0, ro, fail = 0;
struct drm_crtc_helper_funcs *crtc_funcs;
int ret = 0;
DRM_DEBUG("\n");
@ -321,17 +497,23 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
crtc_funcs = set->crtc->helper_private;
DRM_DEBUG("crtc: %p fb: %p outputs: %p num_outputs: %i (x, y) (%i, %i)\n", set->crtc, set->fb, set->outputs, set->num_outputs, set->x, set->y);
DRM_DEBUG("crtc: %p fb: %p connectors: %p num_connectors: %i (x, y) (%i, %i)\n", set->crtc, set->fb, set->connectors, set->num_connectors, set->x, set->y);
dev = set->crtc->dev;
/* save previous config */
save_enabled = set->crtc->enabled;
/* this is meant to be num_output not num_crtc */
save_crtcs = kzalloc(dev->mode_config.num_output * sizeof(struct drm_crtc *), GFP_KERNEL);
/* this is meant to be num_connector not num_crtc */
save_crtcs = kzalloc(dev->mode_config.num_connector * sizeof(struct drm_crtc *), GFP_KERNEL);
if (!save_crtcs)
return -ENOMEM;
save_encoders = kzalloc(dev->mode_config.num_connector * sizeof(struct drm_encoders *), GFP_KERNEL);
if (!save_encoders) {
kfree(save_crtcs);
return -ENOMEM;
}
/* We should be able to check here if the fb has the same properties
* and then just flip_or_move it */
if (set->crtc->fb != set->fb)
@ -347,21 +529,53 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
changed = true;
}
list_for_each_entry(output, &dev->mode_config.output_list, head) {
save_crtcs[count++] = output->crtc;
/* a) traverse passed in connector list and get encoders for them */
count = 0;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct drm_connector_helper_funcs *connector_funcs = connector->helper_private;
save_encoders[count++] = connector->encoder;
new_encoder = NULL;
for (ro = 0; ro < set->num_connectors; ro++) {
if (set->connectors[ro] == connector) {
new_encoder = connector_funcs->best_encoder(connector);
/* if we can't get an encoder for a connector
we are setting now - then fail */
if (new_encoder == NULL)
/* don't break so fail path works correct */
fail = 1;
break;
}
}
if (output->crtc == set->crtc)
if (new_encoder != connector->encoder) {
changed = true;
connector->encoder = new_encoder;
}
}
if (fail) {
ret = -EINVAL;
goto fail_no_encoder;
}
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (!connector->encoder)
continue;
save_crtcs[count++] = connector->encoder->crtc;
if (connector->encoder->crtc == set->crtc)
new_crtc = NULL;
else
new_crtc = output->crtc;
new_crtc = connector->encoder->crtc;
for (ro = 0; ro < set->num_outputs; ro++) {
if (set->outputs[ro] == output)
for (ro = 0; ro < set->num_connectors; ro++) {
if (set->connectors[ro] == connector)
new_crtc = set->crtc;
}
if (new_crtc != output->crtc) {
if (new_crtc != connector->encoder->crtc) {
changed = true;
output->crtc = new_crtc;
connector->encoder->crtc = new_crtc;
}
}
@ -376,40 +590,53 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
DRM_DEBUG("attempting to set mode from userspace\n");
drm_mode_debug_printmodeline(set->mode);
if (!drm_crtc_helper_set_mode(set->crtc, set->mode, set->x,
set->y)) {
set->crtc->enabled = save_enabled;
count = 0;
list_for_each_entry(output, &dev->mode_config.output_list, head)
output->crtc = save_crtcs[count++];
kfree(save_crtcs);
return -EINVAL;
set->y)) {
ret = -EINVAL;
goto fail_set_mode;
}
/* TODO are these needed? */
set->crtc->desired_x = set->x;
set->crtc->desired_y = set->y;
set->crtc->desired_mode = set->mode;
}
drm_disable_unused_functions(dev);
drm_helper_disable_unused_functions(dev);
} else if (flip_or_move) {
if (set->crtc->fb != set->fb)
set->crtc->fb = set->fb;
crtc_funcs->mode_set_base(set->crtc, set->x, set->y);
}
kfree(save_encoders);
kfree(save_crtcs);
return 0;
fail_set_mode:
set->crtc->enabled = save_enabled;
count = 0;
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
connector->encoder->crtc = save_crtcs[count++];
fail_no_encoder:
kfree(save_crtcs);
count = 0;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
connector->encoder = save_encoders[count++];
}
kfree(save_encoders);
return ret;
}
EXPORT_SYMBOL(drm_crtc_helper_set_config);
/**
* drm_initial_config - setup a sane initial output configuration
* drm_initial_config - setup a sane initial connector configuration
* @dev: DRM device
* @can_grow: this configuration is growable
*
* LOCKING:
* Called at init time, must take mode config lock.
*
* Scan the CRTCs and outputs and try to put together an initial setup.
* Scan the CRTCs and connectors and try to put together an initial setup.
* At the moment, this is a cloned configuration across all heads with
* a new framebuffer object as the backing store.
*
@ -418,35 +645,36 @@ EXPORT_SYMBOL(drm_crtc_helper_set_config);
*/
bool drm_helper_initial_config(struct drm_device *dev, bool can_grow)
{
struct drm_output *output;
struct drm_connector *connector;
int ret = false;
mutex_lock(&dev->mode_config.mutex);
drm_crtc_probe_output_modes(dev, 2048, 2048);
drm_helper_probe_connector_modes(dev, 2048, 2048);
drm_pick_crtcs(dev);
/* This is a little screwy, as we've already walked the outputs
/* This is a little screwy, as we've already walked the connectors
* above, but it's a little bit of magic too. There's the potential
* for things not to get setup above if an existing device gets
* re-assigned thus confusing the hardware. By walking the outputs
* re-assigned thus confusing the hardware. By walking the connectors
* this fixes up their crtc's.
*/
list_for_each_entry(output, &dev->mode_config.output_list, head) {
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
/* can't setup the output if there's no assigned mode */
if (!output->crtc || !output->crtc->desired_mode)
struct drm_crtc *crtc = connector->encoder->crtc;
/* can't setup the connector if there's no assigned mode */
if (!crtc || !crtc->desired_mode)
continue;
dev->driver->fb_probe(dev, output->crtc, output);
dev->driver->fb_probe(dev, crtc, connector);
/* and needs an attached fb */
if (output->crtc->fb)
drm_crtc_helper_set_mode(output->crtc, output->crtc->desired_mode, 0, 0);
if (crtc->fb)
drm_crtc_helper_set_mode(crtc, crtc->desired_mode, 0, 0);
}
drm_disable_unused_functions(dev);
drm_helper_disable_unused_functions(dev);
mutex_unlock(&dev->mode_config.mutex);
return ret;
@ -456,7 +684,7 @@ EXPORT_SYMBOL(drm_helper_initial_config);
/**
* drm_hotplug_stage_two
* @dev DRM device
* @output hotpluged output
* @connector hotpluged connector
*
* LOCKING.
* Caller must hold mode config lock, function might grab struct lock.
@ -466,7 +694,7 @@ EXPORT_SYMBOL(drm_helper_initial_config);
* RETURNS:
* Zero on success, errno on failure.
*/
int drm_helper_hotplug_stage_two(struct drm_device *dev, struct drm_output *output,
int drm_helper_hotplug_stage_two(struct drm_device *dev, struct drm_connector *connector,
bool connected)
{
int has_config = 0;
@ -479,37 +707,38 @@ int drm_helper_hotplug_stage_two(struct drm_device *dev, struct drm_output *outp
return 0;
}
if (output->crtc && output->crtc->desired_mode) {
DRM_DEBUG("drm thinks that the output already has a config\n");
if (connector->encoder->crtc && connector->encoder->crtc->desired_mode) {
DRM_DEBUG("drm thinks that the connector already has a config\n");
has_config = 1;
}
drm_crtc_probe_output_modes(dev, 2048, 2048);
drm_helper_probe_connector_modes(dev, 2048, 2048);
if (!has_config)
drm_pick_crtcs(dev);
if (!output->crtc || !output->crtc->desired_mode) {
DRM_DEBUG("could not find a desired mode or crtc for output\n");
if (!connector->encoder->crtc || !connector->encoder->crtc->desired_mode) {
DRM_DEBUG("could not find a desired mode or crtc for connector\n");
return 1;
}
/* We should really check if there is a fb using this crtc */
if (!has_config)
dev->driver->fb_probe(dev, output->crtc, output);
dev->driver->fb_probe(dev, connector->encoder->crtc, connector);
else {
dev->driver->fb_resize(dev, output->crtc);
dev->driver->fb_resize(dev, connector->encoder->crtc);
#if 0
if (!drm_crtc_set_mode(output->crtc, output->crtc->desired_mode, 0, 0))
if (!drm_crtc_set_mode(connector->encoder->crtc, connector->encoder->crtc->desired_mode, 0, 0))
DRM_ERROR("failed to set mode after hotplug\n");
#endif
}
drm_sysfs_hotplug_event(dev);
drm_disable_unused_functions(dev);
drm_helper_disable_unused_functions(dev);
return 0;
}
EXPORT_SYMBOL(drm_helper_hotplug_stage_two);

View file

@ -21,6 +21,11 @@
#include <linux/fb.h>
struct drm_crtc_helper_funcs {
/*
* Control power levels on the CRTC. If the mode passed in is
* unsupported, the provider must use the next lowest power level.
*/
void (*dpms)(struct drm_crtc *crtc, int mode);
void (*prepare)(struct drm_crtc *crtc);
void (*commit)(struct drm_crtc *crtc);
@ -36,32 +41,50 @@ struct drm_crtc_helper_funcs {
void (*mode_set_base)(struct drm_crtc *crtc, int x, int y);
};
struct drm_output_helper_funcs {
bool (*mode_fixup)(struct drm_output *output,
struct drm_encoder_helper_funcs {
void (*dpms)(struct drm_encoder *encoder, int mode);
void (*save)(struct drm_encoder *encoder);
void (*restore)(struct drm_encoder *encoder);
bool (*mode_fixup)(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
void (*prepare)(struct drm_output *output);
void (*commit)(struct drm_output *output);
void (*mode_set)(struct drm_output *output,
void (*prepare)(struct drm_encoder *encoder);
void (*commit)(struct drm_encoder *encoder);
void (*mode_set)(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
};
extern int drm_helper_hotplug_stage_two(struct drm_device *dev, struct drm_output *output,
struct drm_connector_helper_funcs {
int (*get_modes)(struct drm_connector *connector);
int (*mode_valid)(struct drm_connector *connector,
struct drm_display_mode *mode);
struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
};
extern void drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY);
extern void drm_helper_disable_unused_functions(struct drm_device *dev);
extern int drm_helper_hotplug_stage_two(struct drm_device *dev, struct drm_connector *connector,
bool connected);
extern bool drm_helper_initial_config(struct drm_device *dev, bool can_grow);
extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode,
int x, int y);
extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
static inline void drm_crtc_helper_add(struct drm_crtc *crtc, const struct drm_crtc_helper_funcs *funcs)
{
crtc->helper_private = (void *)funcs;
}
static inline void drm_output_helper_add(struct drm_output *output, const struct drm_output_helper_funcs *funcs)
static inline void drm_encoder_helper_add(struct drm_encoder *encoder, const struct drm_encoder_helper_funcs *funcs)
{
output->helper_private = (void *)funcs;
encoder->helper_private = (void *)funcs;
}
static inline void drm_connector_helper_add(struct drm_connector *connector, const struct drm_connector_helper_funcs *funcs)
{
connector->helper_private = (void *)funcs;
}

View file

@ -126,14 +126,14 @@ static struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETOUTPUT, drm_mode_getoutput, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_output_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
@ -142,6 +142,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_WAIT_HOTPLUG, drm_wait_hotplug, 0),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_REPLACEFB, drm_mode_replacefb, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_MASTER|DRM_ROOT_ONLY|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MM_INIT, drm_mm_init_ioctl,
DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),

View file

@ -211,9 +211,9 @@ static struct drm_display_mode edid_est_modes[] = {
* Each EDID block contains a bitmap of the supported "established modes" list
* (defined above). Tease them out and add them to the global modes list.
*/
static int add_established_modes(struct drm_output *output, struct edid *edid)
static int add_established_modes(struct drm_connector *connector, struct edid *edid)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
unsigned long est_bits = edid->established_timings.t1 |
(edid->established_timings.t2 << 8) |
((edid->established_timings.mfg_rsvd & 0x80) << 9);
@ -224,7 +224,7 @@ static int add_established_modes(struct drm_output *output, struct edid *edid)
struct drm_display_mode *newmode;
newmode = drm_mode_duplicate(dev, &edid_est_modes[i]);
if (newmode) {
drm_mode_probed_add(output, newmode);
drm_mode_probed_add(connector, newmode);
modes++;
}
}
@ -239,9 +239,9 @@ static int add_established_modes(struct drm_output *output, struct edid *edid)
* Standard modes can be calculated using the CVT standard. Grab them from
* @edid, calculate them, and add them to the list.
*/
static int add_standard_modes(struct drm_output *output, struct edid *edid)
static int add_standard_modes(struct drm_connector *connector, struct edid *edid)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
int i, modes = 0;
for (i = 0; i < EDID_STD_TIMINGS; i++) {
@ -254,7 +254,7 @@ static int add_standard_modes(struct drm_output *output, struct edid *edid)
newmode = drm_mode_std(dev, &edid->standard_timings[i]);
if (newmode) {
drm_mode_probed_add(output, newmode);
drm_mode_probed_add(connector, newmode);
modes++;
}
}
@ -269,9 +269,9 @@ static int add_standard_modes(struct drm_output *output, struct edid *edid)
* Some of the detailed timing sections may contain mode information. Grab
* it and add it to the list.
*/
static int add_detailed_info(struct drm_output *output, struct edid *edid)
static int add_detailed_info(struct drm_connector *connector, struct edid *edid)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
int i, j, modes = 0;
for (i = 0; i < EDID_DETAILED_TIMINGS; i++) {
@ -290,11 +290,11 @@ static int add_detailed_info(struct drm_output *output, struct edid *edid)
if (newmode) {
if (i == 0 && edid->preferred_timing)
newmode->type |= DRM_MODE_TYPE_PREFERRED;
drm_mode_probed_add(output, newmode);
drm_mode_probed_add(connector, newmode);
/* Use first one for output's preferred mode */
if (!output->display_info.preferred_mode)
output->display_info.preferred_mode =
/* Use first one for connector's preferred mode */
if (!connector->display_info.preferred_mode)
connector->display_info.preferred_mode =
newmode;
modes++;
}
@ -323,7 +323,7 @@ static int add_detailed_info(struct drm_output *output, struct edid *edid)
std = &data->data.timings[j];
newmode = drm_mode_std(dev, std);
if (newmode) {
drm_mode_probed_add(output, newmode);
drm_mode_probed_add(connector, newmode);
modes++;
}
}
@ -440,32 +440,32 @@ static unsigned char *drm_ddc_read(struct i2c_adapter *adapter)
/**
* drm_get_edid - get EDID data, if available
* @output: output we're probing
* @connector: connector we're probing
* @adapter: i2c adapter to use for DDC
*
* Poke the given output's i2c channel to grab EDID data if possible.
* Poke the given connector's i2c channel to grab EDID data if possible.
*
* Return edid data or NULL if we couldn't find any.
*/
struct edid *drm_get_edid(struct drm_output *output,
struct edid *drm_get_edid(struct drm_connector *connector,
struct i2c_adapter *adapter)
{
struct edid *edid;
edid = (struct edid *)drm_ddc_read(adapter);
if (!edid) {
dev_warn(&output->dev->pdev->dev, "%s: no EDID data\n",
drm_get_output_name(output));
dev_warn(&connector->dev->pdev->dev, "%s: no EDID data\n",
drm_get_connector_name(connector));
return NULL;
}
if (!edid_valid(edid)) {
dev_warn(&output->dev->pdev->dev, "%s: EDID invalid.\n",
drm_get_output_name(output));
dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
drm_get_connector_name(connector));
kfree(edid);
return NULL;
}
output->display_info.raw_edid = (char *)edid;
connector->display_info.raw_edid = (char *)edid;
return edid;
}
@ -473,14 +473,14 @@ EXPORT_SYMBOL(drm_get_edid);
/**
* drm_add_edid_modes - add modes from EDID data, if available
* @output: output we're probing
* @connector: connector we're probing
* @edid: edid data
*
* Add the specified modes to the output's mode list.
* Add the specified modes to the connector's mode list.
*
* Return number of modes added or 0 if we couldn't find any.
*/
int drm_add_edid_modes(struct drm_output *output, struct edid *edid)
int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
{
int num_modes = 0;
@ -488,31 +488,31 @@ int drm_add_edid_modes(struct drm_output *output, struct edid *edid)
return 0;
}
if (!edid_valid(edid)) {
dev_warn(&output->dev->pdev->dev, "%s: EDID invalid.\n",
drm_get_output_name(output));
dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
drm_get_connector_name(connector));
return 0;
}
num_modes += add_established_modes(output, edid);
num_modes += add_standard_modes(output, edid);
num_modes += add_detailed_info(output, edid);
num_modes += add_established_modes(connector, edid);
num_modes += add_standard_modes(connector, edid);
num_modes += add_detailed_info(connector, edid);
output->display_info.serration_vsync = edid->serration_vsync;
output->display_info.sync_on_green = edid->sync_on_green;
output->display_info.composite_sync = edid->composite_sync;
output->display_info.separate_syncs = edid->separate_syncs;
output->display_info.blank_to_black = edid->blank_to_black;
output->display_info.video_level = edid->video_level;
output->display_info.digital = edid->digital;
output->display_info.width_mm = edid->width_cm * 10;
output->display_info.height_mm = edid->height_cm * 10;
output->display_info.gamma = edid->gamma;
output->display_info.gtf_supported = edid->default_gtf;
output->display_info.standard_color = edid->standard_color;
output->display_info.display_type = edid->display_type;
output->display_info.active_off_supported = edid->pm_active_off;
output->display_info.suspend_supported = edid->pm_suspend;
output->display_info.standby_supported = edid->pm_standby;
output->display_info.gamma = edid->gamma;
connector->display_info.serration_vsync = edid->serration_vsync;
connector->display_info.sync_on_green = edid->sync_on_green;
connector->display_info.composite_sync = edid->composite_sync;
connector->display_info.separate_syncs = edid->separate_syncs;
connector->display_info.blank_to_black = edid->blank_to_black;
connector->display_info.video_level = edid->video_level;
connector->display_info.digital = edid->digital;
connector->display_info.width_mm = edid->width_cm * 10;
connector->display_info.height_mm = edid->height_cm * 10;
connector->display_info.gamma = edid->gamma;
connector->display_info.gtf_supported = edid->default_gtf;
connector->display_info.standard_color = edid->standard_color;
connector->display_info.display_type = edid->display_type;
connector->display_info.active_off_supported = edid->pm_active_off;
connector->display_info.suspend_supported = edid->pm_suspend;
connector->display_info.standby_supported = edid->pm_standby;
connector->display_info.gamma = edid->gamma;
return num_modes;
}

View file

@ -521,27 +521,27 @@ void drm_mode_sort(struct list_head *mode_list)
/**
* drm_mode_output_list_update - update the mode list for the output
* @output: the output to update
* drm_mode_connector_list_update - update the mode list for the connector
* @connector: the connector to update
*
* LOCKING:
* Caller must hold a lock protecting @mode_list.
*
* This moves the modes from the @output probed_modes list
* This moves the modes from the @connector probed_modes list
* to the actual mode list. It compares the probed mode against the current
* list and only adds different modes. All modes unverified after this point
* will be removed by the prune invalid modes.
*/
void drm_mode_output_list_update(struct drm_output *output)
void drm_mode_connector_list_update(struct drm_connector *connector)
{
struct drm_display_mode *mode;
struct drm_display_mode *pmode, *pt;
int found_it;
list_for_each_entry_safe(pmode, pt, &output->probed_modes,
list_for_each_entry_safe(pmode, pt, &connector->probed_modes,
head) {
found_it = 0;
/* go through current modes checking for the new probed mode */
list_for_each_entry(mode, &output->modes, head) {
list_for_each_entry(mode, &connector->modes, head) {
if (drm_mode_equal(pmode, mode)) {
found_it = 1;
/* if equal delete the probed mode */
@ -553,7 +553,7 @@ void drm_mode_output_list_update(struct drm_output *output)
}
if (!found_it) {
list_move_tail(&pmode->head, &output->modes);
list_move_tail(&pmode->head, &connector->modes);
}
}
}

View file

@ -147,27 +147,27 @@ static void drm_sysfs_device_release(struct device *dev)
}
/*
* Output properties
* Connector properties
*/
static ssize_t status_show(struct device *device,
struct device_attribute *attr,
char *buf)
{
struct drm_output *output = container_of(device, struct drm_output, kdev);
struct drm_connector *connector = container_of(device, struct drm_connector, kdev);
return snprintf(buf, PAGE_SIZE, "%s",
drm_get_output_status_name(output->funcs->detect(output)));
drm_get_connector_status_name(connector->funcs->detect(connector)));
}
static ssize_t dpms_show(struct device *device,
struct device_attribute *attr,
char *buf)
{
struct drm_output *output = container_of(device, struct drm_output, kdev);
struct drm_device *dev = output->dev;
struct drm_connector *connector = container_of(device, struct drm_connector, kdev);
struct drm_device *dev = connector->dev;
uint64_t dpms_status;
int ret;
ret = drm_output_property_get_value(output,
ret = drm_connector_property_get_value(connector,
dev->mode_config.dpms_property,
&dpms_status);
if (ret)
@ -179,17 +179,17 @@ static ssize_t dpms_show(struct device *device,
static ssize_t edid_show(struct kobject *kobj, struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{
struct device *output_dev = container_of(kobj, struct device, kobj);
struct drm_output *output = container_of(output_dev, struct drm_output,
struct device *connector_dev = container_of(kobj, struct device, kobj);
struct drm_connector *connector = container_of(connector_dev, struct drm_connector,
kdev);
unsigned char *edid;
size_t size;
if (!output->edid_blob_ptr)
if (!connector->edid_blob_ptr)
return 0;
edid = output->edid_blob_ptr->data;
size = output->edid_blob_ptr->length;
edid = connector->edid_blob_ptr->data;
size = connector->edid_blob_ptr->length;
if (!edid)
return 0;
@ -207,11 +207,11 @@ static ssize_t modes_show(struct device *device,
struct device_attribute *attr,
char *buf)
{
struct drm_output *output = container_of(device, struct drm_output, kdev);
struct drm_connector *connector = container_of(device, struct drm_connector, kdev);
struct drm_display_mode *mode;
int written = 0;
list_for_each_entry(mode, &output->modes, head) {
list_for_each_entry(mode, &connector->modes, head) {
written += snprintf(buf + written, PAGE_SIZE - written, "%s\n",
mode->name);
}
@ -219,7 +219,7 @@ static ssize_t modes_show(struct device *device,
return written;
}
static struct device_attribute output_attrs[] = {
static struct device_attribute connector_attrs[] = {
__ATTR_RO(status),
__ATTR_RO(dpms),
__ATTR_RO(modes),
@ -232,48 +232,48 @@ static struct bin_attribute edid_attr = {
};
/**
* drm_sysfs_output_add - add an output to sysfs
* @output: output to add
* drm_sysfs_connector_add - add an connector to sysfs
* @connector: connector to add
*
* Create an output device in sysfs, along with its associated output
* Create an connector device in sysfs, along with its associated connector
* properties (so far, connection status, dpms, mode list & edid) and
* generate a hotplug event so userspace knows there's a new output
* generate a hotplug event so userspace knows there's a new connector
* available.
*/
int drm_sysfs_output_add(struct drm_output *output)
int drm_sysfs_connector_add(struct drm_connector *connector)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
int ret = 0, i, j;
if (device_is_registered(&output->kdev))
if (device_is_registered(&connector->kdev))
return 0;
output->kdev.parent = &dev->primary->kdev;
output->kdev.class = drm_class;
output->kdev.release = drm_sysfs_device_release;
connector->kdev.parent = &dev->primary->kdev;
connector->kdev.class = drm_class;
connector->kdev.release = drm_sysfs_device_release;
DRM_DEBUG("adding \"%s\" to sysfs\n", drm_get_output_name(output));
DRM_DEBUG("adding \"%s\" to sysfs\n", drm_get_connector_name(connector));
snprintf(output->kdev.bus_id, BUS_ID_SIZE, "card%d-%s",
dev->primary->index, drm_get_output_name(output));
ret = device_register(&output->kdev);
snprintf(connector->kdev.bus_id, BUS_ID_SIZE, "card%d-%s",
dev->primary->index, drm_get_connector_name(connector));
ret = device_register(&connector->kdev);
if (ret) {
DRM_ERROR("failed to register output device: %d\n", ret);
DRM_ERROR("failed to register connector device: %d\n", ret);
goto out;
}
for (i = 0; i < ARRAY_SIZE(output_attrs); i++) {
ret = device_create_file(&output->kdev, &output_attrs[i]);
for (i = 0; i < ARRAY_SIZE(connector_attrs); i++) {
ret = device_create_file(&connector->kdev, &connector_attrs[i]);
if (ret)
goto err_out_files;
}
ret = sysfs_create_bin_file(&output->kdev.kobj, &edid_attr);
ret = sysfs_create_bin_file(&connector->kdev.kobj, &edid_attr);
if (ret)
goto err_out_files;
/* Let userspace know we have a new output */
/* Let userspace know we have a new connector */
drm_sysfs_hotplug_event(dev);
return 0;
@ -281,33 +281,33 @@ int drm_sysfs_output_add(struct drm_output *output)
err_out_files:
if (i > 0)
for (j = 0; j < i; j++)
device_remove_file(&output->kdev, &output_attrs[i]);
device_unregister(&output->kdev);
device_remove_file(&connector->kdev, &connector_attrs[i]);
device_unregister(&connector->kdev);
out:
return ret;
}
EXPORT_SYMBOL(drm_sysfs_output_add);
EXPORT_SYMBOL(drm_sysfs_connector_add);
/**
* drm_sysfs_output_remove - remove an output device from sysfs
* @output: output to remove
* drm_sysfs_connector_remove - remove an connector device from sysfs
* @connector: connector to remove
*
* Remove @output and its associated attributes from sysfs. Note that
* Remove @connector and its associated attributes from sysfs. Note that
* the device model core will take care of sending the "remove" uevent
* at this time, so we don't need to do it.
*/
void drm_sysfs_output_remove(struct drm_output *output)
void drm_sysfs_connector_remove(struct drm_connector *connector)
{
int i;
DRM_DEBUG("removing \"%s\" from sysfs\n", drm_get_output_name(output));
for (i = 0; i < ARRAY_SIZE(output_attrs); i++)
device_remove_file(&output->kdev, &output_attrs[i]);
sysfs_remove_bin_file(&output->kdev.kobj, &edid_attr);
device_unregister(&output->kdev);
DRM_DEBUG("removing \"%s\" from sysfs\n", drm_get_connector_name(connector));
for (i = 0; i < ARRAY_SIZE(connector_attrs); i++)
device_remove_file(&connector->kdev, &connector_attrs[i]);
sysfs_remove_bin_file(&connector->kdev.kobj, &edid_attr);
device_unregister(&connector->kdev);
}
EXPORT_SYMBOL(drm_sysfs_output_remove);
EXPORT_SYMBOL(drm_sysfs_connector_remove);
/**
* drm_sysfs_hotplug_event - generate a DRM uevent

View file

@ -126,7 +126,7 @@ struct intel_dvo_dev_ops {
/*
* Probe for a connected output, and return detect_status.
*/
enum drm_output_status (*detect)(struct intel_dvo_device *dvo);
enum drm_connector_status (*detect)(struct intel_dvo_device *dvo);
/**
* Query the device for the modes it provides.

View file

@ -258,9 +258,9 @@ fail:
return false;
}
static enum drm_output_status ch7017_detect(struct intel_dvo_device *dvo)
static enum drm_connector_status ch7017_detect(struct intel_dvo_device *dvo)
{
return output_status_unknown;
return connector_status_unknown;
}
static enum drm_mode_status ch7017_mode_valid(struct intel_dvo_device *dvo,

View file

@ -230,7 +230,7 @@ out:
return false;
}
static enum drm_output_status ch7xxx_detect(struct intel_dvo_device *dvo)
static enum drm_connector_status ch7xxx_detect(struct intel_dvo_device *dvo)
{
uint8_t cdet, orig_pm, pm;
@ -247,8 +247,8 @@ static enum drm_output_status ch7xxx_detect(struct intel_dvo_device *dvo)
ch7xxx_writeb(dvo, CH7xxx_PM, orig_pm);
if (cdet & CH7xxx_CDET_DVI)
return output_status_connected;
return output_status_disconnected;
return connector_status_connected;
return connector_status_disconnected;
}
static enum drm_mode_status ch7xxx_mode_valid(struct intel_dvo_device *dvo,

View file

@ -297,9 +297,9 @@ out:
return false;
}
static enum drm_output_status ivch_detect(struct intel_dvo_device *dvo)
static enum drm_connector_status ivch_detect(struct intel_dvo_device *dvo)
{
return output_status_connected;
return connector_status_connected;
}
static enum drm_mode_status ivch_mode_valid(struct intel_dvo_device *dvo,

View file

@ -180,16 +180,16 @@ out:
return false;
}
static enum drm_output_status sil164_detect(struct intel_dvo_device *dvo)
static enum drm_connector_status sil164_detect(struct intel_dvo_device *dvo)
{
uint8_t reg9;
sil164_readb(dvo, SIL164_REG9, &reg9);
if (reg9 & SIL164_9_HTPLG)
return output_status_connected;
return connector_status_connected;
else
return output_status_disconnected;
return connector_status_disconnected;
}
static enum drm_mode_status sil164_mode_valid(struct intel_dvo_device *dvo,

View file

@ -207,16 +207,16 @@ out:
return false;
}
static enum drm_output_status tfp410_detect(struct intel_dvo_device *dvo)
static enum drm_connector_status tfp410_detect(struct intel_dvo_device *dvo)
{
enum drm_output_status ret = output_status_disconnected;
enum drm_connector_status ret = connector_status_disconnected;
uint8_t ctl2;
if (tfp410_readb(dvo, TFP410_CTL_2, &ctl2)) {
if (ctl2 & TFP410_CTL_2_HTPLG)
ret = output_status_connected;
ret = connector_status_connected;
else
ret = output_status_disconnected;
ret = connector_status_disconnected;
}
return ret;

View file

@ -33,9 +33,9 @@
#include "i915_drm.h"
#include "i915_drv.h"
static void intel_crt_dpms(struct drm_output *output, int mode)
static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 temp;
@ -61,17 +61,17 @@ static void intel_crt_dpms(struct drm_output *output, int mode)
I915_WRITE(ADPA, temp);
}
static void intel_crt_save(struct drm_output *output)
static void intel_crt_save(struct drm_connector *connector)
{
}
static void intel_crt_restore(struct drm_output *output)
static void intel_crt_restore(struct drm_connector *connector)
{
}
static int intel_crt_mode_valid(struct drm_output *output,
static int intel_crt_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
if (mode->flags & V_DBLSCAN)
@ -83,19 +83,20 @@ static int intel_crt_mode_valid(struct drm_output *output,
return MODE_OK;
}
static bool intel_crt_mode_fixup(struct drm_output *output,
static bool intel_crt_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
return true;
}
static void intel_crt_mode_set(struct drm_output *output,
static void intel_crt_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = output->dev;
struct drm_crtc *crtc = output->crtc;
struct drm_device *dev = encoder->dev;
struct drm_crtc *crtc = encoder->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct drm_i915_private *dev_priv = dev->dev_private;
int dpll_md_reg;
@ -138,9 +139,9 @@ static void intel_crt_mode_set(struct drm_output *output,
* \return TRUE if CRT is connected.
* \return FALSE if CRT is disconnected.
*/
static bool intel_crt_detect_hotplug(struct drm_output *output)
static bool intel_crt_detect_hotplug(struct drm_connector *connector)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u32 temp;
@ -164,57 +165,58 @@ static bool intel_crt_detect_hotplug(struct drm_output *output)
return false;
}
static bool intel_crt_detect_ddc(struct drm_output *output)
static bool intel_crt_detect_ddc(struct drm_connector *connector)
{
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
/* CRT should always be at 0, but check anyway */
if (intel_output->type != INTEL_OUTPUT_ANALOG)
return false;
return intel_ddc_probe(output);
return intel_ddc_probe(intel_output);
}
static enum drm_output_status intel_crt_detect(struct drm_output *output)
static enum drm_connector_status intel_crt_detect(struct drm_connector *connector)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
if (intel_crt_detect_hotplug(output))
return output_status_connected;
if (intel_crt_detect_hotplug(connector))
return connector_status_connected;
else
return output_status_disconnected;
return connector_status_disconnected;
}
if (intel_crt_detect_ddc(output))
return output_status_connected;
if (intel_crt_detect_ddc(connector))
return connector_status_connected;
/* TODO use load detect */
return output_status_unknown;
return connector_status_unknown;
}
static void intel_crt_destroy(struct drm_output *output)
static void intel_crt_destroy(struct drm_connector *connector)
{
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
intel_i2c_destroy(intel_output->ddc_bus);
drm_output_cleanup(output);
kfree(output);
drm_connector_cleanup(connector);
kfree(connector);
}
static int intel_crt_get_modes(struct drm_output *output)
static int intel_crt_get_modes(struct drm_connector *connector)
{
return intel_ddc_get_modes(output);
struct intel_output *intel_output = to_intel_output(connector);
return intel_ddc_get_modes(intel_output);
}
static bool intel_crt_set_property(struct drm_output *output,
static bool intel_crt_set_property(struct drm_connector *connector,
struct drm_property *property,
uint64_t value)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
if (property == dev->mode_config.dpms_property)
intel_crt_dpms(output, (uint32_t)(value & 0xf));
if (property == dev->mode_config.dpms_property && connector->encoder)
intel_crt_dpms(connector->encoder, (uint32_t)(value & 0xf));
return true;
}
@ -223,52 +225,71 @@ static bool intel_crt_set_property(struct drm_output *output,
* Routines for controlling stuff on the analog port
*/
static const struct drm_output_helper_funcs intel_crt_helper_funcs = {
static const struct drm_encoder_helper_funcs intel_crt_helper_funcs = {
.dpms = intel_crt_dpms,
.mode_fixup = intel_crt_mode_fixup,
.prepare = intel_output_prepare,
.commit = intel_output_commit,
.prepare = intel_encoder_prepare,
.commit = intel_encoder_commit,
.mode_set = intel_crt_mode_set,
};
static const struct drm_output_funcs intel_crt_output_funcs = {
.dpms = intel_crt_dpms,
static const struct drm_connector_funcs intel_crt_connector_funcs = {
.save = intel_crt_save,
.restore = intel_crt_restore,
.detect = intel_crt_detect,
.get_modes = intel_crt_get_modes,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = intel_crt_destroy,
.set_property = intel_crt_set_property,
.mode_valid = intel_crt_mode_valid,
};
static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = {
.mode_valid = intel_crt_mode_valid,
.get_modes = intel_crt_get_modes,
.best_encoder = intel_best_encoder,
};
void intel_crt_enc_destroy(struct drm_encoder *encoder)
{
drm_encoder_cleanup(encoder);
}
static const struct drm_encoder_funcs intel_crt_enc_funcs = {
.destroy = intel_crt_enc_destroy,
};
void intel_crt_init(struct drm_device *dev)
{
struct drm_output *output;
struct drm_connector *connector;
struct intel_output *intel_output;
intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL);
if (!intel_output)
return;
output = &intel_output->base;
drm_output_init(dev, &intel_output->base, &intel_crt_output_funcs, DRM_MODE_OUTPUT_DAC);
connector = &intel_output->base;
drm_connector_init(dev, &intel_output->base, &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
drm_encoder_init(dev, &intel_output->enc, &intel_crt_enc_funcs, DRM_MODE_ENCODER_DAC);
drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
/* Set up the DDC bus. */
intel_output->ddc_bus = intel_i2c_create(dev, GPIOA, "CRTDDC_A");
if (!intel_output->ddc_bus) {
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
"failed.\n");
intel_crt_destroy(output);
intel_crt_destroy(connector);
return;
}
intel_output->type = INTEL_OUTPUT_ANALOG;
output->interlace_allowed = 0;
output->doublescan_allowed = 0;
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;
drm_encoder_helper_add(&intel_output->enc, &intel_crt_helper_funcs);
drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
drm_sysfs_connector_add(connector);
drm_output_helper_add(output, &intel_crt_helper_funcs);
drm_sysfs_output_add(output);
drm_output_attach_property(output, dev->mode_config.connector_type_property, ConnectorVGA);
}

View file

@ -225,10 +225,10 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type)
{
struct drm_device *dev = crtc->dev;
struct drm_mode_config *mode_config = &dev->mode_config;
struct drm_output *l_entry;
struct drm_connector *l_entry;
list_for_each_entry(l_entry, &mode_config->output_list, head) {
if (l_entry->crtc == crtc) {
list_for_each_entry(l_entry, &mode_config->connector_list, head) {
if (l_entry->encoder->crtc == crtc) {
struct intel_output *intel_output = to_intel_output(l_entry);
if (intel_output->type == type)
return true;
@ -240,7 +240,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type)
#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; }
/**
* Returns whether the given set of divisors are valid for a given refclk with
* the given outputs.
* the given connectors.
*/
static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock)
@ -264,7 +264,7 @@ static bool intel_PLL_is_valid(struct drm_crtc *crtc, intel_clock_t *clock)
if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
INTELPllInvalid ("vco out of range\n");
/* XXX: We may need to be checking "Dot clock" depending on the multiplier,
* output, etc., rather than just a single range.
* connector, etc., rather than just a single range.
*/
if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
INTELPllInvalid ("dot out of range\n");
@ -575,24 +575,28 @@ static void intel_crtc_dpms(struct drm_crtc *crtc, int mode)
static void intel_crtc_prepare (struct drm_crtc *crtc)
{
crtc->funcs->dpms(crtc, DPMSModeOff);
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
crtc_funcs->dpms(crtc, DPMSModeOff);
}
static void intel_crtc_commit (struct drm_crtc *crtc)
{
crtc->funcs->dpms(crtc, DPMSModeOn);
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
crtc_funcs->dpms(crtc, DPMSModeOn);
}
void intel_output_prepare (struct drm_output *output)
void intel_encoder_prepare (struct drm_encoder *encoder)
{
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
/* lvds has its own version of prepare see intel_lvds_prepare */
output->funcs->dpms(output, DPMSModeOff);
encoder_funcs->dpms(encoder, DPMSModeOff);
}
void intel_output_commit (struct drm_output *output)
void intel_encoder_commit (struct drm_encoder *encoder)
{
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
/* lvds has its own version of commit see intel_lvds_commit */
output->funcs->dpms(output, DPMSModeOn);
encoder_funcs->dpms(encoder, DPMSModeOn);
}
static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,
@ -716,12 +720,12 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
bool ok, is_sdvo = false, is_dvo = false;
bool is_crt = false, is_lvds = false, is_tv = false;
struct drm_mode_config *mode_config = &dev->mode_config;
struct drm_output *output;
struct drm_connector *connector;
list_for_each_entry(output, &mode_config->output_list, head) {
struct intel_output *intel_output = to_intel_output(output);
list_for_each_entry(connector, &mode_config->connector_list, head) {
struct intel_output *intel_output = to_intel_output(connector);
if (output->crtc != crtc)
if (!connector->encoder || connector->encoder->crtc != crtc)
continue;
switch (intel_output->type) {
@ -1082,38 +1086,40 @@ static struct drm_display_mode load_detect_mode = {
704, 832, 0, 480, 489, 491, 520, 0, V_NHSYNC | V_NVSYNC),
};
struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output,
struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output,
struct drm_display_mode *mode,
int *dpms_mode)
{
struct drm_device *dev = output->dev;
struct intel_output *intel_output = to_intel_output(output);
struct intel_crtc *intel_crtc;
struct drm_crtc *possible_crtc;
struct drm_crtc *supported_crtc =NULL;
struct drm_encoder *encoder = &intel_output->enc;
struct drm_crtc *crtc = NULL;
struct drm_output_helper_funcs *output_funcs;
struct drm_device *dev = encoder->dev;
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
struct drm_crtc_helper_funcs *crtc_funcs;
int i = -1;
/*
* Algorithm gets a little messy:
* - if the output already has an assigned crtc, use it (but make
* - if the connector already has an assigned crtc, use it (but make
* sure it's on first)
* - try to find the first unused crtc that can drive this output,
* - try to find the first unused crtc that can drive this connector,
* and use that if we find one
* - if there are no unused crtcs available, try to use the first
* one we found that supports the output
* one we found that supports the connector
*/
/* See if we already have a CRTC for this output */
if (output->crtc) {
crtc = output->crtc;
/* Make sure the crtc and output are running */
/* See if we already have a CRTC for this connector */
if (encoder->crtc) {
crtc = encoder->crtc;
/* Make sure the crtc and connector are running */
intel_crtc = to_intel_crtc(crtc);
*dpms_mode = intel_crtc->dpms_mode;
if (intel_crtc->dpms_mode != DPMSModeOn) {
crtc->funcs->dpms(crtc, DPMSModeOn);
output->funcs->dpms(output, DPMSModeOn);
crtc_funcs = crtc->helper_private;
crtc_funcs->dpms(crtc, DPMSModeOn);
encoder_funcs->dpms(encoder, DPMSModeOn);
}
return crtc;
}
@ -1121,7 +1127,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output,
/* Find an unused one (if possible) */
list_for_each_entry(possible_crtc, &dev->mode_config.crtc_list, head) {
i++;
if (!(output->possible_crtcs & (1 << i)))
if (!(encoder->possible_crtcs & (1 << i)))
continue;
if (!possible_crtc->enabled) {
crtc = possible_crtc;
@ -1133,7 +1139,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output,
/*
* If we didn't find an unused CRTC, use the first available one
* that can drive this output.
* that can drive this connector.
*/
if (!crtc) {
crtc = supported_crtc;
@ -1141,7 +1147,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output,
return NULL;
}
output->crtc = crtc;
encoder->crtc = crtc;
intel_output->load_detect_temp = TRUE;
intel_crtc = to_intel_crtc(crtc);
@ -1152,38 +1158,41 @@ struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output,
mode = &load_detect_mode;
drm_crtc_helper_set_mode(crtc, mode, 0, 0);
} else {
if (intel_crtc->dpms_mode != DPMSModeOn)
crtc->funcs->dpms(crtc, DPMSModeOn);
if (intel_crtc->dpms_mode != DPMSModeOn) {
crtc_funcs = crtc->helper_private;
crtc_funcs->dpms(crtc, DPMSModeOn);
}
output_funcs = output->helper_private;
/* Add this output to the crtc */
output_funcs->mode_set(output, &crtc->mode, &crtc->mode);
output_funcs->commit(output);
/* Add this connector to the crtc */
encoder_funcs->mode_set(encoder, &crtc->mode, &crtc->mode);
encoder_funcs->commit(encoder);
}
/* let the output get through one full cycle before testing */
/* let the connector get through one full cycle before testing */
intel_wait_for_vblank(dev);
return crtc;
}
void intel_release_load_detect_pipe(struct drm_output *output, int dpms_mode)
void intel_release_load_detect_pipe(struct intel_output *intel_output, int dpms_mode)
{
struct drm_device *dev = output->dev;
struct intel_output *intel_output = to_intel_output(output);
struct drm_crtc *crtc = output->crtc;
struct drm_encoder *encoder = &intel_output->enc;
struct drm_device *dev = encoder->dev;
struct drm_crtc *crtc = encoder->crtc;
struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
if (intel_output->load_detect_temp) {
output->crtc = NULL;
encoder->crtc = NULL;
intel_output->load_detect_temp = FALSE;
crtc->enabled = drm_crtc_in_use(crtc);
drm_disable_unused_functions(dev);
crtc->enabled = drm_helper_crtc_in_use(crtc);
drm_helper_disable_unused_functions(dev);
}
/* Switch crtc and output back off if necessary */
if (crtc->enabled && dpms_mode != DPMSModeOn) {
if (output->crtc == crtc)
output->funcs->dpms(output, dpms_mode);
crtc->funcs->dpms(crtc, dpms_mode);
if (encoder->crtc == crtc)
encoder_funcs->dpms(encoder, dpms_mode);
crtc_funcs->dpms(crtc, dpms_mode);
}
}
@ -1257,7 +1266,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
}
/* XXX: It would be nice to validate the clocks, but we can't reuse
* i830PllIsValid() because it relies on the xf86_config output
* i830PllIsValid() because it relies on the xf86_config connector
* configuration being accurate, which it isn't necessarily.
*/
@ -1306,6 +1315,7 @@ static void intel_crtc_destroy(struct drm_crtc *crtc)
}
static const struct drm_crtc_helper_funcs intel_helper_funcs = {
.dpms = intel_crtc_dpms,
.mode_fixup = intel_crtc_mode_fixup,
.mode_set = intel_crtc_mode_set,
.mode_set_base = intel_pipe_set_base,
@ -1314,7 +1324,6 @@ static const struct drm_crtc_helper_funcs intel_helper_funcs = {
};
static const struct drm_crtc_funcs intel_crtc_funcs = {
.dpms = intel_crtc_dpms,
.cursor_set = intel_crtc_cursor_set,
.cursor_move = intel_crtc_cursor_move,
.gamma_set = intel_crtc_gamma_set,
@ -1358,14 +1367,14 @@ struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
return crtc;
}
int intel_output_clones(struct drm_device *dev, int type_mask)
int intel_connector_clones(struct drm_device *dev, int type_mask)
{
int index_mask = 0;
struct drm_output *output;
struct drm_connector *connector;
int entry = 0;
list_for_each_entry(output, &dev->mode_config.output_list, head) {
struct intel_output *intel_output = to_intel_output(output);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct intel_output *intel_output = to_intel_output(connector);
if (type_mask & (1 << intel_output->type))
index_mask |= (1 << entry);
entry++;
@ -1376,7 +1385,7 @@ int intel_output_clones(struct drm_device *dev, int type_mask)
static void intel_setup_outputs(struct drm_device *dev)
{
struct drm_output *output;
struct drm_connector *connector;
intel_crt_init(dev);
@ -1393,8 +1402,9 @@ static void intel_setup_outputs(struct drm_device *dev)
if (IS_I9XX(dev) && !IS_I915G(dev))
intel_tv_init(dev);
list_for_each_entry(output, &dev->mode_config.output_list, head) {
struct intel_output *intel_output = to_intel_output(output);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
struct intel_output *intel_output = to_intel_output(connector);
struct drm_encoder *encoder = &intel_output->enc;
int crtc_mask = 0, clone_mask = 0;
/* valid crtcs */
@ -1424,8 +1434,8 @@ static void intel_setup_outputs(struct drm_device *dev)
clone_mask = (1 << INTEL_OUTPUT_TVOUT);
break;
}
output->possible_crtcs = crtc_mask;
output->possible_clones = intel_output_clones(dev, clone_mask);
encoder->possible_crtcs = crtc_mask;
encoder->possible_clones = intel_connector_clones(dev, clone_mask);
}
}
@ -1479,3 +1489,14 @@ void intel_modeset_cleanup(struct drm_device *dev)
{
drm_mode_config_cleanup(dev);
}
/* current intel driver doesn't take advantage of encoders
always give back the encoder for the connector
*/
struct drm_encoder *intel_best_encoder(struct drm_connector *connector)
{
struct intel_output *intel_output = to_intel_output(connector);
return &intel_output->enc;
}

View file

@ -47,7 +47,9 @@ struct intel_i2c_chan {
};
struct intel_output {
struct drm_output base;
struct drm_connector base;
struct drm_encoder enc;
int type;
struct intel_i2c_chan *i2c_bus; /* for control functions */
struct intel_i2c_chan *ddc_bus; /* for DDC only stuff */
@ -66,12 +68,13 @@ struct intel_crtc {
#define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
#define to_intel_output(x) container_of(x, struct intel_output, base)
#define enc_to_intel_output(x) container_of(x, struct intel_output, enc)
struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg,
const char *name);
void intel_i2c_destroy(struct intel_i2c_chan *chan);
int intel_ddc_get_modes(struct drm_output *output);
extern bool intel_ddc_probe(struct drm_output *output);
int intel_ddc_get_modes(struct intel_output *intel_output);
extern bool intel_ddc_probe(struct intel_output *intel_output);
extern void intel_crt_init(struct drm_device *dev);
extern void intel_sdvo_init(struct drm_device *dev, int output_device);
@ -80,23 +83,25 @@ extern void intel_tv_init(struct drm_device *dev);
extern void intel_lvds_init(struct drm_device *dev);
extern void intel_crtc_load_lut(struct drm_crtc *crtc);
extern void intel_output_prepare (struct drm_output *output);
extern void intel_output_commit (struct drm_output *output);
extern void intel_encoder_prepare (struct drm_encoder *encoder);
extern void intel_encoder_commit (struct drm_encoder *encoder);
extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector);
extern struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev,
struct drm_crtc *crtc);
extern void intel_wait_for_vblank(struct drm_device *dev);
extern struct drm_crtc *intel_get_crtc_from_pipe(struct drm_device *dev, int pipe);
extern struct drm_crtc *intel_get_load_detect_pipe(struct drm_output *output,
extern struct drm_crtc *intel_get_load_detect_pipe(struct intel_output *intel_output,
struct drm_display_mode *mode,
int *dpms_mode);
extern void intel_release_load_detect_pipe(struct drm_output *output,
extern void intel_release_load_detect_pipe(struct intel_output *intel_output,
int dpms_mode);
extern struct drm_output* intel_sdvo_find(struct drm_device *dev, int sdvoB);
extern int intel_sdvo_supports_hotplug(struct drm_output *output);
extern void intel_sdvo_set_hotplug(struct drm_output *output, int enable);
extern int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_output *output);
extern struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB);
extern int intel_sdvo_supports_hotplug(struct drm_connector *connector);
extern void intel_sdvo_set_hotplug(struct drm_connector *connector, int enable);
extern int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_connector *connector);
extern int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
extern int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc);

View file

@ -85,10 +85,10 @@ struct intel_dvo_device intel_dvo_devices[] = {
}
};
static void intel_dvo_dpms(struct drm_output *output, int mode)
static void intel_dvo_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_i915_private *dev_priv = output->dev->dev_private;
struct intel_output *intel_output = to_intel_output(output);
struct drm_i915_private *dev_priv = encoder->dev->dev_private;
struct intel_output *intel_output = enc_to_intel_output(encoder);
struct intel_dvo_device *dvo = intel_output->dev_priv;
u32 dvo_reg = dvo->dvo_reg;
u32 temp = I915_READ(dvo_reg);
@ -104,10 +104,10 @@ static void intel_dvo_dpms(struct drm_output *output, int mode)
}
}
static void intel_dvo_save(struct drm_output *output)
static void intel_dvo_save(struct drm_connector *connector)
{
struct drm_i915_private *dev_priv = output->dev->dev_private;
struct intel_output *intel_output = to_intel_output(output);
struct drm_i915_private *dev_priv = connector->dev->dev_private;
struct intel_output *intel_output = to_intel_output(connector);
struct intel_dvo_device *dvo = intel_output->dev_priv;
/* Each output should probably just save the registers it touches,
@ -120,10 +120,10 @@ static void intel_dvo_save(struct drm_output *output)
dvo->dev_ops->save(dvo);
}
static void intel_dvo_restore(struct drm_output *output)
static void intel_dvo_restore(struct drm_connector *connector)
{
struct drm_i915_private *dev_priv = output->dev->dev_private;
struct intel_output *intel_output = to_intel_output(output);
struct drm_i915_private *dev_priv = connector->dev->dev_private;
struct intel_output *intel_output = to_intel_output(connector);
struct intel_dvo_device *dvo = intel_output->dev_priv;
dvo->dev_ops->restore(dvo);
@ -133,10 +133,10 @@ static void intel_dvo_restore(struct drm_output *output)
I915_WRITE(DVOC, dev_priv->saveDVOC);
}
static int intel_dvo_mode_valid(struct drm_output *output,
static int intel_dvo_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
struct intel_dvo_device *dvo = intel_output->dev_priv;
if (mode->flags & V_DBLSCAN)
@ -154,11 +154,11 @@ static int intel_dvo_mode_valid(struct drm_output *output,
return dvo->dev_ops->mode_valid(dvo, mode);
}
static bool intel_dvo_mode_fixup(struct drm_output *output,
static bool intel_dvo_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = enc_to_intel_output(encoder);
struct intel_dvo_device *dvo = intel_output->dev_priv;
/* If we have timings from the BIOS for the panel, put them in
@ -187,14 +187,14 @@ static bool intel_dvo_mode_fixup(struct drm_output *output,
return true;
}
static void intel_dvo_mode_set(struct drm_output *output,
static void intel_dvo_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(output->crtc);
struct intel_output *intel_output = to_intel_output(output);
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
struct intel_output *intel_output = enc_to_intel_output(encoder);
struct intel_dvo_device *dvo = intel_output->dev_priv;
int pipe = intel_crtc->pipe;
u32 dvo_val;
@ -247,17 +247,17 @@ static void intel_dvo_mode_set(struct drm_output *output,
*
* Unimplemented.
*/
static enum drm_output_status intel_dvo_detect(struct drm_output *output)
static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector)
{
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
struct intel_dvo_device *dvo = intel_output->dev_priv;
return dvo->dev_ops->detect(dvo);
}
static int intel_dvo_get_modes(struct drm_output *output)
static int intel_dvo_get_modes(struct drm_connector *connector)
{
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
struct intel_dvo_device *dvo = intel_output->dev_priv;
/* We should probably have an i2c driver get_modes function for those
@ -265,8 +265,8 @@ static int intel_dvo_get_modes(struct drm_output *output)
* (TV-out, for example), but for now with just TMDS and LVDS,
* that's not the case.
*/
intel_ddc_get_modes(output);
if (!list_empty(&output->probed_modes))
intel_ddc_get_modes(intel_output);
if (!list_empty(&connector->probed_modes))
return 1;
#if 0
@ -280,18 +280,18 @@ static int intel_dvo_get_modes(struct drm_output *output)
if (dvo->panel_fixed_mode != NULL) {
struct drm_display_mode *mode;
mode = drm_mode_duplicate(output->dev, dvo->panel_fixed_mode);
mode = drm_mode_duplicate(connector->dev, dvo->panel_fixed_mode);
if (mode) {
drm_mode_probed_add(output, mode);
drm_mode_probed_add(connector, mode);
return 1;
}
}
return 0;
}
static void intel_dvo_destroy (struct drm_output *output)
static void intel_dvo_destroy (struct drm_connector *connector)
{
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
struct intel_dvo_device *dvo = intel_output->dev_priv;
if (dvo) {
@ -306,16 +306,16 @@ static void intel_dvo_destroy (struct drm_output *output)
intel_i2c_destroy(intel_output->i2c_bus);
if (intel_output->ddc_bus)
intel_i2c_destroy(intel_output->ddc_bus);
drm_output_cleanup(output);
kfree(output);
drm_connector_cleanup(connector);
kfree(intel_output);
}
#ifdef RANDR_GET_CRTC_INTERFACE
static struct drm_crtc *intel_dvo_get_crtc(struct drm_output *output)
static struct drm_crtc *intel_dvo_get_crtc(struct drm_connector *connector)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
struct intel_dvo_device *dvo = intel_output->dev_priv;
int pipe = !!(I915_READ(dvo->dvo_reg) & SDVO_PIPE_B_SELECT);
@ -323,23 +323,38 @@ static struct drm_crtc *intel_dvo_get_crtc(struct drm_output *output)
}
#endif
static const struct drm_output_helper_funcs intel_dvo_helper_funcs = {
static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = {
.dpms = intel_dvo_dpms,
.mode_fixup = intel_dvo_mode_fixup,
.prepare = intel_output_prepare,
.prepare = intel_encoder_prepare,
.mode_set = intel_dvo_mode_set,
.commit = intel_output_commit,
.commit = intel_encoder_commit,
};
static const struct drm_output_funcs intel_dvo_output_funcs = {
.dpms = intel_dvo_dpms,
static const struct drm_connector_funcs intel_dvo_connector_funcs = {
.save = intel_dvo_save,
.restore = intel_dvo_restore,
.detect = intel_dvo_detect,
.get_modes = intel_dvo_get_modes,
.destroy = intel_dvo_destroy,
.mode_valid = intel_dvo_mode_valid,
.fill_modes = drm_helper_probe_single_connector_modes,
};
static const struct drm_connector_helper_funcs intel_dvo_connector_helper_funcs = {
.mode_valid = intel_dvo_mode_valid,
.get_modes = intel_dvo_get_modes,
.best_encoder = intel_best_encoder,
};
void intel_dvo_enc_destroy(struct drm_encoder *encoder)
{
drm_encoder_cleanup(encoder);
}
static const struct drm_encoder_funcs intel_dvo_enc_funcs = {
.destroy = intel_dvo_enc_destroy,
};
/**
* Attempts to get a fixed panel timing for LVDS (currently only the i830).
*
@ -347,11 +362,11 @@ static const struct drm_output_funcs intel_dvo_output_funcs = {
* chip being on DVOB/C and having multiple pipes.
*/
static struct drm_display_mode *
intel_dvo_get_current_mode (struct drm_output *output)
intel_dvo_get_current_mode (struct drm_connector *connector)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
struct intel_dvo_device *dvo = intel_output->dev_priv;
uint32_t dvo_reg = dvo->dvo_reg;
uint32_t dvo_val = I915_READ(dvo_reg);
@ -388,8 +403,7 @@ void intel_dvo_init(struct drm_device *dev)
int ret = 0;
int i;
int gpio_inited = 0;
int connector = ConnectorUnknown;
int encoder_type = DRM_MODE_ENCODER_NONE;
intel_output = kzalloc (sizeof(struct intel_output), GFP_KERNEL);
if (!intel_output)
return;
@ -401,7 +415,7 @@ void intel_dvo_init(struct drm_device *dev)
/* Now, try to find a controller */
for (i = 0; i < ARRAY_SIZE(intel_dvo_devices); i++) {
struct drm_output *output = &intel_output->base;
struct drm_connector *connector = &intel_output->base;
int gpio;
dvo = &intel_dvo_devices[i];
@ -442,25 +456,31 @@ void intel_dvo_init(struct drm_device *dev)
intel_output->type = INTEL_OUTPUT_DVO;
switch (dvo->type) {
case INTEL_DVO_CHIP_TMDS:
connector = ConnectorDVID;
drm_output_init(dev, output, &intel_dvo_output_funcs,
DRM_MODE_OUTPUT_TMDS);
// connector = DRM_MODE_CONNECTOR_DVID;
drm_connector_init(dev, connector, &intel_dvo_connector_funcs,
DRM_MODE_CONNECTOR_DVII);
encoder_type = DRM_MODE_ENCODER_TMDS;
break;
case INTEL_DVO_CHIP_LVDS:
connector = ConnectorLVDS;
drm_output_init(dev, output, &intel_dvo_output_funcs,
DRM_MODE_OUTPUT_LVDS);
// connector = DRM_MODE_CONNECTOR_LVDS;
drm_connector_init(dev, connector, &intel_dvo_connector_funcs,
DRM_MODE_CONNECTOR_LVDS);
encoder_type = DRM_MODE_ENCODER_LVDS;
break;
}
drm_output_helper_add(output, &intel_dvo_helper_funcs);
output->display_info.subpixel_order = SubPixelHorizontalRGB;
output->interlace_allowed = false;
output->doublescan_allowed = false;
drm_connector_helper_add(connector, &intel_dvo_connector_helper_funcs);
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = false;
connector->doublescan_allowed = false;
intel_output->dev_priv = dvo;
intel_output->i2c_bus = i2cbus;
drm_encoder_init(dev, &intel_output->enc, &intel_dvo_enc_funcs, encoder_type);
drm_encoder_helper_add(&intel_output->enc, &intel_dvo_helper_funcs);
drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
if (dvo->type == INTEL_DVO_CHIP_LVDS) {
/* For our LVDS chipsets, we should hopefully be able
* to dig the fixed panel mode out of the BIOS data.
@ -469,14 +489,11 @@ void intel_dvo_init(struct drm_device *dev)
* headers, likely), so for now, just get the current
* mode being output through DVO.
*/
dvo->panel_fixed_mode = intel_dvo_get_current_mode(output);
dvo->panel_fixed_mode = intel_dvo_get_current_mode(connector);
dvo->panel_wants_dither = true;
}
drm_sysfs_output_add(output);
drm_output_attach_property(output,
dev->mode_config.connector_type_property,
connector);
drm_sysfs_connector_add(connector);
return;
}

View file

@ -53,7 +53,7 @@ struct intelfb_par {
*/
struct drm_display_mode *our_mode;
struct drm_mode_set set;
struct drm_output *hack;
struct drm_connector *hack;
};
/*
static int
@ -114,7 +114,7 @@ static int intelfb_check_var(struct fb_var_screeninfo *var,
struct intelfb_par *par = info->par;
/*struct drm_device *dev = par->dev;*/
struct drm_framebuffer *fb = par->set.fb;
/*struct drm_output *output;*/
/*struct drm_connector *connector;*/
int depth/*, found = 0*/;
if (!var->pixclock)
@ -195,17 +195,17 @@ static int intelfb_check_var(struct fb_var_screeninfo *var,
}
#if 0
/* Here we walk the output mode list and look for modes. If we haven't
/* Here we walk the connector mode list and look for modes. If we haven't
* got it, then bail. Not very nice, so this is disabled.
* In the set_par code, we create our mode based on the incoming
* parameters. Nicer, but may not be desired by some.
*/
list_for_each_entry(output, &dev->mode_config.output_list, head) {
if (output->crtc == par->crtc)
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (connector->crtc == par->crtc)
break;
}
list_for_each_entry(drm_mode, &output->modes, head) {
list_for_each_entry(drm_mode, &connector->modes, head) {
if (drm_mode->hdisplay == var->xres &&
drm_mode->vdisplay == var->yres &&
(((PICOS2KHZ(var->pixclock))/1000) >= ((drm_mode->clock/1000)-1)) &&
@ -230,7 +230,7 @@ static int intelfb_set_par(struct fb_info *info)
struct drm_framebuffer *fb = par->set.fb;
struct drm_device *dev = par->dev;
struct drm_display_mode *drm_mode, *search_mode;
struct drm_output *output = NULL;
struct drm_connector *connector = NULL;
struct fb_var_screeninfo *var = &info->var;
int found = 0;
@ -276,20 +276,20 @@ static int intelfb_set_par(struct fb_info *info)
drm_mode_set_crtcinfo(drm_mode, CRTC_INTERLACE_HALVE_V);
found = 0;
list_for_each_entry(output, &dev->mode_config.output_list, head) {
if (output->crtc == par->set.crtc){
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
if (connector->encoder->crtc == par->set.crtc){
found = 1;
break;
}
}
/* no output bound, bail */
/* no connector bound, bail */
if (!found)
return -EINVAL;
found = 0;
drm_mode_debug_printmodeline(drm_mode);
list_for_each_entry(search_mode, &output->modes, head) {
list_for_each_entry(search_mode, &connector->modes, head) {
drm_mode_debug_printmodeline(search_mode);
if (drm_mode_equal(drm_mode, search_mode)) {
drm_mode_destroy(dev, drm_mode);
@ -299,7 +299,7 @@ static int intelfb_set_par(struct fb_info *info)
}
}
/* If we didn't find a matching mode that exists on our output,
/* If we didn't find a matching mode that exists on our connector,
* create a new attachment for the incoming user specified mode
*/
if (!found) {
@ -566,7 +566,7 @@ int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc)
}
EXPORT_SYMBOL(intelfb_resize);
int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_output *output)
int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_connector *connector)
{
struct fb_info *info;
struct intelfb_par *par;
@ -581,7 +581,7 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_outp
return -EINVAL;
}
if (!output)
if (!connector)
return -EINVAL;
fb = drm_framebuffer_create(dev);
@ -627,9 +627,9 @@ int intelfb_probe(struct drm_device *dev, struct drm_crtc *crtc, struct drm_outp
par->dev = dev;
par->set.crtc = crtc;
par->set.fb = fb;
par->hack = output;
par->set.outputs = &par->hack;
par->set.num_outputs = 1;
par->hack = connector;
par->set.connectors = &par->hack;
par->set.num_connectors = 1;
info->fbops = &intelfb_ops;

View file

@ -89,9 +89,9 @@ static void intel_lvds_set_power(struct drm_device *dev, bool on)
}
}
static void intel_lvds_dpms(struct drm_output *output, int mode)
static void intel_lvds_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = encoder->dev;
if (mode == DPMSModeOn)
intel_lvds_set_power(dev, true);
@ -101,9 +101,9 @@ static void intel_lvds_dpms(struct drm_output *output, int mode)
/* XXX: We never power down the LVDS pairs. */
}
static void intel_lvds_save(struct drm_output *output)
static void intel_lvds_save(struct drm_connector *connector)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
dev_priv->savePP_ON = I915_READ(PP_ON_DELAYS);
@ -122,9 +122,9 @@ static void intel_lvds_save(struct drm_output *output)
intel_lvds_get_max_backlight(dev);
}
static void intel_lvds_restore(struct drm_output *output)
static void intel_lvds_restore(struct drm_connector *connector)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
I915_WRITE(BLC_PWM_CTL, dev_priv->saveBLC_PWM_CTL);
@ -138,10 +138,10 @@ static void intel_lvds_restore(struct drm_output *output)
intel_lvds_set_power(dev, false);
}
static int intel_lvds_mode_valid(struct drm_output *output,
static int intel_lvds_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_display_mode *fixed_mode = dev_priv->panel_fixed_mode;
@ -155,14 +155,14 @@ static int intel_lvds_mode_valid(struct drm_output *output,
return MODE_OK;
}
static bool intel_lvds_mode_fixup(struct drm_output *output,
static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(output->crtc);
struct drm_output *tmp_output;
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
struct drm_encoder *tmp_encoder;
/* Should never happen!! */
if (!IS_I965G(dev) && intel_crtc->pipe == 0) {
@ -171,10 +171,10 @@ static bool intel_lvds_mode_fixup(struct drm_output *output,
}
/* Should never happen!! */
list_for_each_entry(tmp_output, &dev->mode_config.output_list, head) {
if (tmp_output != output && tmp_output->crtc == output->crtc) {
list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, head) {
if (tmp_encoder != encoder && tmp_encoder->crtc == encoder->crtc) {
printk(KERN_ERR "Can't enable LVDS and another "
"output on the same pipe\n");
"encoder on the same pipe\n");
return false;
}
}
@ -211,9 +211,9 @@ static bool intel_lvds_mode_fixup(struct drm_output *output,
return true;
}
static void intel_lvds_prepare(struct drm_output *output)
static void intel_lvds_prepare(struct drm_encoder *encoder)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_CTL);
@ -223,9 +223,9 @@ static void intel_lvds_prepare(struct drm_output *output)
intel_lvds_set_power(dev, false);
}
static void intel_lvds_commit( struct drm_output *output)
static void intel_lvds_commit( struct drm_encoder *encoder)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
if (dev_priv->backlight_duty_cycle == 0)
@ -235,13 +235,13 @@ static void intel_lvds_commit( struct drm_output *output)
intel_lvds_set_power(dev, true);
}
static void intel_lvds_mode_set(struct drm_output *output,
static void intel_lvds_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(output->crtc);
struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
u32 pfit_control;
/*
@ -276,24 +276,25 @@ static void intel_lvds_mode_set(struct drm_output *output,
/**
* Detect the LVDS connection.
*
* This always returns OUTPUT_STATUS_CONNECTED. This output should only have
* This always returns CONNECTOR_STATUS_CONNECTED. This connector should only have
* been set up if the LVDS was actually connected anyway.
*/
static enum drm_output_status intel_lvds_detect(struct drm_output *output)
static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector)
{
return output_status_connected;
return connector_status_connected;
}
/**
* Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
*/
static int intel_lvds_get_modes(struct drm_output *output)
static int intel_lvds_get_modes(struct drm_connector *connector)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
struct intel_output *intel_output = to_intel_output(connector);
struct drm_i915_private *dev_priv = dev->dev_private;
int ret = 0;
ret = intel_ddc_get_modes(output);
ret = intel_ddc_get_modes(intel_output);
if (ret)
return ret;
@ -302,15 +303,15 @@ static int intel_lvds_get_modes(struct drm_output *output)
* Set wide sync ranges so we get all modes
* handed to valid_mode for checking
*/
output->display_info.min_vfreq = 0;
output->display_info.max_vfreq = 200;
output->display_info.min_hfreq = 0;
output->display_info.max_hfreq = 200;
connector->display_info.min_vfreq = 0;
connector->display_info.max_vfreq = 200;
connector->display_info.min_hfreq = 0;
connector->display_info.max_hfreq = 200;
if (dev_priv->panel_fixed_mode != NULL) {
struct drm_display_mode *mode =
drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
drm_mode_probed_add(output, mode);
drm_mode_probed_add(connector, mode);
return 1;
}
@ -319,49 +320,67 @@ static int intel_lvds_get_modes(struct drm_output *output)
/**
* intel_lvds_destroy - unregister and free LVDS structures
* @output: output to free
* @connector: connector to free
*
* Unregister the DDC bus for this output then free the driver private
* Unregister the DDC bus for this connector then free the driver private
* structure.
*/
static void intel_lvds_destroy(struct drm_output *output)
static void intel_lvds_destroy(struct drm_connector *connector)
{
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
intel_i2c_destroy(intel_output->ddc_bus);
drm_output_cleanup(output);
kfree(output);
drm_connector_cleanup(connector);
kfree(connector);
}
static const struct drm_output_helper_funcs intel_lvds_helper_funcs = {
static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
.dpms = intel_lvds_dpms,
.mode_fixup = intel_lvds_mode_fixup,
.prepare = intel_lvds_prepare,
.mode_set = intel_lvds_mode_set,
.commit = intel_lvds_commit,
};
static const struct drm_output_funcs intel_lvds_output_funcs = {
.dpms = intel_lvds_dpms,
static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
.get_modes = intel_lvds_get_modes,
.mode_valid = intel_lvds_mode_valid,
.best_encoder = intel_best_encoder,
};
static const struct drm_connector_funcs intel_lvds_connector_funcs = {
.save = intel_lvds_save,
.restore = intel_lvds_restore,
.detect = intel_lvds_detect,
.get_modes = intel_lvds_get_modes,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = intel_lvds_destroy,
.mode_valid = intel_lvds_mode_valid,
};
static void intel_lvds_enc_destroy(struct drm_encoder *encoder)
{
drm_encoder_cleanup(encoder);
}
static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
.destroy = intel_lvds_enc_destroy,
};
/**
* intel_lvds_init - setup LVDS outputs on this device
* intel_lvds_init - setup LVDS connectors on this device
* @dev: drm device
*
* Create the output, register the LVDS DDC bus, and try to figure out what
* Create the connector, register the LVDS DDC bus, and try to figure out what
* modes we can display on the LVDS panel (if present).
*/
void intel_lvds_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_output *intel_output;
struct drm_output *output;
struct drm_connector *connector;
struct drm_encoder *encoder;
struct drm_display_mode *scan; /* *modes, *bios_mode; */
struct drm_crtc *crtc;
u32 lvds;
@ -372,16 +391,22 @@ void intel_lvds_init(struct drm_device *dev)
return;
}
output = &intel_output->base;
drm_output_init(dev, &intel_output->base, &intel_lvds_output_funcs,
DRM_MODE_OUTPUT_LVDS);
connector = &intel_output->base;
encoder = &intel_output->enc;
drm_connector_init(dev, &intel_output->base, &intel_lvds_connector_funcs,
DRM_MODE_CONNECTOR_LVDS);
drm_encoder_init(dev, &intel_output->enc, &intel_lvds_enc_funcs,
DRM_MODE_ENCODER_LVDS);
drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
intel_output->type = INTEL_OUTPUT_LVDS;
drm_output_helper_add(output, &intel_lvds_helper_funcs);
output->display_info.subpixel_order = SubPixelHorizontalRGB;
output->interlace_allowed = FALSE;
output->doublescan_allowed = FALSE;
drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
connector->interlace_allowed = FALSE;
connector->doublescan_allowed = FALSE;
/*
@ -399,7 +424,7 @@ void intel_lvds_init(struct drm_device *dev)
if (!intel_output->ddc_bus) {
dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
"failed.\n");
intel_lvds_destroy(output);
intel_lvds_destroy(connector);
return;
}
@ -407,9 +432,9 @@ void intel_lvds_init(struct drm_device *dev)
* Attempt to get the fixed panel mode from DDC. Assume that the
* preferred mode is the right one.
*/
intel_ddc_get_modes(output);
intel_ddc_get_modes(intel_output);
list_for_each_entry(scan, &output->probed_modes, head) {
list_for_each_entry(scan, &connector->probed_modes, head) {
if (scan->type & DRM_MODE_TYPE_PREFERRED) {
dev_priv->panel_fixed_mode =
drm_mode_duplicate(dev, scan);
@ -481,11 +506,10 @@ void intel_lvds_init(struct drm_device *dev)
#endif
out:
drm_sysfs_output_add(output);
drm_output_attach_property(output, dev->mode_config.connector_type_property, ConnectorLVDS);
drm_sysfs_connector_add(connector);
return;
failed:
DRM_DEBUG("No LVDS modes found, disabling.\n");
intel_lvds_destroy(output);
intel_lvds_destroy(connector);
}

View file

@ -13,9 +13,8 @@
* intel_ddc_probe
*
*/
bool intel_ddc_probe(struct drm_output *output)
bool intel_ddc_probe(struct intel_output *intel_output)
{
struct intel_output *intel_output = to_intel_output(output);
u8 out_buf[] = { 0x0, 0x0};
u8 buf[2];
int ret;
@ -43,20 +42,19 @@ bool intel_ddc_probe(struct drm_output *output)
/**
* intel_ddc_get_modes - get modelist from monitor
* @output: DRM output device to use
* @connector: DRM connector device to use
*
* Fetch the EDID information from @output using the DDC bus.
* Fetch the EDID information from @connector using the DDC bus.
*/
int intel_ddc_get_modes(struct drm_output *output)
int intel_ddc_get_modes(struct intel_output *intel_output)
{
struct intel_output *intel_output = to_intel_output(output);
struct edid *edid;
int ret = 0;
edid = drm_get_edid(output, &intel_output->ddc_bus->adapter);
edid = drm_get_edid(&intel_output->base, &intel_output->ddc_bus->adapter);
if (edid) {
drm_mode_output_update_edid_property(output, edid);
ret = drm_add_edid_modes(output, edid);
drm_mode_connector_update_edid_property(&intel_output->base, edid);
ret = drm_add_edid_modes(&intel_output->base, edid);
kfree(edid);
}
return ret;

View file

@ -60,11 +60,10 @@ struct intel_sdvo_priv {
* SDVOB and SDVOC to work around apparent hardware issues (according to
* comments in the BIOS).
*/
void intel_sdvo_write_sdvox(struct drm_output *output, u32 val)
void intel_sdvo_write_sdvox(struct intel_output *intel_output, u32 val)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = intel_output->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_output *intel_output = to_intel_output(output);
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
u32 bval = val, cval = val;
int i;
@ -88,10 +87,9 @@ void intel_sdvo_write_sdvox(struct drm_output *output, u32 val)
}
}
static bool intel_sdvo_read_byte(struct drm_output *output, u8 addr,
static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr,
u8 *ch)
{
struct intel_output *intel_output = to_intel_output(output);
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
u8 out_buf[2];
u8 buf[2];
@ -126,10 +124,9 @@ static bool intel_sdvo_read_byte(struct drm_output *output, u8 addr,
return false;
}
static bool intel_sdvo_write_byte(struct drm_output *output, int addr,
static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr,
u8 ch)
{
struct intel_output *intel_output = to_intel_output(output);
u8 out_buf[2];
struct i2c_msg msgs[] = {
{
@ -198,10 +195,9 @@ const static struct _sdvo_cmd_name {
#define SDVO_NAME(dev_priv) ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC")
#define SDVO_PRIV(output) ((struct intel_sdvo_priv *) (output)->dev_priv)
static void intel_sdvo_write_cmd(struct drm_output *output, u8 cmd,
static void intel_sdvo_write_cmd(struct intel_output *intel_output, u8 cmd,
void *args, int args_len)
{
struct intel_output *intel_output = to_intel_output(output);
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
int i;
@ -223,10 +219,10 @@ static void intel_sdvo_write_cmd(struct drm_output *output, u8 cmd,
}
for (i = 0; i < args_len; i++) {
intel_sdvo_write_byte(output, SDVO_I2C_ARG_0 - i, ((u8*)args)[i]);
intel_sdvo_write_byte(intel_output, SDVO_I2C_ARG_0 - i, ((u8*)args)[i]);
}
intel_sdvo_write_byte(output, SDVO_I2C_OPCODE, cmd);
intel_sdvo_write_byte(intel_output, SDVO_I2C_OPCODE, cmd);
}
static const char *cmd_status_names[] = {
@ -239,10 +235,9 @@ static const char *cmd_status_names[] = {
"Scaling not supported"
};
static u8 intel_sdvo_read_response(struct drm_output *output, void *response,
static u8 intel_sdvo_read_response(struct intel_output *intel_output, void *response,
int response_len)
{
struct intel_output *intel_output = to_intel_output(output);
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
int i;
u8 status;
@ -251,12 +246,12 @@ static u8 intel_sdvo_read_response(struct drm_output *output, void *response,
while (retry--) {
/* Read the command response */
for (i = 0; i < response_len; i++) {
intel_sdvo_read_byte(output, SDVO_I2C_RETURN_0 + i,
intel_sdvo_read_byte(intel_output, SDVO_I2C_RETURN_0 + i,
&((u8 *)response)[i]);
}
/* read the return status */
intel_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, &status);
intel_sdvo_read_byte(intel_output, SDVO_I2C_CMD_STATUS, &status);
if (1) {
DRM_DEBUG("%s: R: ", SDVO_NAME(sdvo_priv));
@ -295,12 +290,12 @@ int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode)
* SDVO chips which defeats the purpose of doing a bus switch in the first
* place.
*/
void intel_sdvo_set_control_bus_switch(struct drm_output *output, u8 target)
void intel_sdvo_set_control_bus_switch(struct intel_output *intel_output, u8 target)
{
intel_sdvo_write_cmd(output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1);
intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1);
}
static bool intel_sdvo_set_target_input(struct drm_output *output, bool target_0, bool target_1)
static bool intel_sdvo_set_target_input(struct intel_output *intel_output, bool target_0, bool target_1)
{
struct intel_sdvo_set_target_input_args targets = {0};
u8 status;
@ -311,10 +306,10 @@ static bool intel_sdvo_set_target_input(struct drm_output *output, bool target_0
if (target_1)
targets.target_1 = 1;
intel_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_INPUT, &targets,
intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_TARGET_INPUT, &targets,
sizeof(targets));
status = intel_sdvo_read_response(output, NULL, 0);
status = intel_sdvo_read_response(intel_output, NULL, 0);
return (status == SDVO_CMD_STATUS_SUCCESS);
}
@ -325,13 +320,13 @@ static bool intel_sdvo_set_target_input(struct drm_output *output, bool target_0
* This function is making an assumption about the layout of the response,
* which should be checked against the docs.
*/
static bool intel_sdvo_get_trained_inputs(struct drm_output *output, bool *input_1, bool *input_2)
static bool intel_sdvo_get_trained_inputs(struct intel_output *intel_output, bool *input_1, bool *input_2)
{
struct intel_sdvo_get_trained_inputs_response response;
u8 status;
intel_sdvo_write_cmd(output, SDVO_CMD_GET_TRAINED_INPUTS, NULL, 0);
status = intel_sdvo_read_response(output, &response, sizeof(response));
intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_TRAINED_INPUTS, NULL, 0);
status = intel_sdvo_read_response(intel_output, &response, sizeof(response));
if (status != SDVO_CMD_STATUS_SUCCESS)
return false;
@ -340,29 +335,29 @@ static bool intel_sdvo_get_trained_inputs(struct drm_output *output, bool *input
return true;
}
static bool intel_sdvo_get_active_outputs(struct drm_output *output,
static bool intel_sdvo_get_active_outputs(struct intel_output *intel_output,
u16 *outputs)
{
u8 status;
intel_sdvo_write_cmd(output, SDVO_CMD_GET_ACTIVE_OUTPUTS, NULL, 0);
status = intel_sdvo_read_response(output, outputs, sizeof(*outputs));
intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ACTIVE_OUTPUTS, NULL, 0);
status = intel_sdvo_read_response(intel_output, outputs, sizeof(*outputs));
return (status == SDVO_CMD_STATUS_SUCCESS);
}
static bool intel_sdvo_set_active_outputs(struct drm_output *output,
static bool intel_sdvo_set_active_outputs(struct intel_output *intel_output,
u16 outputs)
{
u8 status;
intel_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_OUTPUTS, &outputs,
intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_ACTIVE_OUTPUTS, &outputs,
sizeof(outputs));
status = intel_sdvo_read_response(output, NULL, 0);
status = intel_sdvo_read_response(intel_output, NULL, 0);
return (status == SDVO_CMD_STATUS_SUCCESS);
}
static bool intel_sdvo_set_encoder_power_state(struct drm_output *output,
static bool intel_sdvo_set_encoder_power_state(struct intel_output *intel_output,
int mode)
{
u8 status, state = SDVO_ENCODER_STATE_ON;
@ -382,24 +377,24 @@ static bool intel_sdvo_set_encoder_power_state(struct drm_output *output,
break;
}
intel_sdvo_write_cmd(output, SDVO_CMD_SET_ENCODER_POWER_STATE, &state,
intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_ENCODER_POWER_STATE, &state,
sizeof(state));
status = intel_sdvo_read_response(output, NULL, 0);
status = intel_sdvo_read_response(intel_output, NULL, 0);
return (status == SDVO_CMD_STATUS_SUCCESS);
}
static bool intel_sdvo_get_input_pixel_clock_range(struct drm_output *output,
static bool intel_sdvo_get_input_pixel_clock_range(struct intel_output *intel_output,
int *clock_min,
int *clock_max)
{
struct intel_sdvo_pixel_clock_range clocks;
u8 status;
intel_sdvo_write_cmd(output, SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE,
intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE,
NULL, 0);
status = intel_sdvo_read_response(output, &clocks, sizeof(clocks));
status = intel_sdvo_read_response(intel_output, &clocks, sizeof(clocks));
if (status != SDVO_CMD_STATUS_SUCCESS)
return false;
@ -411,31 +406,31 @@ static bool intel_sdvo_get_input_pixel_clock_range(struct drm_output *output,
return true;
}
static bool intel_sdvo_set_target_output(struct drm_output *output,
static bool intel_sdvo_set_target_output(struct intel_output *intel_output,
u16 outputs)
{
u8 status;
intel_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_OUTPUT, &outputs,
intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_TARGET_OUTPUT, &outputs,
sizeof(outputs));
status = intel_sdvo_read_response(output, NULL, 0);
status = intel_sdvo_read_response(intel_output, NULL, 0);
return (status == SDVO_CMD_STATUS_SUCCESS);
}
static bool intel_sdvo_get_timing(struct drm_output *output, u8 cmd,
static bool intel_sdvo_get_timing(struct intel_output *intel_output, u8 cmd,
struct intel_sdvo_dtd *dtd)
{
u8 status;
intel_sdvo_write_cmd(output, cmd, NULL, 0);
status = intel_sdvo_read_response(output, &dtd->part1,
intel_sdvo_write_cmd(intel_output, cmd, NULL, 0);
status = intel_sdvo_read_response(intel_output, &dtd->part1,
sizeof(dtd->part1));
if (status != SDVO_CMD_STATUS_SUCCESS)
return false;
intel_sdvo_write_cmd(output, cmd + 1, NULL, 0);
status = intel_sdvo_read_response(output, &dtd->part2,
intel_sdvo_write_cmd(intel_output, cmd + 1, NULL, 0);
status = intel_sdvo_read_response(intel_output, &dtd->part2,
sizeof(dtd->part2));
if (status != SDVO_CMD_STATUS_SUCCESS)
return false;
@ -443,71 +438,70 @@ static bool intel_sdvo_get_timing(struct drm_output *output, u8 cmd,
return true;
}
static bool intel_sdvo_get_input_timing(struct drm_output *output,
static bool intel_sdvo_get_input_timing(struct intel_output *intel_output,
struct intel_sdvo_dtd *dtd)
{
return intel_sdvo_get_timing(output,
return intel_sdvo_get_timing(intel_output,
SDVO_CMD_GET_INPUT_TIMINGS_PART1, dtd);
}
static bool intel_sdvo_get_output_timing(struct drm_output *output,
static bool intel_sdvo_get_output_timing(struct intel_output *intel_output,
struct intel_sdvo_dtd *dtd)
{
return intel_sdvo_get_timing(output,
return intel_sdvo_get_timing(intel_output,
SDVO_CMD_GET_OUTPUT_TIMINGS_PART1, dtd);
}
static bool intel_sdvo_set_timing(struct drm_output *output, u8 cmd,
static bool intel_sdvo_set_timing(struct intel_output *intel_output, u8 cmd,
struct intel_sdvo_dtd *dtd)
{
u8 status;
intel_sdvo_write_cmd(output, cmd, &dtd->part1, sizeof(dtd->part1));
status = intel_sdvo_read_response(output, NULL, 0);
intel_sdvo_write_cmd(intel_output, cmd, &dtd->part1, sizeof(dtd->part1));
status = intel_sdvo_read_response(intel_output, NULL, 0);
if (status != SDVO_CMD_STATUS_SUCCESS)
return false;
intel_sdvo_write_cmd(output, cmd + 1, &dtd->part2, sizeof(dtd->part2));
status = intel_sdvo_read_response(output, NULL, 0);
intel_sdvo_write_cmd(intel_output, cmd + 1, &dtd->part2, sizeof(dtd->part2));
status = intel_sdvo_read_response(intel_output, NULL, 0);
if (status != SDVO_CMD_STATUS_SUCCESS)
return false;
return true;
}
static bool intel_sdvo_set_input_timing(struct drm_output *output,
static bool intel_sdvo_set_input_timing(struct intel_output *intel_output,
struct intel_sdvo_dtd *dtd)
{
return intel_sdvo_set_timing(output,
return intel_sdvo_set_timing(intel_output,
SDVO_CMD_SET_INPUT_TIMINGS_PART1, dtd);
}
static bool intel_sdvo_set_output_timing(struct drm_output *output,
static bool intel_sdvo_set_output_timing(struct intel_output *intel_output,
struct intel_sdvo_dtd *dtd)
{
return intel_sdvo_set_timing(output,
return intel_sdvo_set_timing(intel_output,
SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd);
}
#if 0
static bool intel_sdvo_get_preferred_input_timing(struct drm_output *output,
static bool intel_sdvo_get_preferred_input_timing(struct intel_output *intel_output,
struct intel_sdvo_dtd *dtd)
{
struct intel_output *intel_output = to_intel_output(output);
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
u8 status;
intel_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1,
intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1,
NULL, 0);
status = intel_sdvo_read_response(output, &dtd->part1,
status = intel_sdvo_read_response(intel_output, &dtd->part1,
sizeof(dtd->part1));
if (status != SDVO_CMD_STATUS_SUCCESS)
return false;
intel_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2,
intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2,
NULL, 0);
status = intel_sdvo_read_response(output, &dtd->part2,
status = intel_sdvo_read_response(intel_output, &dtd->part2,
sizeof(dtd->part2));
if (status != SDVO_CMD_STATUS_SUCCESS)
return false;
@ -516,12 +510,12 @@ static bool intel_sdvo_get_preferred_input_timing(struct drm_output *output,
}
#endif
static int intel_sdvo_get_clock_rate_mult(struct drm_output *output)
static int intel_sdvo_get_clock_rate_mult(struct intel_output *intel_output)
{
u8 response, status;
intel_sdvo_write_cmd(output, SDVO_CMD_GET_CLOCK_RATE_MULT, NULL, 0);
status = intel_sdvo_read_response(output, &response, 1);
intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_CLOCK_RATE_MULT, NULL, 0);
status = intel_sdvo_read_response(intel_output, &response, 1);
if (status != SDVO_CMD_STATUS_SUCCESS) {
DRM_DEBUG("Couldn't get SDVO clock rate multiplier\n");
@ -533,19 +527,19 @@ static int intel_sdvo_get_clock_rate_mult(struct drm_output *output)
return response;
}
static bool intel_sdvo_set_clock_rate_mult(struct drm_output *output, u8 val)
static bool intel_sdvo_set_clock_rate_mult(struct intel_output *intel_output, u8 val)
{
u8 status;
intel_sdvo_write_cmd(output, SDVO_CMD_SET_CLOCK_RATE_MULT, &val, 1);
status = intel_sdvo_read_response(output, NULL, 0);
intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_CLOCK_RATE_MULT, &val, 1);
status = intel_sdvo_read_response(intel_output, NULL, 0);
if (status != SDVO_CMD_STATUS_SUCCESS)
return false;
return true;
}
static bool intel_sdvo_mode_fixup(struct drm_output *output,
static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
@ -556,15 +550,15 @@ static bool intel_sdvo_mode_fixup(struct drm_output *output,
return true;
}
static void intel_sdvo_mode_set(struct drm_output *output,
static void intel_sdvo_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = output->crtc;
struct drm_crtc *crtc = encoder->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = enc_to_intel_output(encoder);
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
u16 width, height;
u16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
@ -618,11 +612,11 @@ static void intel_sdvo_mode_set(struct drm_output *output,
output_dtd.part2.reserved = 0;
/* Set the output timing to the screen */
intel_sdvo_set_target_output(output, sdvo_priv->active_outputs);
intel_sdvo_set_output_timing(output, &output_dtd);
intel_sdvo_set_target_output(intel_output, sdvo_priv->active_outputs);
intel_sdvo_set_output_timing(intel_output, &output_dtd);
/* Set the input timing to the screen. Assume always input 0. */
intel_sdvo_set_target_input(output, true, false);
intel_sdvo_set_target_input(intel_output, true, false);
/* We would like to use i830_sdvo_create_preferred_input_timing() to
* provide the device with a timing it can support, if it supports that
@ -630,29 +624,29 @@ static void intel_sdvo_mode_set(struct drm_output *output,
* output the preferred timing, and we don't support that currently.
*/
#if 0
success = intel_sdvo_create_preferred_input_timing(output, clock,
success = intel_sdvo_create_preferred_input_timing(intel_output, clock,
width, height);
if (success) {
struct intel_sdvo_dtd *input_dtd;
intel_sdvo_get_preferred_input_timing(output, &input_dtd);
intel_sdvo_set_input_timing(output, &input_dtd);
intel_sdvo_get_preferred_input_timing(intel_output, &input_dtd);
intel_sdvo_set_input_timing(intel_output, &input_dtd);
}
#else
intel_sdvo_set_input_timing(output, &output_dtd);
intel_sdvo_set_input_timing(intel_output, &output_dtd);
#endif
switch (intel_sdvo_get_pixel_multiplier(mode)) {
case 1:
intel_sdvo_set_clock_rate_mult(output,
intel_sdvo_set_clock_rate_mult(intel_output,
SDVO_CLOCK_RATE_MULT_1X);
break;
case 2:
intel_sdvo_set_clock_rate_mult(output,
intel_sdvo_set_clock_rate_mult(intel_output,
SDVO_CLOCK_RATE_MULT_2X);
break;
case 4:
intel_sdvo_set_clock_rate_mult(output,
intel_sdvo_set_clock_rate_mult(intel_output,
SDVO_CLOCK_RATE_MULT_4X);
break;
}
@ -686,26 +680,26 @@ static void intel_sdvo_mode_set(struct drm_output *output,
sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
}
intel_sdvo_write_sdvox(output, sdvox);
intel_sdvo_write_sdvox(intel_output, sdvox);
}
static void intel_sdvo_dpms(struct drm_output *output, int mode)
static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = enc_to_intel_output(encoder);
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
u32 temp;
if (mode != DPMSModeOn) {
intel_sdvo_set_active_outputs(output, 0);
intel_sdvo_set_active_outputs(intel_output, 0);
if (0)
intel_sdvo_set_encoder_power_state(output, mode);
intel_sdvo_set_encoder_power_state(intel_output, mode);
if (mode == DPMSModeOff) {
temp = I915_READ(sdvo_priv->output_device);
if ((temp & SDVO_ENABLE) != 0) {
intel_sdvo_write_sdvox(output, temp & ~SDVO_ENABLE);
intel_sdvo_write_sdvox(intel_output, temp & ~SDVO_ENABLE);
}
}
} else {
@ -715,11 +709,11 @@ static void intel_sdvo_dpms(struct drm_output *output, int mode)
temp = I915_READ(sdvo_priv->output_device);
if ((temp & SDVO_ENABLE) == 0)
intel_sdvo_write_sdvox(output, temp | SDVO_ENABLE);
intel_sdvo_write_sdvox(intel_output, temp | SDVO_ENABLE);
for (i = 0; i < 2; i++)
intel_wait_for_vblank(dev);
status = intel_sdvo_get_trained_inputs(output, &input1,
status = intel_sdvo_get_trained_inputs(intel_output, &input1,
&input2);
@ -733,32 +727,32 @@ static void intel_sdvo_dpms(struct drm_output *output, int mode)
}
if (0)
intel_sdvo_set_encoder_power_state(output, mode);
intel_sdvo_set_active_outputs(output, sdvo_priv->active_outputs);
intel_sdvo_set_encoder_power_state(intel_output, mode);
intel_sdvo_set_active_outputs(intel_output, sdvo_priv->active_outputs);
}
return;
}
static void intel_sdvo_save(struct drm_output *output)
static void intel_sdvo_save(struct drm_connector *connector)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
int o;
sdvo_priv->save_sdvo_mult = intel_sdvo_get_clock_rate_mult(output);
intel_sdvo_get_active_outputs(output, &sdvo_priv->save_active_outputs);
sdvo_priv->save_sdvo_mult = intel_sdvo_get_clock_rate_mult(intel_output);
intel_sdvo_get_active_outputs(intel_output, &sdvo_priv->save_active_outputs);
if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) {
intel_sdvo_set_target_input(output, true, false);
intel_sdvo_get_input_timing(output,
intel_sdvo_set_target_input(intel_output, true, false);
intel_sdvo_get_input_timing(intel_output,
&sdvo_priv->save_input_dtd_1);
}
if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) {
intel_sdvo_set_target_input(output, false, true);
intel_sdvo_get_input_timing(output,
intel_sdvo_set_target_input(intel_output, false, true);
intel_sdvo_get_input_timing(intel_output,
&sdvo_priv->save_input_dtd_2);
}
@ -767,8 +761,8 @@ static void intel_sdvo_save(struct drm_output *output)
u16 this_output = (1 << o);
if (sdvo_priv->caps.output_flags & this_output)
{
intel_sdvo_set_target_output(output, this_output);
intel_sdvo_get_output_timing(output,
intel_sdvo_set_target_output(intel_output, this_output);
intel_sdvo_get_output_timing(intel_output,
&sdvo_priv->save_output_dtd[o]);
}
}
@ -776,39 +770,39 @@ static void intel_sdvo_save(struct drm_output *output)
sdvo_priv->save_SDVOX = I915_READ(sdvo_priv->output_device);
}
static void intel_sdvo_restore(struct drm_output *output)
static void intel_sdvo_restore(struct drm_connector *connector)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
int o;
int i;
bool input1, input2;
u8 status;
intel_sdvo_set_active_outputs(output, 0);
intel_sdvo_set_active_outputs(intel_output, 0);
for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++)
{
u16 this_output = (1 << o);
if (sdvo_priv->caps.output_flags & this_output) {
intel_sdvo_set_target_output(output, this_output);
intel_sdvo_set_output_timing(output, &sdvo_priv->save_output_dtd[o]);
intel_sdvo_set_target_output(intel_output, this_output);
intel_sdvo_set_output_timing(intel_output, &sdvo_priv->save_output_dtd[o]);
}
}
if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) {
intel_sdvo_set_target_input(output, true, false);
intel_sdvo_set_input_timing(output, &sdvo_priv->save_input_dtd_1);
intel_sdvo_set_target_input(intel_output, true, false);
intel_sdvo_set_input_timing(intel_output, &sdvo_priv->save_input_dtd_1);
}
if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) {
intel_sdvo_set_target_input(output, false, true);
intel_sdvo_set_input_timing(output, &sdvo_priv->save_input_dtd_2);
intel_sdvo_set_target_input(intel_output, false, true);
intel_sdvo_set_input_timing(intel_output, &sdvo_priv->save_input_dtd_2);
}
intel_sdvo_set_clock_rate_mult(output, sdvo_priv->save_sdvo_mult);
intel_sdvo_set_clock_rate_mult(intel_output, sdvo_priv->save_sdvo_mult);
I915_WRITE(sdvo_priv->output_device, sdvo_priv->save_SDVOX);
@ -816,19 +810,19 @@ static void intel_sdvo_restore(struct drm_output *output)
{
for (i = 0; i < 2; i++)
intel_wait_for_vblank(dev);
status = intel_sdvo_get_trained_inputs(output, &input1, &input2);
status = intel_sdvo_get_trained_inputs(intel_output, &input1, &input2);
if (status == SDVO_CMD_STATUS_SUCCESS && !input1)
DRM_DEBUG("First %s output reported failure to sync\n",
SDVO_NAME(sdvo_priv));
}
intel_sdvo_set_active_outputs(output, sdvo_priv->save_active_outputs);
intel_sdvo_set_active_outputs(intel_output, sdvo_priv->save_active_outputs);
}
static int intel_sdvo_mode_valid(struct drm_output *output,
static int intel_sdvo_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
if (mode->flags & V_DBLSCAN)
@ -843,27 +837,27 @@ static int intel_sdvo_mode_valid(struct drm_output *output,
return MODE_OK;
}
static bool intel_sdvo_get_capabilities(struct drm_output *output, struct intel_sdvo_caps *caps)
static bool intel_sdvo_get_capabilities(struct intel_output *intel_output, struct intel_sdvo_caps *caps)
{
u8 status;
intel_sdvo_write_cmd(output, SDVO_CMD_GET_DEVICE_CAPS, NULL, 0);
status = intel_sdvo_read_response(output, caps, sizeof(*caps));
intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_DEVICE_CAPS, NULL, 0);
status = intel_sdvo_read_response(intel_output, caps, sizeof(*caps));
if (status != SDVO_CMD_STATUS_SUCCESS)
return false;
return true;
}
struct drm_output* intel_sdvo_find(struct drm_device *dev, int sdvoB)
struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB)
{
struct drm_output *output = 0;
struct intel_output *iout = 0;
struct drm_connector *connector = NULL;
struct intel_output *iout = NULL;
struct intel_sdvo_priv *sdvo;
/* find the sdvo output */
list_for_each_entry(output, &dev->mode_config.output_list, head) {
iout = to_intel_output(output);
/* find the sdvo connector */
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
iout = to_intel_output(connector);
if (iout->type != INTEL_OUTPUT_SDVO)
continue;
@ -871,27 +865,30 @@ struct drm_output* intel_sdvo_find(struct drm_device *dev, int sdvoB)
sdvo = iout->dev_priv;
if (sdvo->output_device == SDVOB && sdvoB)
return output;
return connector;
if (sdvo->output_device == SDVOC && !sdvoB)
return output;
return connector;
}
return 0;
}
return NULL;
}
int intel_sdvo_supports_hotplug(struct drm_output *output)
int intel_sdvo_supports_hotplug(struct drm_connector *connector)
{
u8 response[2];
u8 status;
struct intel_output *intel_output;
DRM_DEBUG("\n");
if (!output)
if (!connector)
return 0;
intel_sdvo_write_cmd(output, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0);
status = intel_sdvo_read_response(output, &response, 2);
intel_output = to_intel_output(connector);
intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0);
status = intel_sdvo_read_response(intel_output, &response, 2);
if (response[0] !=0)
return 1;
@ -899,51 +896,55 @@ int intel_sdvo_supports_hotplug(struct drm_output *output)
return 0;
}
void intel_sdvo_set_hotplug(struct drm_output *output, int on)
void intel_sdvo_set_hotplug(struct drm_connector *connector, int on)
{
u8 response[2];
u8 status;
struct intel_output *intel_output = to_intel_output(connector);
intel_sdvo_write_cmd(output, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0);
intel_sdvo_read_response(output, &response, 2);
intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0);
intel_sdvo_read_response(intel_output, &response, 2);
if (on) {
intel_sdvo_write_cmd(output, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0);
status = intel_sdvo_read_response(output, &response, 2);
intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0);
status = intel_sdvo_read_response(intel_output, &response, 2);
intel_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
} else {
response[0] = 0;
response[1] = 0;
intel_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
intel_sdvo_write_cmd(intel_output, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2);
}
intel_sdvo_write_cmd(output, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0);
intel_sdvo_read_response(output, &response, 2);
intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0);
intel_sdvo_read_response(intel_output, &response, 2);
}
static enum drm_output_status intel_sdvo_detect(struct drm_output *output)
static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector)
{
u8 response[2];
u8 status;
struct intel_output *intel_output = to_intel_output(connector);
intel_sdvo_write_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
status = intel_sdvo_read_response(output, &response, 2);
intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
status = intel_sdvo_read_response(intel_output, &response, 2);
DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]);
if ((response[0] != 0) || (response[1] != 0))
return output_status_connected;
return connector_status_connected;
else
return output_status_disconnected;
return connector_status_disconnected;
}
static int intel_sdvo_get_modes(struct drm_output *output)
static int intel_sdvo_get_modes(struct drm_connector *connector)
{
/* set the bus switch and get the modes */
intel_sdvo_set_control_bus_switch(output, SDVO_CONTROL_BUS_DDC2);
intel_ddc_get_modes(output);
struct intel_output *intel_output = to_intel_output(connector);
if (list_empty(&output->probed_modes))
/* set the bus switch and get the modes */
intel_sdvo_set_control_bus_switch(intel_output, SDVO_CONTROL_BUS_DDC2);
intel_ddc_get_modes(intel_output);
if (list_empty(&connector->probed_modes))
return 0;
return 1;
#if 0
@ -959,60 +960,75 @@ static int intel_sdvo_get_modes(struct drm_output *output)
#endif
}
static void intel_sdvo_destroy(struct drm_output *output)
static void intel_sdvo_destroy(struct drm_connector *connector)
{
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
if (intel_output->i2c_bus)
intel_i2c_destroy(intel_output->i2c_bus);
drm_output_cleanup(output);
drm_connector_cleanup(connector);
kfree(intel_output);
}
static const struct drm_output_helper_funcs intel_sdvo_helper_funcs = {
static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
.dpms = intel_sdvo_dpms,
.mode_fixup = intel_sdvo_mode_fixup,
.prepare = intel_output_prepare,
.prepare = intel_encoder_prepare,
.mode_set = intel_sdvo_mode_set,
.commit = intel_output_commit,
.commit = intel_encoder_commit,
};
static const struct drm_output_funcs intel_sdvo_output_funcs = {
.dpms = intel_sdvo_dpms,
static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
.save = intel_sdvo_save,
.restore = intel_sdvo_restore,
.detect = intel_sdvo_detect,
.get_modes = intel_sdvo_get_modes,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = intel_sdvo_destroy,
.mode_valid = intel_sdvo_mode_valid,
};
static const struct drm_connector_helper_funcs intel_sdvo_connector_helper_funcs = {
.get_modes = intel_sdvo_get_modes,
.mode_valid = intel_sdvo_mode_valid,
.best_encoder = intel_best_encoder,
};
void intel_sdvo_enc_destroy(struct drm_encoder *encoder)
{
drm_encoder_cleanup(encoder);
}
static const struct drm_encoder_funcs intel_sdvo_enc_funcs = {
.destroy = intel_sdvo_enc_destroy,
};
void intel_sdvo_init(struct drm_device *dev, int output_device)
{
struct drm_output *output;
struct drm_connector *connector;
struct intel_output *intel_output;
struct intel_sdvo_priv *sdvo_priv;
struct intel_i2c_chan *i2cbus = NULL;
int connector_type;
u8 ch[0x40];
int i;
int output_type, output_id;
int encoder_type, output_id;
intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL);
if (!intel_output) {
return;
}
output = &intel_output->base;
drm_output_init(dev, output, &intel_sdvo_output_funcs,
DRM_MODE_OUTPUT_NONE);
connector = &intel_output->base;
drm_connector_init(dev, connector, &intel_sdvo_connector_funcs,
DRM_MODE_CONNECTOR_Unknown);
drm_connector_helper_add(connector, &intel_sdvo_connector_helper_funcs);
sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1);
intel_output->type = INTEL_OUTPUT_SDVO;
drm_output_helper_add(output, &intel_sdvo_helper_funcs);
output->interlace_allowed = 0;
output->doublescan_allowed = 0;
connector->interlace_allowed = 0;
connector->doublescan_allowed = 0;
/* setup the DDC bus. */
if (output_device == SDVOB)
@ -1021,7 +1037,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device)
i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC");
if (i2cbus == NULL) {
intel_sdvo_destroy(output);
intel_sdvo_destroy(connector);
return;
}
@ -1042,15 +1058,15 @@ void intel_sdvo_init(struct drm_device *dev, int output_device)
/* Read the regs to test if we can talk to the device */
for (i = 0; i < 0x40; i++) {
if (!intel_sdvo_read_byte(output, i, &ch[i])) {
if (!intel_sdvo_read_byte(intel_output, i, &ch[i])) {
DRM_DEBUG("No SDVO device found on SDVO%c\n",
output_device == SDVOB ? 'B' : 'C');
intel_sdvo_destroy(output);
intel_sdvo_destroy(connector);
return;
}
}
intel_sdvo_get_capabilities(output, &sdvo_priv->caps);
intel_sdvo_get_capabilities(intel_output, &sdvo_priv->caps);
memset(&sdvo_priv->active_outputs, 0, sizeof(sdvo_priv->active_outputs));
@ -1058,30 +1074,30 @@ void intel_sdvo_init(struct drm_device *dev, int output_device)
if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0)
{
sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0;
output->display_info.subpixel_order = SubPixelHorizontalRGB;
output_type = DRM_MODE_OUTPUT_DAC;
connector_type = ConnectorVGA;
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
encoder_type = DRM_MODE_ENCODER_DAC;
connector_type = DRM_MODE_CONNECTOR_VGA;
}
else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1)
{
sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1;
output->display_info.subpixel_order = SubPixelHorizontalRGB;
output_type = DRM_MODE_OUTPUT_DAC;
connector_type = ConnectorVGA;
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
encoder_type = DRM_MODE_ENCODER_DAC;
connector_type = DRM_MODE_CONNECTOR_VGA;
}
else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
{
sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0;
output->display_info.subpixel_order = SubPixelHorizontalRGB;
output_type = DRM_MODE_OUTPUT_TMDS;
connector_type = ConnectorDVID;
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
encoder_type = DRM_MODE_ENCODER_TMDS;
connector_type = DRM_MODE_CONNECTOR_DVID;
}
else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1)
{
sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1;
output->display_info.subpixel_order = SubPixelHorizontalRGB;
output_type = DRM_MODE_OUTPUT_TMDS;
connector_type = ConnectorDVID;
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
encoder_type = DRM_MODE_ENCODER_TMDS;
connector_type = DRM_MODE_CONNECTOR_DVID;
}
else
{
@ -1091,19 +1107,21 @@ void intel_sdvo_init(struct drm_device *dev, int output_device)
DRM_DEBUG("%s: No active RGB or TMDS outputs (0x%02x%02x)\n",
SDVO_NAME(sdvo_priv),
bytes[0], bytes[1]);
intel_sdvo_destroy(output);
intel_sdvo_destroy(connector);
return;
}
output->output_type = output_type;
output->output_type_id = output_id;
drm_encoder_init(dev, &intel_output->enc, &intel_sdvo_enc_funcs, encoder_type);
drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs);
connector->connector_type = connector_type;
drm_sysfs_output_add(output);
drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
drm_sysfs_connector_add(connector);
/* Set the input timing to the screen. Assume always input 0. */
intel_sdvo_set_target_input(output, true, false);
intel_sdvo_set_target_input(intel_output, true, false);
intel_sdvo_get_input_pixel_clock_range(output,
intel_sdvo_get_input_pixel_clock_range(intel_output,
&sdvo_priv->pixel_clock_min,
&sdvo_priv->pixel_clock_max);
@ -1127,5 +1145,4 @@ void intel_sdvo_init(struct drm_device *dev, int output_device)
intel_output->ddc_bus = i2cbus;
drm_output_attach_property(output, dev->mode_config.connector_type_property, connector_type);
}

View file

@ -898,9 +898,9 @@ const static struct tv_mode tv_modes[] = {
#define NUM_TV_MODES sizeof(tv_modes) / sizeof (tv_modes[0])
static void
intel_tv_dpms(struct drm_output *output, int mode)
intel_tv_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
switch(mode) {
@ -916,11 +916,11 @@ intel_tv_dpms(struct drm_output *output, int mode)
}
static void
intel_tv_save(struct drm_output *output)
intel_tv_save(struct drm_connector *connector)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
struct intel_tv_priv *tv_priv = intel_output->dev_priv;
int i;
@ -966,13 +966,13 @@ intel_tv_save(struct drm_output *output)
}
static void
intel_tv_restore(struct drm_output *output)
intel_tv_restore(struct drm_connector *connector)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = connector->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
struct intel_tv_priv *tv_priv = intel_output->dev_priv;
struct drm_crtc *crtc = output->crtc;
struct drm_crtc *crtc = connector->encoder->crtc;
struct intel_crtc *intel_crtc;
int i;
@ -1067,18 +1067,18 @@ intel_tv_mode_lookup (char *tv_format)
}
static const struct tv_mode *
intel_tv_mode_find (struct drm_output *output)
intel_tv_mode_find (struct intel_output *intel_output)
{
struct intel_output *intel_output = to_intel_output(output);
struct intel_tv_priv *tv_priv = intel_output->dev_priv;
return intel_tv_mode_lookup(tv_priv->tv_format);
}
static enum drm_mode_status
intel_tv_mode_valid(struct drm_output *output, struct drm_display_mode *mode)
intel_tv_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode)
{
const struct tv_mode *tv_mode = intel_tv_mode_find(output);
struct intel_output *intel_output = to_intel_output(connector);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output);
/* Ensure TV refresh is close to desired refresh */
if (tv_mode && abs(tv_mode->refresh - drm_mode_vrefresh(mode)) < 1)
@ -1088,21 +1088,22 @@ intel_tv_mode_valid(struct drm_output *output, struct drm_display_mode *mode)
static bool
intel_tv_mode_fixup(struct drm_output *output, struct drm_display_mode *mode,
intel_tv_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = encoder->dev;
struct drm_mode_config *drm_config = &dev->mode_config;
const struct tv_mode *tv_mode = intel_tv_mode_find (output);
struct drm_output *other_output;
struct intel_output *intel_output = enc_to_intel_output(encoder);
const struct tv_mode *tv_mode = intel_tv_mode_find (intel_output);
struct drm_encoder *other_encoder;
if (!tv_mode)
return FALSE;
/* FIXME: lock output list */
list_for_each_entry(other_output, &drm_config->output_list, head) {
if (other_output != output &&
other_output->crtc == output->crtc)
/* FIXME: lock encoder list */
list_for_each_entry(other_encoder, &drm_config->encoder_list, head) {
if (other_encoder != encoder &&
other_encoder->crtc == encoder->crtc)
return FALSE;
}
@ -1111,16 +1112,16 @@ intel_tv_mode_fixup(struct drm_output *output, struct drm_display_mode *mode,
}
static void
intel_tv_mode_set(struct drm_output *output, struct drm_display_mode *mode,
intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = output->dev;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc *crtc = output->crtc;
struct drm_crtc *crtc = encoder->crtc;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = enc_to_intel_output(encoder);
struct intel_tv_priv *tv_priv = intel_output->dev_priv;
const struct tv_mode *tv_mode = intel_tv_mode_find(output);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output);
u32 tv_ctl;
u32 hctl1, hctl2, hctl3;
u32 vctl1, vctl2, vctl3, vctl4, vctl5, vctl6, vctl7;
@ -1137,14 +1138,14 @@ intel_tv_mode_set(struct drm_output *output, struct drm_display_mode *mode,
switch (tv_priv->type) {
default:
case ConnectorUnknown:
case ConnectorComposite:
case DRM_MODE_CONNECTOR_Unknown:
case DRM_MODE_CONNECTOR_Composite:
tv_ctl |= TV_ENC_OUTPUT_COMPOSITE;
video_levels = tv_mode->composite_levels;
color_conversion = tv_mode->composite_color;
burst_ena = tv_mode->burst_ena;
break;
case ConnectorComponent:
case DRM_MODE_CONNECTOR_Component:
tv_ctl |= TV_ENC_OUTPUT_COMPONENT;
video_levels = &component_levels;
if (tv_mode->burst_ena)
@ -1153,7 +1154,7 @@ intel_tv_mode_set(struct drm_output *output, struct drm_display_mode *mode,
color_conversion = &hdtv_csc_yprpb;
burst_ena = FALSE;
break;
case ConnectorSVIDEO:
case DRM_MODE_CONNECTOR_SVIDEO:
tv_ctl |= TV_ENC_OUTPUT_SVIDEO;
video_levels = tv_mode->svideo_levels;
color_conversion = tv_mode->svideo_color;
@ -1355,15 +1356,15 @@ static const struct drm_display_mode reported_modes[] = {
* \return FALSE if TV is disconnected.
*/
static int
intel_tv_detect_type (struct drm_crtc *crtc, struct drm_output *output)
intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output)
{
struct drm_device *dev = output->dev;
struct drm_encoder *encoder = &intel_output->enc;
struct drm_device *dev = encoder->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_output *intel_output = to_intel_output(output);
u32 pipeastat, pipeastat_save;
u32 tv_ctl, save_tv_ctl;
u32 tv_dac, save_tv_dac;
int type = ConnectorUnknown;
int type = DRM_MODE_CONNECTOR_Unknown;
tv_dac = I915_READ(TV_DAC);
@ -1410,13 +1411,13 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct drm_output *output)
*/
if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
DRM_DEBUG("Detected Composite TV connection\n");
type = ConnectorComposite;
type = DRM_MODE_CONNECTOR_Composite;
} else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
DRM_DEBUG("Detected S-Video TV connection\n");
type = ConnectorSVIDEO;
type = DRM_MODE_CONNECTOR_SVIDEO;
} else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
DRM_DEBUG("Detected Component TV connection\n");
type = ConnectorComponent;
type = DRM_MODE_CONNECTOR_Component;
} else {
DRM_DEBUG("No TV connection detected\n");
type = -1;
@ -1432,46 +1433,48 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct drm_output *output)
/**
* Detect the TV connection.
*
* Currently this always returns OUTPUT_STATUS_UNKNOWN, as we need to be sure
* Currently this always returns CONNECTOR_STATUS_UNKNOWN, as we need to be sure
* we have a pipe programmed in order to probe the TV.
*/
static enum drm_output_status
intel_tv_detect(struct drm_output *output)
static enum drm_connector_status
intel_tv_detect(struct drm_connector *connector)
{
struct drm_crtc *crtc;
struct drm_display_mode mode;
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
struct intel_tv_priv *tv_priv = intel_output->dev_priv;
struct drm_encoder *encoder = &intel_output->enc;
int dpms_mode;
int type = tv_priv->type;
mode = reported_modes[0];
drm_mode_set_crtcinfo(&mode, CRTC_INTERLACE_HALVE_V);
if (output->crtc) {
type = intel_tv_detect_type(output->crtc, output);
if (encoder->crtc) {
type = intel_tv_detect_type(encoder->crtc, intel_output);
} else {
crtc = intel_get_load_detect_pipe(output, &mode, &dpms_mode);
crtc = intel_get_load_detect_pipe(intel_output, &mode, &dpms_mode);
if (crtc) {
type = intel_tv_detect_type(crtc, output);
intel_release_load_detect_pipe(output, dpms_mode);
type = intel_tv_detect_type(crtc, intel_output);
intel_release_load_detect_pipe(intel_output, dpms_mode);
} else
type = -1;
}
#if 0
if (type != tv_priv->type) {
struct drm_property *connector_property =
output->dev->mode_config.connector_type_property;
connector->dev->mode_config.connector_type_property;
tv_priv->type = type;
drm_output_property_set_value(output, connector_property,
drm_connector_property_set_value(connector, connector_property,
type);
}
#endif
if (type < 0)
return output_status_disconnected;
return connector_status_disconnected;
return output_status_connected;
return connector_status_connected;
}
static struct input_res {
@ -1496,10 +1499,11 @@ static struct input_res {
*/
static int
intel_tv_get_modes(struct drm_output *output)
intel_tv_get_modes(struct drm_connector *connector)
{
struct drm_display_mode *mode_ptr;
const struct tv_mode *tv_mode = intel_tv_mode_find(output);
struct intel_output *intel_output = to_intel_output(connector);
const struct tv_mode *tv_mode = intel_tv_mode_find(intel_output);
int j;
for (j = 0; j < sizeof(input_res_table) / sizeof(input_res_table[0]);
@ -1538,33 +1542,33 @@ intel_tv_get_modes(struct drm_output *output)
mode_ptr->htotal / 1000) / 1000;
mode_ptr->type = DRM_MODE_TYPE_DRIVER;
drm_mode_probed_add(output, mode_ptr);
drm_mode_probed_add(connector, mode_ptr);
}
return 0;
}
static void
intel_tv_destroy (struct drm_output *output)
intel_tv_destroy (struct drm_connector *connector)
{
struct intel_output *intel_output = to_intel_output(output);
struct intel_output *intel_output = to_intel_output(connector);
drm_output_cleanup(output);
drm_connector_cleanup(connector);
drm_free(intel_output, sizeof(struct intel_output) + sizeof(struct intel_tv_priv),
DRM_MEM_DRIVER);
}
static bool
intel_tv_set_property(struct drm_output *output, struct drm_property *property,
intel_tv_set_property(struct drm_connector *connector, struct drm_property *property,
uint64_t val)
{
struct drm_device *dev = output->dev;
struct intel_output *intel_output = to_intel_output(output);
struct drm_device *dev = connector->dev;
struct intel_output *intel_output = to_intel_output(connector);
struct intel_tv_priv *tv_priv = intel_output->dev_priv;
int ret = 0;
ret = drm_output_property_set_value(output, property, val);
ret = drm_connector_property_set_value(connector, property, val);
if (ret < 0)
goto out;
@ -1582,40 +1586,55 @@ intel_tv_set_property(struct drm_output *output, struct drm_property *property,
goto out;
}
tv_priv->tv_format = tv_modes[val].name;
intel_tv_mode_set(output, NULL, NULL);
intel_tv_mode_set(&intel_output->enc, NULL, NULL);
} else {
ret = -EINVAL;
goto out;
}
intel_tv_mode_set(output, NULL, NULL);
intel_tv_mode_set(&intel_output->enc, NULL, NULL);
out:
return ret;
}
static const struct drm_output_helper_funcs intel_tv_helper_funcs = {
static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = {
.dpms = intel_tv_dpms,
.mode_fixup = intel_tv_mode_fixup,
.prepare = intel_output_prepare,
.prepare = intel_encoder_prepare,
.mode_set = intel_tv_mode_set,
.commit = intel_output_commit,
.commit = intel_encoder_commit,
};
static const struct drm_output_funcs intel_tv_output_funcs = {
.dpms = intel_tv_dpms,
static const struct drm_connector_funcs intel_tv_connector_funcs = {
.save = intel_tv_save,
.restore = intel_tv_restore,
.mode_valid = intel_tv_mode_valid,
.detect = intel_tv_detect,
.get_modes = intel_tv_get_modes,
.destroy = intel_tv_destroy,
.set_property = intel_tv_set_property,
.fill_modes = drm_helper_probe_single_connector_modes,
};
static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = {
.mode_valid = intel_tv_mode_valid,
.get_modes = intel_tv_get_modes,
.best_encoder = intel_best_encoder,
};
void intel_tv_enc_destroy(struct drm_encoder *encoder)
{
drm_encoder_cleanup(encoder);
}
static const struct drm_encoder_funcs intel_tv_enc_funcs = {
.destroy = intel_tv_enc_destroy,
};
void
intel_tv_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_output *output;
struct drm_connector *connector;
struct intel_output *intel_output;
struct intel_tv_priv *tv_priv;
u32 tv_dac_on, tv_dac_off, save_tv_dac;
@ -1657,17 +1676,21 @@ intel_tv_init(struct drm_device *dev)
if (!intel_output) {
return;
}
output = &intel_output->base;
connector = &intel_output->base;
drm_output_init(dev, output, &intel_tv_output_funcs,
DRM_MODE_OUTPUT_TVDAC);
drm_connector_init(dev, connector, &intel_tv_connector_funcs,
DRM_MODE_CONNECTOR_Unknown);
drm_encoder_init(dev, &intel_output->enc, &intel_tv_enc_funcs,
DRM_MODE_ENCODER_TVDAC);
drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
tv_priv = (struct intel_tv_priv *)(intel_output + 1);
intel_output->type = INTEL_OUTPUT_TVOUT;
output->possible_crtcs = ((1 << 0) | (1 << 1));
output->possible_clones = (1 << INTEL_OUTPUT_TVOUT);
intel_output->enc.possible_crtcs = ((1 << 0) | (1 << 1));
intel_output->enc.possible_clones = (1 << INTEL_OUTPUT_TVOUT);
intel_output->dev_priv = tv_priv;
tv_priv->type = ConnectorUnknown;
tv_priv->type = DRM_MODE_CONNECTOR_Unknown;
/* BIOS margin values */
tv_priv->margin[TV_MARGIN_LEFT] = 54;
@ -1677,13 +1700,10 @@ intel_tv_init(struct drm_device *dev)
tv_priv->tv_format = kstrdup(tv_modes[initial_mode].name, GFP_KERNEL);
drm_output_helper_add(output, &intel_tv_helper_funcs);
output->interlace_allowed = FALSE;
output->doublescan_allowed = FALSE;
drm_output_attach_property(output,
dev->mode_config.connector_type_property,
ConnectorUnknown);
drm_encoder_helper_add(&intel_output->enc, &intel_tv_helper_funcs);
drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
connector->interlace_allowed = FALSE;
connector->doublescan_allowed = FALSE;
/* Create TV properties then attach current values */
tv_format_names = drm_alloc(sizeof(char *) * NUM_TV_MODES,
@ -1694,20 +1714,20 @@ intel_tv_init(struct drm_device *dev)
tv_format_names[i] = tv_modes[i].name;
drm_create_tv_properties(dev, NUM_TV_MODES, tv_format_names);
drm_output_attach_property(output, dev->mode_config.tv_mode_property,
drm_connector_attach_property(connector, dev->mode_config.tv_mode_property,
initial_mode);
drm_output_attach_property(output,
drm_connector_attach_property(connector,
dev->mode_config.tv_left_margin_property,
tv_priv->margin[TV_MARGIN_LEFT]);
drm_output_attach_property(output,
drm_connector_attach_property(connector,
dev->mode_config.tv_top_margin_property,
tv_priv->margin[TV_MARGIN_TOP]);
drm_output_attach_property(output,
drm_connector_attach_property(connector,
dev->mode_config.tv_right_margin_property,
tv_priv->margin[TV_MARGIN_RIGHT]);
drm_output_attach_property(output,
drm_connector_attach_property(connector,
dev->mode_config.tv_bottom_margin_property,
tv_priv->margin[TV_MARGIN_BOTTOM]);
out:
drm_sysfs_output_add(output);
drm_sysfs_connector_add(connector);
}

View file

@ -558,7 +558,7 @@ union drm_wait_vblank {
/* Handle monitor hotplug.
*
* May want to extend this later to pass reply information which
* details the outputs which generated the hotplug event.
* details the connectors which generated the hotplug event.
* Some chipsets can't determine that though, and we'd need to leave
* it to the higher levels to determine exactly what changed.
*/
@ -998,7 +998,7 @@ struct drm_mm_info_arg {
* Drm mode setting
*/
#define DRM_DISPLAY_INFO_LEN 32
#define DRM_OUTPUT_NAME_LEN 32
#define DRM_CONNECTOR_NAME_LEN 32
#define DRM_DISPLAY_MODE_LEN 32
#define DRM_PROP_NAME_LEN 32
@ -1025,58 +1025,69 @@ struct drm_mode_modeinfo {
struct drm_mode_card_res {
uint64_t fb_id_ptr;
uint64_t crtc_id_ptr;
uint64_t output_id_ptr;
uint64_t connector_id_ptr;
uint64_t encoder_id_ptr;
int count_fbs;
int count_crtcs;
int count_outputs;
int count_connectors;
int count_encoders;
int min_width, max_width;
int min_height, max_height;
};
struct drm_mode_crtc {
uint64_t set_outputs_ptr;
uint64_t set_connectors_ptr;
unsigned int crtc_id; /**< Id */
unsigned int fb_id; /**< Id of framebuffer */
int x, y; /**< Position on the frameuffer */
int count_outputs;
unsigned int outputs; /**< Outputs that are connected */
int count_connectors;
unsigned int connectors; /**< Connectors that are connected */
int count_possibles;
unsigned int possibles; /**< Outputs that can be connected */
unsigned int possibles; /**< Connectors that can be connected */
int gamma_size;
int mode_valid;
struct drm_mode_modeinfo mode;
};
#define DRM_MODE_OUTPUT_NONE 0
#define DRM_MODE_OUTPUT_DAC 1
#define DRM_MODE_OUTPUT_TMDS 2
#define DRM_MODE_OUTPUT_LVDS 3
#define DRM_MODE_OUTPUT_TVDAC 4
struct drm_mode_get_encoder {
struct drm_mode_get_output {
uint32_t encoder_type;
uint32_t encoder_id;
unsigned int crtc; /**< Id of crtc */
uint32_t crtcs;
uint32_t clones;
};
#define DRM_MODE_ENCODER_NONE 0
#define DRM_MODE_ENCODER_DAC 1
#define DRM_MODE_ENCODER_TMDS 2
#define DRM_MODE_ENCODER_LVDS 3
#define DRM_MODE_ENCODER_TVDAC 4
struct drm_mode_get_connector {
uint64_t encoders_ptr;
uint64_t modes_ptr;
uint64_t props_ptr;
uint64_t prop_values_ptr;
int count_modes;
int count_props;
unsigned int output; /**< Id */
unsigned int crtc; /**< Id of crtc */
unsigned int output_type;
unsigned int output_type_id;
int count_encoders;
unsigned int encoder; /**< Current Encoder */
unsigned int connector; /**< Id */
unsigned int connector_type;
unsigned int connector_type_id;
unsigned int connection;
unsigned int mm_width, mm_height; /**< HxW in millimeters */
unsigned int subpixel;
int count_crtcs;
int count_clones;
unsigned int crtcs; /**< possible crtc to connect to */
unsigned int clones; /**< list of clones */
};
#define DRM_MODE_PROP_PENDING (1<<0)
@ -1102,10 +1113,10 @@ struct drm_mode_get_property {
int count_enum_blobs;
};
struct drm_mode_output_set_property {
struct drm_mode_connector_set_property {
uint64_t value;
unsigned int prop_id;
unsigned int output_id;
unsigned int connector_id;
};
struct drm_mode_get_blob {
@ -1124,7 +1135,7 @@ struct drm_mode_fb_cmd {
};
struct drm_mode_mode_cmd {
unsigned int output_id;
unsigned int connector_id;
struct drm_mode_modeinfo mode;
};
@ -1260,13 +1271,13 @@ struct drm_mode_hotplug {
#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res)
#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc)
#define DRM_IOCTL_MODE_GETOUTPUT DRM_IOWR(0xA2, struct drm_mode_get_output)
#define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA2, struct drm_mode_get_connector)
#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA3, struct drm_mode_crtc)
#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xA4, struct drm_mode_fb_cmd)
#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xA5, unsigned int)
#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xA6, struct drm_mode_fb_cmd)
#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xA7, struct drm_mode_output_set_property)
#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xA7, struct drm_mode_connector_set_property)
#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xA8, struct drm_mode_get_blob)
#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd)
#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xAA, struct drm_mode_mode_cmd)
@ -1277,6 +1288,7 @@ struct drm_mode_hotplug {
#define DRM_IOCTL_WAIT_HOTPLUG DRM_IOWR(0xAE, union drm_wait_hotplug)
#define DRM_IOCTL_MODE_REPLACEFB DRM_IOWR(0xAF, struct drm_mode_fb_cmd)
#define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xB0, struct drm_mode_get_encoder)
/*@}*/
/**

View file

@ -453,15 +453,15 @@ static spinlock_t hotplug_lock = SPIN_LOCK_UNLOCKED;
static void i915_hotplug_tv(struct drm_device *dev)
{
struct drm_output *output;
struct drm_connector *connector;
struct intel_output *iout;
enum drm_output_status status;
enum drm_connector_status status;
mutex_lock(&dev->mode_config.mutex);
/* find the crt output */
list_for_each_entry(output, &dev->mode_config.output_list, head) {
iout = to_intel_output(output);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
iout = to_intel_output(connector);
if (iout->type == INTEL_OUTPUT_TVOUT)
break;
else
@ -471,9 +471,9 @@ static void i915_hotplug_tv(struct drm_device *dev)
if (iout == 0)
goto unlock;
status = output->funcs->detect(output);
drm_helper_hotplug_stage_two(dev, output,
status == output_status_connected ? 1 : 0);
status = connector->funcs->detect(connector);
drm_helper_hotplug_stage_two(dev, connector,
status == connector_status_connected ? 1 : 0);
unlock:
mutex_unlock(&dev->mode_config.mutex);
@ -481,14 +481,14 @@ unlock:
static void i915_hotplug_crt(struct drm_device *dev, bool isconnected)
{
struct drm_output *output;
struct drm_connector *connector;
struct intel_output *iout;
mutex_lock(&dev->mode_config.mutex);
/* find the crt output */
list_for_each_entry(output, &dev->mode_config.output_list, head) {
iout = to_intel_output(output);
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
iout = to_intel_output(connector);
if (iout->type == INTEL_OUTPUT_ANALOG)
break;
else
@ -498,7 +498,7 @@ static void i915_hotplug_crt(struct drm_device *dev, bool isconnected)
if (iout == 0)
goto unlock;
drm_helper_hotplug_stage_two(dev, output, isconnected);
drm_helper_hotplug_stage_two(dev, connector, isconnected);
unlock:
mutex_unlock(&dev->mode_config.mutex);
@ -506,24 +506,24 @@ unlock:
static void i915_hotplug_sdvo(struct drm_device *dev, int sdvoB)
{
struct drm_output *output = 0;
enum drm_output_status status;
struct drm_connector *connector = 0;
enum drm_connector_status status;
mutex_lock(&dev->mode_config.mutex);
output = intel_sdvo_find(dev, sdvoB);
connector = intel_sdvo_find(dev, sdvoB);
if (!output)
if (!connector)
goto unlock;
status = output->funcs->detect(output);
status = connector->funcs->detect(connector);
if (status != output_status_connected)
drm_helper_hotplug_stage_two(dev, output, false);
if (status != connector_status_connected)
drm_helper_hotplug_stage_two(dev, connector, false);
else
drm_helper_hotplug_stage_two(dev, output, true);
drm_helper_hotplug_stage_two(dev, connector, true);
intel_sdvo_set_hotplug(output, 1);
intel_sdvo_set_hotplug(connector, 1);
unlock:
mutex_unlock(&dev->mode_config.mutex);
@ -961,15 +961,15 @@ void i915_disable_vblank(struct drm_device *dev, int plane)
void i915_enable_interrupt (struct drm_device *dev)
{
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
struct drm_output *o;
struct drm_connector *o;
dev_priv->irq_enable_reg |= I915_USER_INTERRUPT;
if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) {
if (dev->mode_config.num_output)
if (dev->mode_config.num_connector)
dev_priv->irq_enable_reg |= I915_DISPLAY_PORT_INTERRUPT;
} else {
if (dev->mode_config.num_output)
if (dev->mode_config.num_connector)
dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
/* Enable global interrupts for hotplug - not a pipeA event */

View file

@ -47,27 +47,32 @@ int printMode(struct drm_mode_modeinfo *mode)
return 0;
}
int printOutput(int fd, drmModeResPtr res, drmModeOutputPtr output, uint32_t id)
int printConnector(int fd, drmModeResPtr res, drmModeConnectorPtr connector, uint32_t id)
{
int i = 0, j;
struct drm_mode_modeinfo *mode = NULL;
drmModePropertyPtr props;
drmModeEncoderPtr enc;
unsigned char *name = NULL;
printf("Output: %d-%d\n", output->output_type, output->output_type_id);
printf("Connector: %d-%d\n", connector->connector_type, connector->connector_type_id);
printf("\tid : %i\n", id);
printf("\tcrtc id : %i\n", output->crtc);
printf("\tconn : %s\n", getConnectionText(output->connection));
printf("\tsize : %ix%i (mm)\n", output->mmWidth, output->mmHeight);
printf("\tcount_crtcs : %i\n", output->count_crtcs);
printf("\tcrtcs : %i\n", output->crtcs);
printf("\tcount_clones : %i\n", output->count_clones);
printf("\tclones : %i\n", output->clones);
printf("\tcount_modes : %i\n", output->count_modes);
printf("\tcount_props : %i\n", output->count_props);
printf("\tencoder id : %i\n", connector->encoder);
printf("\tconn : %s\n", getConnectionText(connector->connection));
printf("\tsize : %ix%i (mm)\n", connector->mmWidth, connector->mmHeight);
printf("\tcount_modes : %i\n", connector->count_modes);
printf("\tcount_props : %i\n", connector->count_props);
printf("\tcount_encs : %i\n", connector->count_encoders);
for (i = 0; i < output->count_props; i++) {
props = drmModeGetProperty(fd, output->props[i]);
for (i = 0; i < connector->count_encoders; i++) {
enc = drmModeGetEncoder(fd, connector->encoders[i]);
if (enc) {
printf("Encoder: %d %d %d %d %d\n", enc->crtc, enc->encoder_id, enc->encoder_type, enc->crtcs, enc->clones);
}
}
for (i = 0; i < connector->count_props; i++) {
props = drmModeGetProperty(fd, connector->props[i]);
name = NULL;
if (props) {
printf("Property: %s\n", props->name);
@ -82,7 +87,7 @@ int printOutput(int fd, drmModeResPtr res, drmModeOutputPtr output, uint32_t id)
if (props->flags & DRM_MODE_PROP_BLOB) {
drmModePropertyBlobPtr blob;
blob = drmModeGetPropertyBlob(fd, output->prop_values[i]);
blob = drmModeGetPropertyBlob(fd, connector->prop_values[i]);
if (blob) {
printf("blob is %d length, %08X\n", blob->length, *(uint32_t *)blob->data);
drmModeFreePropertyBlob(blob);
@ -94,15 +99,15 @@ int printOutput(int fd, drmModeResPtr res, drmModeOutputPtr output, uint32_t id)
for (j = 0; j < props->count_enums; j++) {
printf("\t\t%lld = %s\n", props->enums[j].value, props->enums[j].name);
if (output->prop_values[i] == props->enums[j].value)
if (connector->prop_values[i] == props->enums[j].value)
name = props->enums[j].name;
}
if (props->count_enums && name) {
printf("\toutput property name %s %s\n", props->name, name);
printf("\tconnector property name %s %s\n", props->name, name);
} else {
printf("\toutput property id %s %lli\n", props->name, output->prop_values[i]);
printf("\tconnector property id %s %lli\n", props->name, connector->prop_values[i]);
}
}
@ -110,17 +115,27 @@ int printOutput(int fd, drmModeResPtr res, drmModeOutputPtr output, uint32_t id)
}
}
for (i = 0; i < output->count_modes; i++) {
mode = &output->modes[i];
for (i = 0; i < connector->count_modes; i++) {
mode = &connector->modes[i];
if (mode)
printMode(mode);
else
printf("\t\tmode: Invalid mode %p\n", &output->modes[i]);
printf("\t\tmode: Invalid mode %p\n", &connector->modes[i]);
}
return 0;
}
int printEncoder(int fd, drmModeResPtr res, drmModeEncoderPtr encoder, uint32_t id)
{
printf("Encoder\n");
printf("\tid :%i\n", id);
printf("\ttype :%d\n", encoder->encoder_type);
printf("\tcrtcs :%d\n", encoder->crtcs);
printf("\tclones :%d\n", encoder->clones);
return 0;
}
int printCrtc(int fd, drmModeResPtr res, drmModeCrtcPtr crtc, uint32_t id)
{
printf("Crtc\n");
@ -130,8 +145,8 @@ int printCrtc(int fd, drmModeResPtr res, drmModeCrtcPtr crtc, uint32_t id)
printf("\twidth : %i\n", crtc->width);
printf("\theight : %i\n", crtc->height);
printf("\tmode : %p\n", &crtc->mode);
printf("\tnum outputs : %i\n", crtc->count_outputs);
printf("\toutputs : %i\n", crtc->outputs);
printf("\tnum connectors : %i\n", crtc->count_connectors);
printf("\tconnectors : %i\n", crtc->connectors);
printf("\tnum possible : %i\n", crtc->count_possibles);
printf("\tpossibles : %i\n", crtc->possibles);
@ -155,21 +170,34 @@ int printFrameBuffer(int fd, drmModeResPtr res, drmModeFBPtr fb)
int printRes(int fd, drmModeResPtr res)
{
int i;
drmModeOutputPtr output;
drmModeConnectorPtr connector;
drmModeCrtcPtr crtc;
drmModeFBPtr fb;
drmModeEncoderPtr encoder;
for (i = 0; i < res->count_outputs; i++) {
output = drmModeGetOutput(fd, res->outputs[i]);
for (i = 0; i < res->count_connectors; i++) {
connector = drmModeGetConnector(fd, res->connectors[i]);
if (!output)
printf("Could not get output %i\n", i);
if (!connector)
printf("Could not get connector %i\n", i);
else {
printOutput(fd, res, output, res->outputs[i]);
drmModeFreeOutput(output);
printConnector(fd, res, connector, res->connectors[i]);
drmModeFreeConnector(connector);
}
}
for (i = 0; i < res->count_encoders; i++) {
encoder = drmModeGetEncoder(fd, res->encoders[i]);
if (!encoder)
printf("Could not get encoder %i\n", i);
else {
printEncoder(fd, res, encoder, res->encoders[i]);
drmModeFreeEncoder(encoder);
}
}
for (i = 0; i < res->count_crtcs; i++) {
crtc = drmModeGetCrtc(fd, res->crtcs[i]);
@ -214,24 +242,24 @@ static struct drm_mode_modeinfo mode = {
int testMode(int fd, drmModeResPtr res)
{
uint32_t output = res->outputs[0];
uint32_t connector = res->connectors[0];
uint32_t newMode = 0;
int ret = 0;
int error = 0;
printf("Test: adding mode to output %i\n", output);
printf("Test: adding mode to connector %i\n", connector);
/* printMode(&mode); */
printf("\tAttaching mode %i to output %i\n", newMode, output);
printf("\tAttaching mode %i to connector %i\n", newMode, connector);
ret = drmModeAttachMode(fd, output, &mode);
ret = drmModeAttachMode(fd, connector, &mode);
if (ret)
goto err_mode;
printf("\tDetaching mode %i from output %i\n", newMode, output);
ret = drmModeDetachMode(fd, output, &mode);
printf("\tDetaching mode %i from connector %i\n", newMode, connector);
ret = drmModeDetachMode(fd, connector, &mode);
if (ret)
goto err_mode;
@ -330,15 +358,15 @@ err:
int testDPMS(int fd, drmModeResPtr res)
{
int output_id;
int connector_id;
int i;
for (i = 0; i < res->count_outputs; i++) {
output_id = res->outputs[i];
/* turn output off */
drmModeOutputSetProperty(fd, output_id, dpms_prop_id, 3);
for (i = 0; i < res->count_connectors; i++) {
connector_id = res->connectors[i];
/* turn connector off */
drmModeConnectorSetProperty(fd, connector_id, dpms_prop_id, 3);
sleep(2);
drmModeOutputSetProperty(fd, output_id, dpms_prop_id, 0);
drmModeConnectorSetProperty(fd, connector_id, dpms_prop_id, 0);
}
return 1;