mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-01-06 06:10:18 +01:00
Merge branch 'modesetting-101-encoders' into modesetting-101
This commit is contained in:
commit
eba6cdc936
29 changed files with 1932 additions and 1478 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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__ */
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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, ®9);
|
||||
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue