mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2026-05-05 19:28:03 +02:00
SDVO almost works
This commit is contained in:
parent
02951cc179
commit
6034c55916
2 changed files with 170 additions and 24 deletions
|
|
@ -60,7 +60,7 @@ struct intel_sdvo_priv {
|
|||
* SDVOB and SDVOC to work around apparent hardware issues (according to
|
||||
* comments in the BIOS).
|
||||
*/
|
||||
static void intel_sdvo_write_sdvox(struct drm_output *output, u32 val)
|
||||
void intel_sdvo_write_sdvox(struct drm_output *output, u32 val)
|
||||
{
|
||||
struct drm_device *dev = output->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
|
@ -69,10 +69,12 @@ static void intel_sdvo_write_sdvox(struct drm_output *output, u32 val)
|
|||
u32 bval = val, cval = val;
|
||||
int i;
|
||||
|
||||
if (sdvo_priv->output_device == SDVOB)
|
||||
if (sdvo_priv->output_device == SDVOB) {
|
||||
cval = I915_READ(SDVOC);
|
||||
else
|
||||
bval = I915_READ(SDVOB);
|
||||
bval = bval | (1 << 26);
|
||||
} else {
|
||||
bval = I915_READ(SDVOB) | (1 << 26);
|
||||
}
|
||||
/*
|
||||
* Write the registers twice for luck. Sometimes,
|
||||
* writing them only once doesn't appear to 'stick'.
|
||||
|
|
@ -879,6 +881,70 @@ void intel_sdvo_dump(void)
|
|||
|
||||
}
|
||||
|
||||
struct drm_output* intel_sdvo_find(struct drm_device *dev, int sdvoB)
|
||||
{
|
||||
struct drm_output *output = 0;
|
||||
struct intel_output *iout = 0;
|
||||
struct intel_sdvo_priv *sdvo;
|
||||
|
||||
/* find the sdvo output */
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head) {
|
||||
iout = output->driver_private;
|
||||
|
||||
if (iout->type != INTEL_OUTPUT_SDVO) {
|
||||
iout = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
sdvo = iout->dev_priv;
|
||||
|
||||
if (sdvo->output_device == SDVOB && sdvoB)
|
||||
break;
|
||||
|
||||
if (sdvo->output_device == SDVOC && !sdvoB)
|
||||
break;
|
||||
|
||||
sdvo = 0;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
int intel_sdvo_supports_hotplug(struct drm_output *output)
|
||||
{
|
||||
u8 response[2];
|
||||
u8 status;
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
intel_sdvo_write_cmd(output, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0);
|
||||
status = intel_sdvo_read_response(output, &response, 2);
|
||||
|
||||
if (response[0] !=0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void intel_sdvo_set_hotplug(struct drm_output *output, int on)
|
||||
{
|
||||
u8 response[2];
|
||||
u8 status;
|
||||
|
||||
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(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);
|
||||
}
|
||||
|
||||
DRM_DEBUG("readback\n");
|
||||
intel_sdvo_write_cmd(output, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0);
|
||||
intel_sdvo_read_response(output, &response, 2);
|
||||
}
|
||||
|
||||
static enum drm_output_status intel_sdvo_detect(struct drm_output *output)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -307,26 +307,19 @@ static struct drm_device *hotplug_dev;
|
|||
static int hotplug_cmd = 0;
|
||||
static spinlock_t hotplug_lock = SPIN_LOCK_UNLOCKED;
|
||||
|
||||
static void i915_hotplug_crt(struct drm_device *dev)
|
||||
/* TODO
|
||||
* The locking in these functions are realy messed up.
|
||||
* Currently the stage 1 functions takes both the locks.
|
||||
* But have to release it since intel_fb_probe grabs the
|
||||
* struct_mTODO utex. So to do this as cleanly as possible
|
||||
* you need to release the locks between stage 1 and 2.
|
||||
*/
|
||||
|
||||
static void i915_hotplug_stage2(struct drm_device *dev, struct drm_output *output)
|
||||
{
|
||||
struct drm_output *output;
|
||||
struct drm_crtc *crtc;
|
||||
struct intel_output *iout;
|
||||
int has_config = 0;
|
||||
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
|
||||
/* find the crt output */
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head) {
|
||||
iout = output->driver_private;
|
||||
if (iout->type == INTEL_OUTPUT_ANALOG)
|
||||
break;
|
||||
}
|
||||
|
||||
if (iout == 0)
|
||||
goto unlock;
|
||||
|
||||
if (output->crtc && output->crtc->desired_mode) {
|
||||
DRM_DEBUG("monkey has banana\n");
|
||||
|
|
@ -357,6 +350,36 @@ static void i915_hotplug_crt(struct drm_device *dev)
|
|||
|
||||
drm_disable_unused_functions(dev);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
}
|
||||
|
||||
static void i915_hotplug_crt(struct drm_device *dev)
|
||||
{
|
||||
struct drm_output *output;
|
||||
struct intel_output *iout;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
|
||||
/* find the crt output */
|
||||
list_for_each_entry(output, &dev->mode_config.output_list, head) {
|
||||
iout = output->driver_private;
|
||||
if (iout->type == INTEL_OUTPUT_ANALOG)
|
||||
break;
|
||||
else
|
||||
iout = 0;
|
||||
}
|
||||
|
||||
if (iout == 0)
|
||||
goto unlock;
|
||||
|
||||
/* TODO ugly locking */
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
i915_hotplug_stage2(dev, output);
|
||||
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
return;
|
||||
|
||||
|
|
@ -367,6 +390,41 @@ unlock:
|
|||
DRM_DEBUG("monkey hunt done\n");
|
||||
}
|
||||
|
||||
static void i915_hotplug_sdvo(struct drm_device *dev, int sdvoB)
|
||||
{
|
||||
struct drm_output *output = 0;
|
||||
enum drm_output_status status;
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
|
||||
output = intel_sdvo_find(dev, sdvoB);
|
||||
|
||||
if (!output) {
|
||||
DRM_ERROR("could not find sdvo%s output\n", sdvoB ? "B" : "C");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
status = output->funcs->detect(output);
|
||||
|
||||
if (status != output_status_connected) {
|
||||
DRM_DEBUG("disconnect or unkown we don't do anything then\n");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
/* TODO ugly locking */
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
i915_hotplug_stage2(dev, output);
|
||||
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
return;
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
|
||||
static void i915_hotplug_work_func(struct work_struct *work)
|
||||
{
|
||||
struct drm_device *dev = hotplug_dev;
|
||||
|
|
@ -383,6 +441,13 @@ static void i915_hotplug_work_func(struct work_struct *work)
|
|||
|
||||
if (crt)
|
||||
i915_hotplug_crt(dev);
|
||||
|
||||
if (sdvoB)
|
||||
i915_hotplug_sdvo(dev, 1);
|
||||
|
||||
if (sdvoC)
|
||||
i915_hotplug_sdvo(dev, 0);
|
||||
|
||||
}
|
||||
|
||||
static int i915_run_hotplug_tasklet(struct drm_device *dev, uint32_t stat)
|
||||
|
|
@ -453,6 +518,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
|||
DRM_DEBUG("MSK %08x\n", dev_priv->irq_enable_reg | USER_INT_FLAG);
|
||||
DRM_DEBUG("M&I %08x\n", temp);
|
||||
DRM_DEBUG("HOT %08x\n", I915_READ(PORT_HOTPLUG_STAT));
|
||||
} else {
|
||||
/* DRM_DEBUG("v\n"); */
|
||||
}
|
||||
#else
|
||||
DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
|
||||
|
|
@ -684,6 +751,7 @@ int i915_irq_wait(struct drm_device *dev, void *data,
|
|||
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;
|
||||
|
||||
dev_priv->irq_enable_reg = USER_INT_FLAG;
|
||||
if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
|
||||
|
|
@ -694,8 +762,17 @@ void i915_enable_interrupt (struct drm_device *dev)
|
|||
/* if (dev_priv->mode_setting) */ {
|
||||
dev_priv->irq_enable_reg |= (1 << 17);
|
||||
|
||||
/* Activate the CRT hotplug detection */
|
||||
I915_WRITE(PORT_HOTPLUG_EN, (1 << 9));
|
||||
/* Activate the CRT and SDVOB hotplug detection */
|
||||
I915_WRITE(PORT_HOTPLUG_EN, (1 << 9) | (1 << 26));
|
||||
|
||||
o = intel_sdvo_find(dev, 1);
|
||||
if (o) {
|
||||
intel_sdvo_supports_hotplug(o);
|
||||
|
||||
intel_sdvo_set_hotplug(o, 1);
|
||||
I915_WRITE(SDVOB, I915_READ(SDVOB) | (1 << 26));
|
||||
I915_WRITE(SDVOB, I915_READ(SDVOB) | (1 << 26));
|
||||
}
|
||||
}
|
||||
|
||||
/* if (IS_I9XX(dev_priv)) */ {
|
||||
|
|
@ -707,6 +784,9 @@ void i915_enable_interrupt (struct drm_device *dev)
|
|||
DRM_DEBUG("HEN %08x\n",I915_READ(PORT_HOTPLUG_EN));
|
||||
DRM_DEBUG("HST %08x\n",I915_READ(PORT_HOTPLUG_STAT));
|
||||
DRM_DEBUG("IER %08x\n",I915_READ(I915REG_INT_ENABLE_R));
|
||||
DRM_DEBUG("SDB %08x\n",I915_READ(SDVOB));
|
||||
|
||||
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
|
||||
|
||||
dev_priv->irq_enabled = 1;
|
||||
|
||||
|
|
@ -914,8 +994,8 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
|
|||
struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private;
|
||||
|
||||
I915_WRITE16(I915REG_HWSTAM, 0xeffe);
|
||||
I915_WRITE16(I915REG_INT_MASK_R, 0x0);
|
||||
I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
|
||||
I915_WRITE(I915REG_INT_MASK_R, 0x0);
|
||||
I915_WRITE(I915REG_INT_ENABLE_R, 0x0);
|
||||
}
|
||||
|
||||
void i915_driver_irq_postinstall(struct drm_device * dev)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue