From 52f9028c84baea81230dc673b756552e8e90aecd Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 5 Apr 2007 11:21:06 +1000 Subject: Initial import of modesetting for intel driver in DRM --- linux-core/intel_sdvo.c | 999 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 999 insertions(+) create mode 100644 linux-core/intel_sdvo.c (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c new file mode 100644 index 00000000..4094b788 --- /dev/null +++ b/linux-core/intel_sdvo.c @@ -0,0 +1,999 @@ +/* + * Copyright 2006 Dave Airlie + * Copyright © 2006 Intel Corporation + * Eric Anholt + * Jesse Barnes + */ + +#include +#include "drmP.h" +#include "drm.h" +#include "drm_crtc.h" +#include "intel_drv.h" +#include "i915_drm.h" +#include "i915_drv.h" +#include "intel_sdvo_regs.h" + +struct intel_sdvo_priv { + struct intel_i2c_chan *i2c_bus; + int slaveaddr; + int output_device; + + u16 active_outputs; + + struct intel_sdvo_caps caps; + int pixel_clock_min, pixel_clock_max; + + int save_sdvo_mult; + u16 save_active_outputs; + struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2; + struct intel_sdvo_dtd save_output_dtd[16]; + u32 save_SDVOX; +}; + +/** + * Writes the SDVOB or SDVOC with the given value, but always writes both + * 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) +{ + drm_device_t *dev = output->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_output *intel_output = output->driver_private; + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + u32 bval = val, cval = val; + int i; + + if (sdvo_priv->output_device == SDVOB) + cval = I915_READ(SDVOC); + else + bval = I915_READ(SDVOB); + + /* + * Write the registers twice for luck. Sometimes, + * writing them only once doesn't appear to 'stick'. + * The BIOS does this too. Yay, magic + */ + for (i = 0; i < 2; i++) + { + I915_WRITE(SDVOB, bval); + I915_READ(SDVOB); + I915_WRITE(SDVOC, cval); + I915_READ(SDVOC); + } +} + +static bool intel_sdvo_read_byte(struct drm_output *output, u8 addr, + u8 *ch) +{ + struct intel_output *intel_output = output->driver_private; + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + u8 out_buf[2]; + u8 buf[2]; + int ret; + + struct i2c_msg msgs[] = { + { + .addr = sdvo_priv->i2c_bus->slave_addr, + .flags = 0, + .len = 1, + .buf = out_buf, + }, + { + .addr = sdvo_priv->i2c_bus->slave_addr, + .flags = I2C_M_RD, + .len = 1, + .buf = buf, + } + }; + + out_buf[0] = addr; + out_buf[1] = 0; + + if ((ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2)) == 2) + { +// DRM_DEBUG("got back from addr %02X = %02x\n", out_buf[0], buf[0]); + *ch = buf[0]; + return true; + } + + DRM_DEBUG("i2c transfer returned %d\n", ret); + return false; +} + + +static bool intel_sdvo_read_byte_quiet(struct drm_output *output, int addr, + u8 *ch) +{ + return true; + +} + +static bool intel_sdvo_write_byte(struct drm_output *output, int addr, + u8 ch) +{ + struct intel_output *intel_output = output->driver_private; + u8 out_buf[2]; + struct i2c_msg msgs[] = { + { + .addr = intel_output->i2c_bus->slave_addr, + .flags = 0, + .len = 2, + .buf = out_buf, + } + }; + + out_buf[0] = addr; + out_buf[1] = ch; + + if (i2c_transfer(&intel_output->i2c_bus->adapter, msgs, 1) == 1) + { + return true; + } + return false; +} + +#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} +/** Mapping of command numbers to names, for debug output */ +const static struct _sdvo_cmd_name { + u8 cmd; + char *name; +} sdvo_cmd_names[] = { + SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_RESOLUTION_SUPPORT), + SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH), +}; + +#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, + void *args, int args_len) +{ + struct intel_output *intel_output = output->driver_private; + int i; + + for (i = 0; i < args_len; i++) { + intel_sdvo_write_byte(output, SDVO_I2C_ARG_0 - i, ((u8*)args)[i]); + } + intel_sdvo_write_byte(output, SDVO_I2C_OPCODE, cmd); +} + +static const char *cmd_status_names[] = { + "Power on", + "Success", + "Not supported", + "Invalid arg", + "Pending", + "Target not specified", + "Scaling not supported" +}; + +static u8 intel_sdvo_read_response(struct drm_output *output, void *response, + int response_len) +{ + int i; + u8 status; + + /* Read the command response */ + for (i = 0; i < response_len; i++) { + intel_sdvo_read_byte(output, SDVO_I2C_RETURN_0 + i, + &((u8 *)response)[i]); + } + + /* read the return status */ + intel_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, &status); + + return status; + +} + +int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) +{ + if (mode->clock >= 100000) + return 1; + else if (mode->clock >= 50000) + return 2; + else + return 4; +} + +static void intel_sdvo_set_control_bus_switch(struct drm_output *output, u8 target) +{ + intel_sdvo_write_cmd(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) +{ + struct intel_sdvo_set_target_input_args targets = {0}; + u8 status; + + if (target_0 && target_1) + return SDVO_CMD_STATUS_NOTSUPP; + + if (target_1) + targets.target_1 = 1; + + intel_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_INPUT, &targets, + sizeof(targets)); + + status = intel_sdvo_read_response(output, NULL, 0); + + return (status == SDVO_CMD_STATUS_SUCCESS); +} + +/** + * Return whether each input is trained. + * + * 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) +{ + 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)); + if (status != SDVO_CMD_STATUS_SUCCESS) + return false; + + *input_1 = response.input0_trained; + *input_2 = response.input1_trained; + return TRUE; +} + +static bool intel_sdvo_get_active_outputs(struct drm_output *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)); + + return (status == SDVO_CMD_STATUS_SUCCESS); +} + +static bool intel_sdvo_set_active_outputs(struct drm_output *output, + u16 outputs) +{ + u8 status; + + intel_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_OUTPUTS, &outputs, + sizeof(outputs)); + status = intel_sdvo_read_response(output, NULL, 0); + return (status == SDVO_CMD_STATUS_SUCCESS); +} + +static bool intel_sdvo_set_encoder_power_state(struct drm_output *output, + int mode) +{ + u8 status, state = SDVO_ENCODER_STATE_ON; + + switch (mode) { + case DPMSModeOn: + state = SDVO_ENCODER_STATE_ON; + break; + case DPMSModeStandby: + state = SDVO_ENCODER_STATE_STANDBY; + break; + case DPMSModeSuspend: + state = SDVO_ENCODER_STATE_SUSPEND; + break; + case DPMSModeOff: + state = SDVO_ENCODER_STATE_OFF; + break; + } + + intel_sdvo_write_cmd(output, SDVO_CMD_SET_ENCODER_POWER_STATE, &state, + sizeof(state)); + status = intel_sdvo_read_response(output, NULL, 0); + + return (status == SDVO_CMD_STATUS_SUCCESS); +} + +static bool intel_sdvo_get_input_pixel_clock_range(struct drm_output *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, + NULL, 0); + + status = intel_sdvo_read_response(output, &clocks, sizeof(clocks)); + + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; + + /* Convert the values from units of 10 kHz to kHz. */ + *clock_min = clocks.min * 10; + *clock_max = clocks.max * 10; + + return TRUE; +} + +static bool intel_sdvo_set_target_output(struct drm_output *output, + u16 outputs) +{ + u8 status; + + intel_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_OUTPUT, &outputs, + sizeof(outputs)); + + status = intel_sdvo_read_response(output, NULL, 0); + return (status == SDVO_CMD_STATUS_SUCCESS); +} + +static bool intel_sdvo_get_timing(struct drm_output *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, + 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, + sizeof(dtd->part2)); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; + + return TRUE; +} + +static bool intel_sdvo_get_input_timing(struct drm_output *output, + struct intel_sdvo_dtd *dtd) +{ + return intel_sdvo_get_timing(output, + SDVO_CMD_GET_INPUT_TIMINGS_PART1, dtd); +} + +static bool intel_sdvo_get_output_timing(struct drm_output *output, + struct intel_sdvo_dtd *dtd) +{ + return intel_sdvo_get_timing(output, + SDVO_CMD_GET_OUTPUT_TIMINGS_PART1, dtd); +} + +static bool intel_sdvo_set_timing(struct drm_output *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); + 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); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; + + return TRUE; +} + +static bool intel_sdvo_set_input_timing(struct drm_output *output, + struct intel_sdvo_dtd *dtd) +{ + return intel_sdvo_set_timing(output, + SDVO_CMD_SET_INPUT_TIMINGS_PART1, dtd); +} + +static bool intel_sdvo_set_output_timing(struct drm_output *output, + struct intel_sdvo_dtd *dtd) +{ + return intel_sdvo_set_timing(output, + SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, dtd); +} + +#if 0 +static bool intel_sdvo_get_preferred_input_timing(struct drm_output *output, + struct intel_sdvo_dtd *dtd) +{ + struct intel_output *intel_output = output->driver_private; + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + u8 status; + + intel_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1, + NULL, 0); + + status = intel_sdvo_read_response(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, + NULL, 0); + status = intel_sdvo_read_response(output, &dtd->part2, + sizeof(dtd->part2)); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; + + return TRUE; +} +#endif + +static int intel_sdvo_get_clock_rate_mult(struct drm_output *output) +{ + struct intel_output *intel_output = output->driver_private; + u8 response, status; + + intel_sdvo_write_cmd(output, SDVO_CMD_GET_CLOCK_RATE_MULT, NULL, 0); + status = intel_sdvo_read_response(output, &response, 1); + + if (status != SDVO_CMD_STATUS_SUCCESS) { + DRM_DEBUG("Couldn't get SDVO clock rate multiplier\n"); + return SDVO_CLOCK_RATE_MULT_1X; + } else { + DRM_DEBUG("Current clock rate multiplier: %d\n", response); + } + + return response; +} + +static bool intel_sdvo_set_clock_rate_mult(struct drm_output *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); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; + + return TRUE; +} + +static bool intel_sdvo_mode_fixup(struct drm_output *output, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + /* Make the CRTC code factor in the SDVO pixel multiplier. The SDVO + * device will be told of the multiplier during mode_set. + */ + adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode); + return TRUE; +} + +static void intel_sdvo_mode_set(struct drm_output *output, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + drm_device_t *dev = output->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_crtc *crtc = output->crtc; + struct intel_crtc *intel_crtc = crtc->driver_private; + struct intel_output *intel_output = output->driver_private; + 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; + u16 h_sync_offset, v_sync_offset; + u32 sdvox; + struct intel_sdvo_dtd output_dtd; + int sdvo_pixel_multiply; + + if (!mode) + return; + + width = mode->crtc_hdisplay; + height = mode->crtc_vdisplay; + + /* do some mode translations */ + h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start; + h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; + + v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start; + v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; + + h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start; + v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start; + + output_dtd.part1.clock = mode->clock / 10; + output_dtd.part1.h_active = width & 0xff; + output_dtd.part1.h_blank = h_blank_len & 0xff; + output_dtd.part1.h_high = (((width >> 8) & 0xf) << 4) | + ((h_blank_len >> 8) & 0xf); + output_dtd.part1.v_active = height & 0xff; + output_dtd.part1.v_blank = v_blank_len & 0xff; + output_dtd.part1.v_high = (((height >> 8) & 0xf) << 4) | + ((v_blank_len >> 8) & 0xf); + + output_dtd.part2.h_sync_off = h_sync_offset; + output_dtd.part2.h_sync_width = h_sync_len & 0xff; + output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 | + (v_sync_len & 0xf); + output_dtd.part2.sync_off_width_high = ((h_sync_offset & 0x300) >> 2) | + ((h_sync_len & 0x300) >> 4) | ((v_sync_offset & 0x30) >> 2) | + ((v_sync_len & 0x30) >> 4); + + output_dtd.part2.dtd_flags = 0x18; + if (mode->flags & V_PHSYNC) + output_dtd.part2.dtd_flags |= 0x2; + if (mode->flags & V_PVSYNC) + output_dtd.part2.dtd_flags |= 0x4; + + output_dtd.part2.sdvo_flags = 0; + output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0; + 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); + + /* Set the input timing to the screen. Assume always input 0. */ + intel_sdvo_set_target_input(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 + * feature. However, presumably we would need to adjust the CRTC to + * output the preferred timing, and we don't support that currently. + */ +#if 0 + success = intel_sdvo_create_preferred_input_timing(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); + } +#else + intel_sdvo_set_input_timing(output, &output_dtd); +#endif + + switch (intel_sdvo_get_pixel_multiplier(mode)) { + case 1: + intel_sdvo_set_clock_rate_mult(output, + SDVO_CLOCK_RATE_MULT_1X); + break; + case 2: + intel_sdvo_set_clock_rate_mult(output, + SDVO_CLOCK_RATE_MULT_2X); + break; + case 4: + intel_sdvo_set_clock_rate_mult(output, + SDVO_CLOCK_RATE_MULT_4X); + break; + } + + /* Set the SDVO control regs. */ + sdvox = I915_READ(sdvo_priv->output_device); + switch (sdvo_priv->output_device) { + case SDVOB: + sdvox &= SDVOB_PRESERVE_MASK; + break; + case SDVOC: + sdvox &= SDVOC_PRESERVE_MASK; + break; + } + sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; + if (intel_crtc->pipe == 1) + sdvox |= SDVO_PIPE_B_SELECT; + + sdvo_pixel_multiply = intel_sdvo_get_pixel_multiplier(mode); + if (IS_I965G(dev)) { + /* done in crtc_mode_set as the dpll_md reg must be written + early */ + } else if (IS_I945G(dev) || IS_I945GM(dev)) { + /* done in crtc_mode_set as it lives inside the + dpll register */ + } else { + sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT; + } + + intel_sdvo_write_sdvox(output, sdvox); +} + +static void intel_sdvo_dpms(struct drm_output *output, int mode) +{ + drm_device_t *dev = output->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_output *intel_output = output->driver_private; + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + u32 temp; + + if (mode != DPMSModeOn) { + intel_sdvo_set_active_outputs(output, 0); + if (0) + intel_sdvo_set_encoder_power_state(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); + } + } + } else { + bool input1, input2; + int i; + u8 status; + + temp = I915_READ(sdvo_priv->output_device); + if ((temp & SDVO_ENABLE) == 0) + intel_sdvo_write_sdvox(output, temp | SDVO_ENABLE); + for (i = 0; i < 2; i++) + intel_wait_for_vblank(dev); + + status = intel_sdvo_get_trained_inputs(output, &input1, + &input2); + + + /* Warn if the device reported failure to sync. */ + if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { + DRM_ERROR("First %s output reported failure to sync\n", + SDVO_NAME(sdvo_priv)); + } + + if (0) + intel_sdvo_set_encoder_power_state(output, mode); + intel_sdvo_set_active_outputs(output, sdvo_priv->active_outputs); + } + return; +} + +static void intel_sdvo_save(struct drm_output *output) +{ + drm_device_t *dev = output->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_output *intel_output = output->driver_private; + 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); + + if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) { + intel_sdvo_set_target_input(output, TRUE, FALSE); + intel_sdvo_get_input_timing(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, + &sdvo_priv->save_input_dtd_2); + } + + 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_get_output_timing(output, + &sdvo_priv->save_output_dtd[o]); + } + } + + sdvo_priv->save_SDVOX = I915_READ(sdvo_priv->output_device); +} + +static void intel_sdvo_restore(struct drm_output *output) +{ + drm_device_t *dev = output->dev; + drm_i915_private_t *dev_priv = dev->dev_private; + struct intel_output *intel_output = output->driver_private; + 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); + + 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]); + } + } + + 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); + } + + 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_clock_rate_mult(output, sdvo_priv->save_sdvo_mult); + + I915_WRITE(sdvo_priv->output_device, sdvo_priv->save_SDVOX); + + if (sdvo_priv->save_SDVOX & SDVO_ENABLE) + { + for (i = 0; i < 2; i++) + intel_wait_for_vblank(dev); + status = intel_sdvo_get_trained_inputs(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); +} + +static int intel_sdvo_mode_valid(struct drm_output *output, + struct drm_display_mode *mode) +{ + struct intel_output *intel_output = output->driver_private; + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; + + if (mode->flags & V_DBLSCAN) + return MODE_NO_DBLESCAN; + + if (sdvo_priv->pixel_clock_min > mode->clock) + return MODE_CLOCK_HIGH; + + if (sdvo_priv->pixel_clock_max < mode->clock) + return MODE_CLOCK_LOW; + + return MODE_OK; +} + +static bool intel_sdvo_get_capabilities(struct drm_output *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)); + if (status != SDVO_CMD_STATUS_SUCCESS) + return FALSE; + + return TRUE; +} + + +static void intel_sdvo_dump_cmd(struct drm_output *output, int opcode) +{ + + +} + +static void intel_sdvo_dump_device(struct drm_output *output) +{ + +} + +void intel_sdvo_dump(void) +{ + +} + + +static enum drm_output_status intel_sdvo_detect(struct drm_output *output) +{ + u8 response[2]; + u8 status; + + intel_sdvo_write_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0); + status = intel_sdvo_read_response(output, &response, 2); + + if (status != SDVO_CMD_STATUS_SUCCESS) + return output_status_unknown; + + DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]); + if ((response[0] != 0) || (response[1] != 0)) + return output_status_connected; + else + return output_status_disconnected; +} + +static int intel_sdvo_get_modes(struct drm_output *output) +{ + struct drm_display_mode *modes; + + /* set the bus switch and get the modes */ + intel_sdvo_set_control_bus_switch(output, SDVO_CONTROL_BUS_DDC2); + intel_ddc_get_modes(output); + + if (list_empty(&output->probed_modes)) + return 0; + return 1; +#if 0 + /* Mac mini hack. On this device, I get DDC through the analog, which + * load-detects as disconnected. I fail to DDC through the SDVO DDC, + * but it does load-detect as connected. So, just steal the DDC bits + * from analog when we fail at finding it the right way. + */ + /* TODO */ + return NULL; + + return NULL; +#endif +} + +static void intel_sdvo_destroy(struct drm_output *output) +{ + struct intel_output *intel_output = output->driver_private; + + if (intel_output->i2c_bus) + intel_i2c_destroy(intel_output->i2c_bus); + + if (intel_output) { + kfree(intel_output); + output->driver_private = NULL; + } +} + +static const struct drm_output_funcs intel_sdvo_output_funcs = { + .dpms = intel_sdvo_dpms, + .save = intel_sdvo_save, + .restore = intel_sdvo_restore, + .mode_valid = intel_sdvo_mode_valid, + .mode_fixup = intel_sdvo_mode_fixup, + .prepare = intel_output_prepare, + .mode_set = intel_sdvo_mode_set, + .commit = intel_output_commit, + .detect = intel_sdvo_detect, + .get_modes = intel_sdvo_get_modes, + .cleanup = intel_sdvo_destroy +}; + +void intel_sdvo_init(drm_device_t *dev, int output_device) +{ + struct drm_output *output; + struct intel_output *intel_output; + struct intel_sdvo_priv *sdvo_priv; + struct intel_i2c_chan *i2cbus = NULL; + u8 ch[0x40]; + int i; + char name[DRM_OUTPUT_LEN]; + char *name_prefix; + char *name_suffix; + + + output = drm_output_create(dev, &intel_sdvo_output_funcs, NULL); + if (!output) + return; + + intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); + if (!intel_output) { + drm_output_destroy(output); + return; + } + + sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1); + intel_output->type = INTEL_OUTPUT_SDVO; + output->driver_private = intel_output; + output->interlace_allowed = 0; + output->doublescan_allowed = 0; + + /* setup the DDC bus. */ + if (output_device == SDVOB) + i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB"); + else + i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC"); + + if (i2cbus == NULL) { + drm_output_destroy(output); + return; + } + + sdvo_priv->i2c_bus = i2cbus; + + if (output_device == SDVOB) { + name_suffix = "-1"; + sdvo_priv->i2c_bus->slave_addr = 0x38; + } else { + name_suffix = "-2"; + sdvo_priv->i2c_bus->slave_addr = 0x39; + } + + sdvo_priv->output_device = output_device; + intel_output->i2c_bus = i2cbus; + intel_output->dev_priv = sdvo_priv; + + + /* 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])) { + DRM_DEBUG("No SDVO device found on SDVO%c\n", + output_device == SDVOB ? 'B' : 'C'); + drm_output_destroy(output); + return; + } + } + + intel_sdvo_get_capabilities(output, &sdvo_priv->caps); + + memset(&sdvo_priv->active_outputs, 0, sizeof(sdvo_priv->active_outputs)); + + if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) + { + sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0; + output->subpixel_order = SubPixelHorizontalRGB; + name_prefix="TMDS"; + } + else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) + { + sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1; + output->subpixel_order = SubPixelHorizontalRGB; + name_prefix="TMDS"; + } + else + { + unsigned char bytes[2]; + + memcpy (bytes, &sdvo_priv->caps.output_flags, 2); + DRM_DEBUG("%s: No active TMDS outputs (0x%02x%02x)\n", + SDVO_NAME(sdvo_priv), + bytes[0], bytes[1]); + } + strcpy (name, name_prefix); + strcat (name, name_suffix); + if (!drm_output_rename(output, name)) + { + drm_output_destroy(output); + return; + } + + + /* Set the input timing to the screen. Assume always input 0. */ + intel_sdvo_set_target_input(output, TRUE, FALSE); + + intel_sdvo_get_input_pixel_clock_range(output, + &sdvo_priv->pixel_clock_min, + &sdvo_priv->pixel_clock_max); + + + DRM_DEBUG("%s device VID/DID: %02X:%02X.%02X, " + "clock range %dMHz - %dMHz, " + "input 1: %c, input 2: %c, " + "output 1: %c, output 2: %c\n", + SDVO_NAME(sdvo_priv), + sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id, + sdvo_priv->caps.device_rev_id, + sdvo_priv->pixel_clock_min / 1000, + sdvo_priv->pixel_clock_max / 1000, + (sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N', + (sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N', + sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0 ? 'Y' : 'N', + sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1 ? 'Y' : 'N'); + + intel_output->ddc_bus = i2cbus; +} -- cgit v1.2.3 From 1c9ba24c2f37ca78965f8aa57ece02ef5bdb9b06 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 5 Apr 2007 11:34:11 -0700 Subject: Add required permission notices for code copied from X.Org source. --- linux-core/intel_sdvo.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 4094b788..0e870d15 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -1,7 +1,30 @@ +/* + * Copyright © 2006-2007 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Eric Anholt + */ /* * Copyright 2006 Dave Airlie - * Copyright © 2006 Intel Corporation - * Eric Anholt * Jesse Barnes */ -- cgit v1.2.3 From 23a66fd506e71fdfde906d1679fb07c0df8bec4c Mon Sep 17 00:00:00 2001 From: David Airlie Date: Tue, 10 Apr 2007 16:26:07 +1000 Subject: fixup true/false in intel_sdvo.c --- linux-core/intel_sdvo.c | 72 ++++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 34 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 0e870d15..4a954f9e 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -298,7 +298,7 @@ static bool intel_sdvo_get_trained_inputs(struct drm_output *output, bool *input *input_1 = response.input0_trained; *input_2 = response.input1_trained; - return TRUE; + return true; } static bool intel_sdvo_get_active_outputs(struct drm_output *output, @@ -363,13 +363,13 @@ static bool intel_sdvo_get_input_pixel_clock_range(struct drm_output *output, status = intel_sdvo_read_response(output, &clocks, sizeof(clocks)); if (status != SDVO_CMD_STATUS_SUCCESS) - return FALSE; + return false; /* Convert the values from units of 10 kHz to kHz. */ *clock_min = clocks.min * 10; *clock_max = clocks.max * 10; - return TRUE; + return true; } static bool intel_sdvo_set_target_output(struct drm_output *output, @@ -393,15 +393,15 @@ static bool intel_sdvo_get_timing(struct drm_output *output, u8 cmd, status = intel_sdvo_read_response(output, &dtd->part1, sizeof(dtd->part1)); if (status != SDVO_CMD_STATUS_SUCCESS) - return FALSE; + return false; intel_sdvo_write_cmd(output, cmd + 1, NULL, 0); status = intel_sdvo_read_response(output, &dtd->part2, sizeof(dtd->part2)); if (status != SDVO_CMD_STATUS_SUCCESS) - return FALSE; + return false; - return TRUE; + return true; } static bool intel_sdvo_get_input_timing(struct drm_output *output, @@ -426,14 +426,14 @@ static bool intel_sdvo_set_timing(struct drm_output *output, u8 cmd, intel_sdvo_write_cmd(output, cmd, &dtd->part1, sizeof(dtd->part1)); status = intel_sdvo_read_response(output, NULL, 0); if (status != SDVO_CMD_STATUS_SUCCESS) - return FALSE; + return false; intel_sdvo_write_cmd(output, cmd + 1, &dtd->part2, sizeof(dtd->part2)); status = intel_sdvo_read_response(output, NULL, 0); if (status != SDVO_CMD_STATUS_SUCCESS) - return FALSE; + return false; - return TRUE; + return true; } static bool intel_sdvo_set_input_timing(struct drm_output *output, @@ -464,16 +464,16 @@ static bool intel_sdvo_get_preferred_input_timing(struct drm_output *output, status = intel_sdvo_read_response(output, &dtd->part1, sizeof(dtd->part1)); if (status != SDVO_CMD_STATUS_SUCCESS) - return FALSE; + return false; intel_sdvo_write_cmd(output, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2, NULL, 0); status = intel_sdvo_read_response(output, &dtd->part2, sizeof(dtd->part2)); if (status != SDVO_CMD_STATUS_SUCCESS) - return FALSE; + return false; - return TRUE; + return true; } #endif @@ -502,9 +502,9 @@ static bool intel_sdvo_set_clock_rate_mult(struct drm_output *output, u8 val) intel_sdvo_write_cmd(output, SDVO_CMD_SET_CLOCK_RATE_MULT, &val, 1); status = intel_sdvo_read_response(output, NULL, 0); if (status != SDVO_CMD_STATUS_SUCCESS) - return FALSE; + return false; - return TRUE; + return true; } static bool intel_sdvo_mode_fixup(struct drm_output *output, @@ -515,7 +515,7 @@ static bool intel_sdvo_mode_fixup(struct drm_output *output, * device will be told of the multiplier during mode_set. */ adjusted_mode->clock *= intel_sdvo_get_pixel_multiplier(mode); - return TRUE; + return true; } static void intel_sdvo_mode_set(struct drm_output *output, @@ -584,7 +584,7 @@ static void intel_sdvo_mode_set(struct drm_output *output, intel_sdvo_set_output_timing(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(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 @@ -620,16 +620,20 @@ static void intel_sdvo_mode_set(struct drm_output *output, } /* Set the SDVO control regs. */ - sdvox = I915_READ(sdvo_priv->output_device); - switch (sdvo_priv->output_device) { - case SDVOB: - sdvox &= SDVOB_PRESERVE_MASK; - break; - case SDVOC: - sdvox &= SDVOC_PRESERVE_MASK; - break; - } - sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; + if (0/*IS_I965GM(dev)*/) { + sdvox = SDVO_BORDER_ENABLE; + } else { + sdvox = I915_READ(sdvo_priv->output_device); + switch (sdvo_priv->output_device) { + case SDVOB: + sdvox &= SDVOB_PRESERVE_MASK; + break; + case SDVOC: + sdvox &= SDVOC_PRESERVE_MASK; + break; + } + sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; + } if (intel_crtc->pipe == 1) sdvox |= SDVO_PIPE_B_SELECT; @@ -706,13 +710,13 @@ static void intel_sdvo_save(struct drm_output *output) intel_sdvo_get_active_outputs(output, &sdvo_priv->save_active_outputs); if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) { - intel_sdvo_set_target_input(output, TRUE, FALSE); + intel_sdvo_set_target_input(output, true, false); intel_sdvo_get_input_timing(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_target_input(output, false, true); intel_sdvo_get_input_timing(output, &sdvo_priv->save_input_dtd_2); } @@ -754,12 +758,12 @@ static void intel_sdvo_restore(struct drm_output *output) } if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) { - intel_sdvo_set_target_input(output, TRUE, FALSE); + intel_sdvo_set_target_input(output, true, false); intel_sdvo_set_input_timing(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_target_input(output, false, true); intel_sdvo_set_input_timing(output, &sdvo_priv->save_input_dtd_2); } @@ -805,9 +809,9 @@ static bool intel_sdvo_get_capabilities(struct drm_output *output, struct intel_ intel_sdvo_write_cmd(output, SDVO_CMD_GET_DEVICE_CAPS, NULL, 0); status = intel_sdvo_read_response(output, caps, sizeof(*caps)); if (status != SDVO_CMD_STATUS_SUCCESS) - return FALSE; + return false; - return TRUE; + return true; } @@ -980,7 +984,7 @@ void intel_sdvo_init(drm_device_t *dev, int output_device) } else { - unsigned char bytes[2]; + unsigned char bytes[2]; memcpy (bytes, &sdvo_priv->caps.output_flags, 2); DRM_DEBUG("%s: No active TMDS outputs (0x%02x%02x)\n", @@ -997,7 +1001,7 @@ void intel_sdvo_init(drm_device_t *dev, int output_device) /* Set the input timing to the screen. Assume always input 0. */ - intel_sdvo_set_target_input(output, TRUE, FALSE); + intel_sdvo_set_target_input(output, true, false); intel_sdvo_get_input_pixel_clock_range(output, &sdvo_priv->pixel_clock_min, -- cgit v1.2.3 From 50672adb3142abca743535a8e60c360ef47b2a08 Mon Sep 17 00:00:00 2001 From: David Airlie Date: Tue, 10 Apr 2007 16:49:36 +1000 Subject: add sdvo debugging output --- linux-core/intel_sdvo.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 4a954f9e..1b45afdb 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -209,11 +209,30 @@ static void intel_sdvo_write_cmd(struct drm_output *output, u8 cmd, void *args, int args_len) { struct intel_output *intel_output = output->driver_private; + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; int i; + if (1) { + printk("%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd); + for (i = 0; i < args_len; i++) + printk("%02X ", ((u8 *)args)[i]); + for (; i < 8; i++) + printk(" "); + for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) { + if (cmd == sdvo_cmd_names[i].cmd) { + printk("(%s)", sdvo_cmd_names[i].name); + break; + } + } + if (i == sizeof(sdvo_cmd_names)/ sizeof(sdvo_cmd_names[0])) + printk("(%02X)",cmd); + printk("\n"); + } + for (i = 0; i < args_len; i++) { intel_sdvo_write_byte(output, SDVO_I2C_ARG_0 - i, ((u8*)args)[i]); } + intel_sdvo_write_byte(output, SDVO_I2C_OPCODE, cmd); } @@ -230,6 +249,8 @@ static const char *cmd_status_names[] = { static u8 intel_sdvo_read_response(struct drm_output *output, void *response, int response_len) { + struct intel_output *intel_output = output->driver_private; + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; int i; u8 status; @@ -242,6 +263,18 @@ static u8 intel_sdvo_read_response(struct drm_output *output, void *response, /* read the return status */ intel_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, &status); + if (1) { + printk("%s: R: ", SDVO_NAME(sdvo_priv)); + for (i = 0; i < response_len; i++) + printk("%02X ", ((u8 *)response)[i]); + for (; i < 8; i++) + printk(" "); + if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) + printk("(%s)", cmd_status_names[status]); + else + printk("(??? %d)", status); + printk("\n"); + } return status; } -- cgit v1.2.3 From b729b919baed250313caf3f0bbd4044e084de8bf Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 17 Apr 2007 16:11:00 +0100 Subject: Fix a register read that was swapped SDVOB/SDVOC Check for the PENDING message when reading the attached displays. Ensures the command has completed before continuing. (probably need to check PENDING in other SDVO calls too) --- linux-core/intel_sdvo.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 1b45afdb..6f592f8a 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -29,6 +29,7 @@ */ #include +#include #include "drmP.h" #include "drm.h" #include "drm_crtc.h" @@ -69,9 +70,9 @@ static void intel_sdvo_write_sdvox(struct drm_output *output, u32 val) int i; if (sdvo_priv->output_device == SDVOB) - cval = I915_READ(SDVOC); - else bval = I915_READ(SDVOB); + else + cval = I915_READ(SDVOC); /* * Write the registers twice for luck. Sometimes, @@ -869,12 +870,21 @@ static enum drm_output_status intel_sdvo_detect(struct drm_output *output) { u8 response[2]; u8 status; + u8 retry = 50; intel_sdvo_write_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0); - status = intel_sdvo_read_response(output, &response, 2); - if (status != SDVO_CMD_STATUS_SUCCESS) - return output_status_unknown; + while (retry--) { + status = intel_sdvo_read_response(output, &response, 2); + + if (status == SDVO_CMD_STATUS_SUCCESS) + break; + + if (status != SDVO_CMD_STATUS_PENDING) + return output_status_unknown; + + mdelay(50); + } DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]); if ((response[0] != 0) || (response[1] != 0)) -- cgit v1.2.3 From 2352ec9bfab20761cc898ea40db2a7c6d53e81f3 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 18 Apr 2007 10:39:58 +1000 Subject: backout alanh's broken commit --- linux-core/intel_sdvo.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 6f592f8a..5dbfb8eb 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -70,10 +70,9 @@ static void intel_sdvo_write_sdvox(struct drm_output *output, u32 val) int i; if (sdvo_priv->output_device == SDVOB) - bval = I915_READ(SDVOB); - else cval = I915_READ(SDVOC); - + else + bval = I915_READ(SDVOB); /* * Write the registers twice for luck. Sometimes, * writing them only once doesn't appear to 'stick'. -- cgit v1.2.3 From dc03e07f236ea5716d271155dcbbc54a218732c6 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Wed, 18 Apr 2007 11:46:04 +0100 Subject: Move SDVO PENDING check to read_response so all SDVO commands benefit from the spin loop. --- linux-core/intel_sdvo.c | 60 +++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 32 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 6f592f8a..edc27016 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -254,30 +254,38 @@ static u8 intel_sdvo_read_response(struct drm_output *output, void *response, struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; int i; u8 status; + u8 retry = 50; - /* Read the command response */ - for (i = 0; i < response_len; i++) { - intel_sdvo_read_byte(output, SDVO_I2C_RETURN_0 + i, + while (retry--) { + /* Read the command response */ + for (i = 0; i < response_len; i++) { + intel_sdvo_read_byte(output, SDVO_I2C_RETURN_0 + i, &((u8 *)response)[i]); - } + } - /* read the return status */ - intel_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, &status); + /* read the return status */ + intel_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, &status); + + if (1) { + printk("%s: R: ", SDVO_NAME(sdvo_priv)); + for (i = 0; i < response_len; i++) + printk("%02X ", ((u8 *)response)[i]); + for (; i < 8; i++) + printk(" "); + if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) + printk("(%s)", cmd_status_names[status]); + else + printk("(??? %d)", status); + printk("\n"); + } - if (1) { - printk("%s: R: ", SDVO_NAME(sdvo_priv)); - for (i = 0; i < response_len; i++) - printk("%02X ", ((u8 *)response)[i]); - for (; i < 8; i++) - printk(" "); - if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) - printk("(%s)", cmd_status_names[status]); - else - printk("(??? %d)", status); - printk("\n"); - } - return status; + if (status != SDVO_CMD_STATUS_PENDING) + return status; + + mdelay(50); + } + return SDVO_CMD_STATUS_SUCCESS; } int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) @@ -870,21 +878,9 @@ static enum drm_output_status intel_sdvo_detect(struct drm_output *output) { u8 response[2]; u8 status; - u8 retry = 50; intel_sdvo_write_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0); - - while (retry--) { - status = intel_sdvo_read_response(output, &response, 2); - - if (status == SDVO_CMD_STATUS_SUCCESS) - break; - - if (status != SDVO_CMD_STATUS_PENDING) - return output_status_unknown; - - mdelay(50); - } + status = intel_sdvo_read_response(output, &response, 2); DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]); if ((response[0] != 0) || (response[1] != 0)) -- cgit v1.2.3 From ea8bcb466bca82081816ca3d83a420f09a62870c Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Wed, 18 Apr 2007 11:47:21 +0100 Subject: Check status after SDVO command for sdvo_set_control_bus_switch --- linux-core/intel_sdvo.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index edc27016..e7618e11 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -298,9 +298,14 @@ int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) return 4; } -static void intel_sdvo_set_control_bus_switch(struct drm_output *output, u8 target) +static bool intel_sdvo_set_control_bus_switch(struct drm_output *output, u8 target) { + u8 status; + intel_sdvo_write_cmd(output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1); + status = intel_sdvo_read_response(output, NULL, 0); + + return (status == SDVO_CMD_STATUS_SUCCESS); } static bool intel_sdvo_set_target_input(struct drm_output *output, bool target_0, bool target_1) -- cgit v1.2.3 From 51e867c57880c85c87e187af0a667e9b99413206 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Wed, 18 Apr 2007 11:53:25 +0100 Subject: Support the RGB outputs of SDVO cards, which are essentially VGA outs. The drm_initial_config path has specific handling code to name match for VGA, TMDS or LVDS. This is pretty restrictive and should probably be dealt with to be more generic. --- linux-core/intel_sdvo.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index e7618e11..67c3329d 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -1014,7 +1014,28 @@ void intel_sdvo_init(drm_device_t *dev, int output_device) memset(&sdvo_priv->active_outputs, 0, sizeof(sdvo_priv->active_outputs)); - if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) + /* TODO, CVBS, SVID, YPRPB & SCART outputs. + * drm_initial_config probably wants tweaking too to support the + * above. But has fixed VGA, TMDS and LVDS checking code. That should + * be dealt with. + */ + if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0) + { + sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0; + output->subpixel_order = SubPixelHorizontalRGB; + /* drm_initial_config wants this name, but should be RGB */ + /* Use this for now.... */ + name_prefix="VGA"; + } + else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) + { + sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1; + output->subpixel_order = SubPixelHorizontalRGB; + /* drm_initial_config wants this name, but should be RGB */ + /* Use this for now.... */ + name_prefix="VGA"; + } + else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) { sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0; output->subpixel_order = SubPixelHorizontalRGB; @@ -1031,7 +1052,7 @@ void intel_sdvo_init(drm_device_t *dev, int output_device) unsigned char bytes[2]; memcpy (bytes, &sdvo_priv->caps.output_flags, 2); - DRM_DEBUG("%s: No active TMDS outputs (0x%02x%02x)\n", + DRM_DEBUG("%s: No active RGB or TMDS outputs (0x%02x%02x)\n", SDVO_NAME(sdvo_priv), bytes[0], bytes[1]); } @@ -1063,8 +1084,11 @@ void intel_sdvo_init(drm_device_t *dev, int output_device) sdvo_priv->pixel_clock_max / 1000, (sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N', (sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N', - sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0 ? 'Y' : 'N', - sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1 ? 'Y' : 'N'); + /* check currently supported outputs */ + sdvo_priv->caps.output_flags & + (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N', + sdvo_priv->caps.output_flags & + (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); intel_output->ddc_bus = i2cbus; } -- cgit v1.2.3 From b642ced0830d4e91785ba94677abe637c7cb3791 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Wed, 18 Apr 2007 13:52:46 +0100 Subject: Fix return status --- linux-core/intel_sdvo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index c9bc692e..f004c766 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -284,7 +284,7 @@ static u8 intel_sdvo_read_response(struct drm_output *output, void *response, mdelay(50); } - return SDVO_CMD_STATUS_SUCCESS; + return status; } int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) -- cgit v1.2.3 From 8d893e49ec35905a3718c565ec56c21d76dc745c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 19 Apr 2007 09:43:46 +1000 Subject: backout SDVO control bus check and comment why this is a bad idea --- linux-core/intel_sdvo.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index f004c766..507b0f5e 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -297,14 +297,14 @@ int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) return 4; } -static bool intel_sdvo_set_control_bus_switch(struct drm_output *output, u8 target) +/** + * Don't check status code from this as it switches the bus back to the + * 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) { - u8 status; - intel_sdvo_write_cmd(output, SDVO_CMD_SET_CONTROL_BUS_SWITCH, &target, 1); - status = intel_sdvo_read_response(output, NULL, 0); - - return (status == SDVO_CMD_STATUS_SUCCESS); } static bool intel_sdvo_set_target_input(struct drm_output *output, bool target_0, bool target_1) -- cgit v1.2.3 From 6238ebee21f800cec6c77b6bf90d7916ca945931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 20 Apr 2007 16:52:04 -0400 Subject: Clean up and return if no outputs are found. --- linux-core/intel_sdvo.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 507b0f5e..98c4034d 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -1054,6 +1054,8 @@ void intel_sdvo_init(drm_device_t *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]); + drm_output_destroy(output); + return; } strcpy (name, name_prefix); strcat (name, name_suffix); -- cgit v1.2.3 From eba00df1203040905d38bf0ef449d25d6dbdb72c Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Thu, 10 May 2007 13:16:05 +0100 Subject: Just some minor cleanups. --- linux-core/intel_sdvo.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 98c4034d..58aa432c 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -525,7 +525,6 @@ static bool intel_sdvo_get_preferred_input_timing(struct drm_output *output, static int intel_sdvo_get_clock_rate_mult(struct drm_output *output) { - struct intel_output *intel_output = output->driver_private; u8 response, status; intel_sdvo_write_cmd(output, SDVO_CMD_GET_CLOCK_RATE_MULT, NULL, 0); @@ -895,8 +894,6 @@ static enum drm_output_status intel_sdvo_detect(struct drm_output *output) static int intel_sdvo_get_modes(struct drm_output *output) { - struct drm_display_mode *modes; - /* set the bus switch and get the modes */ intel_sdvo_set_control_bus_switch(output, SDVO_CONTROL_BUS_DDC2); intel_ddc_get_modes(output); -- cgit v1.2.3 From 5ce8aaae7251e60c078eda0a21894aae0e1d7a45 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 17 May 2007 12:46:36 +0100 Subject: Large changes for fbdev support. Change from DIRECTCOLOR to TRUECOLOR, and enable support for PSEUDOCOLOR. DIRECTCOLOR support needs more work. Add the ability to change the mode on the fbdev device. Support depth 8, 15, 16 and 24 (and 32). Add a /dev/fbX device per CRTC, but there's some code which doesn't allocate the fbX device unless the output is actually enabled. Read the code on this as it impacts the fbcon map flags. Pick CRTC's based on the available outputs. More work could be done here to match modes, so cloning could be achieved on outputs. This fits more inline with what the X code does. --- linux-core/intel_sdvo.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 58aa432c..c02fd958 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -1010,26 +1010,18 @@ void intel_sdvo_init(drm_device_t *dev, int output_device) memset(&sdvo_priv->active_outputs, 0, sizeof(sdvo_priv->active_outputs)); - /* TODO, CVBS, SVID, YPRPB & SCART outputs. - * drm_initial_config probably wants tweaking too to support the - * above. But has fixed VGA, TMDS and LVDS checking code. That should - * be dealt with. - */ + /* TODO, CVBS, SVID, YPRPB & SCART outputs. */ if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0) { sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0; output->subpixel_order = SubPixelHorizontalRGB; - /* drm_initial_config wants this name, but should be RGB */ - /* Use this for now.... */ - name_prefix="VGA"; + name_prefix="RGB"; } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) { sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1; output->subpixel_order = SubPixelHorizontalRGB; - /* drm_initial_config wants this name, but should be RGB */ - /* Use this for now.... */ - name_prefix="VGA"; + name_prefix="RGB"; } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) { -- cgit v1.2.3 From d42c1de3fb05405820b03ec9bb12f0b9a7eb0a7b Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Fri, 18 May 2007 14:16:27 +0100 Subject: Change some printk's to DRM_DEBUG's --- linux-core/intel_sdvo.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index c02fd958..196298ff 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -213,20 +213,20 @@ static void intel_sdvo_write_cmd(struct drm_output *output, u8 cmd, int i; if (1) { - printk("%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd); + DRM_DEBUG("%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd); for (i = 0; i < args_len; i++) - printk("%02X ", ((u8 *)args)[i]); + DRM_DEBUG("%02X ", ((u8 *)args)[i]); for (; i < 8; i++) - printk(" "); + DRM_DEBUG(" "); for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) { if (cmd == sdvo_cmd_names[i].cmd) { - printk("(%s)", sdvo_cmd_names[i].name); + DRM_DEBUG("(%s)", sdvo_cmd_names[i].name); break; } } if (i == sizeof(sdvo_cmd_names)/ sizeof(sdvo_cmd_names[0])) - printk("(%02X)",cmd); - printk("\n"); + DRM_DEBUG("(%02X)",cmd); + DRM_DEBUG("\n"); } for (i = 0; i < args_len; i++) { @@ -266,16 +266,16 @@ static u8 intel_sdvo_read_response(struct drm_output *output, void *response, intel_sdvo_read_byte(output, SDVO_I2C_CMD_STATUS, &status); if (1) { - printk("%s: R: ", SDVO_NAME(sdvo_priv)); + DRM_DEBUG("%s: R: ", SDVO_NAME(sdvo_priv)); for (i = 0; i < response_len; i++) - printk("%02X ", ((u8 *)response)[i]); + DRM_DEBUG("%02X ", ((u8 *)response)[i]); for (; i < 8; i++) - printk(" "); + DRM_DEBUG(" "); if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) - printk("(%s)", cmd_status_names[status]); + DRM_DEBUG("(%s)", cmd_status_names[status]); else - printk("(??? %d)", status); - printk("\n"); + DRM_DEBUG("(??? %d)", status); + DRM_DEBUG("\n"); } if (status != SDVO_CMD_STATUS_PENDING) -- cgit v1.2.3 From cbcbe80c09bd95485ce8a9b0d86242fedcd7c182 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Mon, 24 Sep 2007 15:43:00 -0700 Subject: Cleanup SDVO debug output SDVO debug messages were incorrectly including severity prefixes in each print rather than each unique line. Fix it up. --- linux-core/intel_sdvo.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 11f3a0a6..19df1d4d 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -215,18 +215,18 @@ static void intel_sdvo_write_cmd(struct drm_output *output, u8 cmd, if (1) { DRM_DEBUG("%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd); for (i = 0; i < args_len; i++) - DRM_DEBUG("%02X ", ((u8 *)args)[i]); + printk("%02X ", ((u8 *)args)[i]); for (; i < 8; i++) - DRM_DEBUG(" "); + printk(" "); for (i = 0; i < sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); i++) { if (cmd == sdvo_cmd_names[i].cmd) { - DRM_DEBUG("(%s)", sdvo_cmd_names[i].name); + printk("(%s)", sdvo_cmd_names[i].name); break; } } if (i == sizeof(sdvo_cmd_names)/ sizeof(sdvo_cmd_names[0])) - DRM_DEBUG("(%02X)",cmd); - DRM_DEBUG("\n"); + printk("(%02X)",cmd); + printk("\n"); } for (i = 0; i < args_len; i++) { @@ -268,14 +268,14 @@ static u8 intel_sdvo_read_response(struct drm_output *output, void *response, if (1) { DRM_DEBUG("%s: R: ", SDVO_NAME(sdvo_priv)); for (i = 0; i < response_len; i++) - DRM_DEBUG("%02X ", ((u8 *)response)[i]); + printk("%02X ", ((u8 *)response)[i]); for (; i < 8; i++) - DRM_DEBUG(" "); + printk(" "); if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) - DRM_DEBUG("(%s)", cmd_status_names[status]); + printk("(%s)", cmd_status_names[status]); else - DRM_DEBUG("(??? %d)", status); - DRM_DEBUG("\n"); + printk("(??? %d)", status); + printk("\n"); } if (status != SDVO_CMD_STATUS_PENDING) -- cgit v1.2.3 From 2ed12b6b7eee8a1b5b0adf0cd8f3cb8c1bc3ccaf Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Thu, 27 Sep 2007 14:21:03 +0100 Subject: Add some more checks to modelist walking for matching incoming modes to current modelist. --- linux-core/intel_sdvo.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 19df1d4d..51fe43cb 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -730,9 +730,12 @@ static void intel_sdvo_dpms(struct drm_output *output, int mode) &input2); - /* Warn if the device reported failure to sync. */ + /* Warn if the device reported failure to sync. + * A lot of SDVO devices fail to notify of sync, but it's + * a given it the status is a success, we succeeded. + */ if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { - DRM_ERROR("First %s output reported failure to sync\n", + DRM_DEBUG("First %s output reported failure to sync\n", SDVO_NAME(sdvo_priv)); } @@ -839,10 +842,10 @@ static int intel_sdvo_mode_valid(struct drm_output *output, return MODE_NO_DBLESCAN; if (sdvo_priv->pixel_clock_min > mode->clock) - return MODE_CLOCK_HIGH; + return MODE_CLOCK_LOW; if (sdvo_priv->pixel_clock_max < mode->clock) - return MODE_CLOCK_LOW; + return MODE_CLOCK_HIGH; return MODE_OK; } -- cgit v1.2.3 From f99dea7db00dd46aa96eaed3a61dff9c956fd86f Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 11 Dec 2007 15:56:48 +1000 Subject: modesetting: fixup property setting and add connector property --- linux-core/intel_sdvo.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 51fe43cb..0da57faa 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -950,6 +950,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) 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; char name[DRM_OUTPUT_LEN]; @@ -1019,24 +1020,28 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0; output->subpixel_order = SubPixelHorizontalRGB; name_prefix="RGB"; + connector_type = ConnectorVGA; } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) { sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1; output->subpixel_order = SubPixelHorizontalRGB; name_prefix="RGB"; + connector_type = ConnectorVGA; } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) { sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0; output->subpixel_order = SubPixelHorizontalRGB; name_prefix="TMDS"; + connector_type = ConnectorDVID; } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) { sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1; output->subpixel_order = SubPixelHorizontalRGB; name_prefix="TMDS"; + connector_type = ConnectorDVID; } else { @@ -1084,4 +1089,6 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); intel_output->ddc_bus = i2cbus; + + drm_output_attach_property(output, dev->mode_config.connector_type_property, connector_type); } -- cgit v1.2.3 From e239882b1e90cba0297118ec7dc432bea06b0bd0 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Tue, 4 Dec 2007 15:36:36 +0100 Subject: Modesetting Hotplug --- linux-core/intel_sdvo.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 4 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 0da57faa..d2d00e2a 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -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,72 @@ 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) + continue; + + sdvo = iout->dev_priv; + + if (sdvo->output_device == SDVOB && sdvoB) + return output; + + if (sdvo->output_device == SDVOC && !sdvoB) + return output; + + } + + return 0; +} + +int intel_sdvo_supports_hotplug(struct drm_output *output) +{ + u8 response[2]; + u8 status; + DRM_DEBUG("\n"); + + if (!output) + return 0; + + 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; + + intel_sdvo_write_cmd(output, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0); + intel_sdvo_read_response(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(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(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) { -- cgit v1.2.3 From bdbc34e297bd7e4cb036df6244dfb0d816eed36d Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Tue, 18 Dec 2007 02:09:48 +0100 Subject: Fix and cleanup of Hotplug --- linux-core/intel_sdvo.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index d2d00e2a..1d7d0b7d 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -53,6 +53,7 @@ struct intel_sdvo_priv { struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2; struct intel_sdvo_dtd save_output_dtd[16]; u32 save_SDVOX; + int hotplug_enabled; }; /** @@ -71,9 +72,14 @@ void intel_sdvo_write_sdvox(struct drm_output *output, u32 val) if (sdvo_priv->output_device == SDVOB) { cval = I915_READ(SDVOC); - bval = bval | (1 << 26); + + if (sdvo_priv->hotplug_enabled) + bval = bval | (1 << 26); } else { - bval = I915_READ(SDVOB) | (1 << 26); + bval = I915_READ(SDVOB); + + if (sdvo_priv->hotplug_enabled) + cval = cval | (1 << 26); } /* * Write the registers twice for luck. Sometimes, @@ -927,6 +933,8 @@ int intel_sdvo_supports_hotplug(struct drm_output *output) void intel_sdvo_set_hotplug(struct drm_output *output, int on) { + struct intel_output *intel_output = output->driver_private; + struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; u8 response[2]; u8 status; @@ -934,11 +942,15 @@ void intel_sdvo_set_hotplug(struct drm_output *output, int on) intel_sdvo_read_response(output, &response, 2); if (on) { + sdvo_priv->hotplug_enabled = 1; + 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 { + sdvo_priv->hotplug_enabled = 0; + response[0] = 0; response[1] = 0; intel_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2); @@ -1064,6 +1076,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) } sdvo_priv->output_device = output_device; + sdvo_priv->hotplug_enabled = 0; intel_output->i2c_bus = i2cbus; intel_output->dev_priv = sdvo_priv; -- cgit v1.2.3 From b13dc383df85d75cb1ea422f4d13efc2a4a8a732 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 18 Dec 2007 17:41:20 +1100 Subject: remove output names --- linux-core/intel_sdvo.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 0da57faa..7f55829b 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -953,12 +953,10 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) int connector_type; u8 ch[0x40]; int i; - char name[DRM_OUTPUT_LEN]; - char *name_prefix; - char *name_suffix; - + int output_type, output_id; - output = drm_output_create(dev, &intel_sdvo_output_funcs, NULL); + output = drm_output_create(dev, &intel_sdvo_output_funcs, + DRM_MODE_OUTPUT_NONE); if (!output) return; @@ -988,10 +986,10 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) sdvo_priv->i2c_bus = i2cbus; if (output_device == SDVOB) { - name_suffix = "-1"; + output_id = 1; sdvo_priv->i2c_bus->slave_addr = 0x38; } else { - name_suffix = "-2"; + output_id = 2; sdvo_priv->i2c_bus->slave_addr = 0x39; } @@ -1019,28 +1017,28 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) { sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0; output->subpixel_order = SubPixelHorizontalRGB; - name_prefix="RGB"; + output_type = DRM_MODE_OUTPUT_DAC; connector_type = ConnectorVGA; } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) { sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1; output->subpixel_order = SubPixelHorizontalRGB; - name_prefix="RGB"; + output_type = DRM_MODE_OUTPUT_DAC; connector_type = ConnectorVGA; } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) { sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0; output->subpixel_order = SubPixelHorizontalRGB; - name_prefix="TMDS"; + output_type = DRM_MODE_OUTPUT_TMDS; connector_type = ConnectorDVID; } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) { sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1; output->subpixel_order = SubPixelHorizontalRGB; - name_prefix="TMDS"; + output_type = DRM_MODE_OUTPUT_TMDS; connector_type = ConnectorDVID; } else @@ -1054,14 +1052,9 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) drm_output_destroy(output); return; } - strcpy (name, name_prefix); - strcat (name, name_suffix); - if (!drm_output_rename(output, name)) - { - drm_output_destroy(output); - return; - } - + + output->output_type = output_type; + output->output_type_id = output_id; /* Set the input timing to the screen. Assume always input 0. */ intel_sdvo_set_target_input(output, true, false); -- cgit v1.2.3 From 903d9231d6f998657cc80ee6f20ded4df68e691b Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 11 Mar 2008 20:29:37 +0000 Subject: Add support for monitor hotplug signals/waits Also adjust i915 irq handling as it follows the 16bit'ism's of the i8xx series. --- linux-core/intel_sdvo.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 3887df00..a8441d8f 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -53,7 +53,6 @@ struct intel_sdvo_priv { struct intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2; struct intel_sdvo_dtd save_output_dtd[16]; u32 save_SDVOX; - int hotplug_enabled; }; /** @@ -72,14 +71,8 @@ void intel_sdvo_write_sdvox(struct drm_output *output, u32 val) if (sdvo_priv->output_device == SDVOB) { cval = I915_READ(SDVOC); - - if (sdvo_priv->hotplug_enabled) - bval = bval | (1 << 26); } else { bval = I915_READ(SDVOB); - - if (sdvo_priv->hotplug_enabled) - cval = cval | (1 << 26); } /* * Write the registers twice for luck. Sometimes, @@ -933,8 +926,6 @@ int intel_sdvo_supports_hotplug(struct drm_output *output) void intel_sdvo_set_hotplug(struct drm_output *output, int on) { - struct intel_output *intel_output = output->driver_private; - struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; u8 response[2]; u8 status; @@ -942,15 +933,11 @@ void intel_sdvo_set_hotplug(struct drm_output *output, int on) intel_sdvo_read_response(output, &response, 2); if (on) { - sdvo_priv->hotplug_enabled = 1; - 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 { - sdvo_priv->hotplug_enabled = 0; - response[0] = 0; response[1] = 0; intel_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2); @@ -1074,7 +1061,6 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) } sdvo_priv->output_device = output_device; - sdvo_priv->hotplug_enabled = 0; intel_output->i2c_bus = i2cbus; intel_output->dev_priv = sdvo_priv; -- cgit v1.2.3 From fa116081a919e716eb95fcfa421d93f10f6f0a4f Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Wed, 9 Apr 2008 11:30:15 -0700 Subject: Fixup sysfs output registration Put off registering new outputs with sysfs until they're properly configured, or we may get duplicates if the type hasn't been set yet (as is the case with SDVO initialization). This also means moving de-registration into the cleanup function instead of output destroy, since the latter occurs during the normal course of setup when an output isn't found (and therefore not registered with sysfs yet. --- linux-core/intel_sdvo.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index a8441d8f..4fb3f21c 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -1123,6 +1123,8 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) output->output_type = output_type; output->output_type_id = output_id; + drm_sysfs_output_add(output); + /* Set the input timing to the screen. Assume always input 0. */ intel_sdvo_set_target_input(output, true, false); -- cgit v1.2.3 From 0a6e301e6de3421f116d1b5d8205ca4f442091e2 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 10 Apr 2008 11:23:55 -0700 Subject: Keep display info in struct display_info Some fields had snuck into the drm_output structure. Put them back and fill in more stuff from the EDID block. --- linux-core/intel_sdvo.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 4fb3f21c..c9e65af4 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -1083,28 +1083,28 @@ 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->subpixel_order = SubPixelHorizontalRGB; + output->display_info.subpixel_order = SubPixelHorizontalRGB; output_type = DRM_MODE_OUTPUT_DAC; connector_type = ConnectorVGA; } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) { sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1; - output->subpixel_order = SubPixelHorizontalRGB; + output->display_info.subpixel_order = SubPixelHorizontalRGB; output_type = DRM_MODE_OUTPUT_DAC; connector_type = ConnectorVGA; } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) { sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0; - output->subpixel_order = SubPixelHorizontalRGB; + output->display_info.subpixel_order = SubPixelHorizontalRGB; output_type = DRM_MODE_OUTPUT_TMDS; connector_type = ConnectorDVID; } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) { sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1; - output->subpixel_order = SubPixelHorizontalRGB; + output->display_info.subpixel_order = SubPixelHorizontalRGB; output_type = DRM_MODE_OUTPUT_TMDS; connector_type = ConnectorDVID; } -- cgit v1.2.3 From bee546ad696e3157b878dfa90e563786b5b5c7ac Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 10 Apr 2008 19:02:53 -0700 Subject: Remove structure fields & code Cleanup some random cruft left over from the initial port. --- linux-core/intel_sdvo.c | 25 ------------------------- 1 file changed, 25 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index c9e65af4..ba6fe9a8 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -126,14 +126,6 @@ static bool intel_sdvo_read_byte(struct drm_output *output, u8 addr, return false; } - -static bool intel_sdvo_read_byte_quiet(struct drm_output *output, int addr, - u8 *ch) -{ - return true; - -} - static bool intel_sdvo_write_byte(struct drm_output *output, int addr, u8 ch) { @@ -863,23 +855,6 @@ static bool intel_sdvo_get_capabilities(struct drm_output *output, struct intel_ return true; } - -static void intel_sdvo_dump_cmd(struct drm_output *output, int opcode) -{ - - -} - -static void intel_sdvo_dump_device(struct drm_output *output) -{ - -} - -void intel_sdvo_dump(void) -{ - -} - struct drm_output* intel_sdvo_find(struct drm_device *dev, int sdvoB) { struct drm_output *output = 0; -- cgit v1.2.3 From df8cd54286fbae5903d8ede390ec4a11cb6c4b6c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 29 May 2008 14:02:14 +1000 Subject: modesetting: reorganise code into core and helper functions. This splits a lot of the core modesetting code out into a file of helper functions, that are only called from themselves and/or the driver. The driver gets called into more often or can call these functions from itself if it is a helper using driver. I've broken framebuffer resize doing this but I didn't like the API for that in any case. --- linux-core/intel_sdvo.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index ba6fe9a8..41da034d 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -972,18 +972,21 @@ static void intel_sdvo_destroy(struct drm_output *output) } } -static const struct drm_output_funcs intel_sdvo_output_funcs = { - .dpms = intel_sdvo_dpms, - .save = intel_sdvo_save, - .restore = intel_sdvo_restore, - .mode_valid = intel_sdvo_mode_valid, +static const struct drm_output_helper_funcs intel_sdvo_helper_funcs = { .mode_fixup = intel_sdvo_mode_fixup, .prepare = intel_output_prepare, .mode_set = intel_sdvo_mode_set, .commit = intel_output_commit, +}; + +static const struct drm_output_funcs intel_sdvo_output_funcs = { + .dpms = intel_sdvo_dpms, + .save = intel_sdvo_save, + .restore = intel_sdvo_restore, .detect = intel_sdvo_detect, .get_modes = intel_sdvo_get_modes, - .cleanup = intel_sdvo_destroy + .cleanup = intel_sdvo_destroy, + .mode_valid = intel_sdvo_mode_valid, }; void intel_sdvo_init(struct drm_device *dev, int output_device) @@ -1010,6 +1013,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) 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->driver_private = intel_output; output->interlace_allowed = 0; output->doublescan_allowed = 0; -- cgit v1.2.3 From 98c5cf7f6fc51f1a8f5f90b3895009cd38dd8f22 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 May 2008 11:25:41 +1000 Subject: modesetting: reorganise out crtc/outputs are allocated. Use subclassing from the drivers to allocate the objects. This saves two objects being allocated for each crtc/output and generally makes exit paths cleaner. --- linux-core/intel_sdvo.c | 54 +++++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 29 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 41da034d..f4b1c6ef 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -64,7 +64,7 @@ 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; - struct intel_output *intel_output = output->driver_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; @@ -91,7 +91,7 @@ void intel_sdvo_write_sdvox(struct drm_output *output, u32 val) static bool intel_sdvo_read_byte(struct drm_output *output, u8 addr, u8 *ch) { - struct intel_output *intel_output = output->driver_private; + 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]; @@ -129,7 +129,7 @@ static bool intel_sdvo_read_byte(struct drm_output *output, u8 addr, static bool intel_sdvo_write_byte(struct drm_output *output, int addr, u8 ch) { - struct intel_output *intel_output = output->driver_private; + struct intel_output *intel_output = to_intel_output(output); u8 out_buf[2]; struct i2c_msg msgs[] = { { @@ -201,7 +201,7 @@ const static struct _sdvo_cmd_name { static void intel_sdvo_write_cmd(struct drm_output *output, u8 cmd, void *args, int args_len) { - struct intel_output *intel_output = output->driver_private; + struct intel_output *intel_output = to_intel_output(output); struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; int i; @@ -242,7 +242,7 @@ static const char *cmd_status_names[] = { static u8 intel_sdvo_read_response(struct drm_output *output, void *response, int response_len) { - struct intel_output *intel_output = output->driver_private; + struct intel_output *intel_output = to_intel_output(output); struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; int i; u8 status; @@ -493,7 +493,7 @@ static bool intel_sdvo_set_output_timing(struct drm_output *output, static bool intel_sdvo_get_preferred_input_timing(struct drm_output *output, struct intel_sdvo_dtd *dtd) { - struct intel_output *intel_output = output->driver_private; + struct intel_output *intel_output = to_intel_output(output); struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; u8 status; @@ -563,8 +563,8 @@ static void intel_sdvo_mode_set(struct drm_output *output, struct drm_device *dev = output->dev; struct drm_i915_private *dev_priv = dev->dev_private; struct drm_crtc *crtc = output->crtc; - struct intel_crtc *intel_crtc = crtc->driver_private; - struct intel_output *intel_output = output->driver_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct intel_output *intel_output = to_intel_output(output); 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; @@ -693,7 +693,7 @@ static void intel_sdvo_dpms(struct drm_output *output, int mode) { struct drm_device *dev = output->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_output *intel_output = output->driver_private; + struct intel_output *intel_output = to_intel_output(output); struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; u32 temp; @@ -743,7 +743,7 @@ static void intel_sdvo_save(struct drm_output *output) { struct drm_device *dev = output->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_output *intel_output = output->driver_private; + struct intel_output *intel_output = to_intel_output(output); struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; int o; @@ -780,7 +780,7 @@ static void intel_sdvo_restore(struct drm_output *output) { struct drm_device *dev = output->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_output *intel_output = output->driver_private; + struct intel_output *intel_output = to_intel_output(output); struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; int o; int i; @@ -828,7 +828,7 @@ static void intel_sdvo_restore(struct drm_output *output) static int intel_sdvo_mode_valid(struct drm_output *output, struct drm_display_mode *mode) { - struct intel_output *intel_output = output->driver_private; + struct intel_output *intel_output = to_intel_output(output); struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; if (mode->flags & V_DBLSCAN) @@ -863,7 +863,7 @@ struct drm_output* intel_sdvo_find(struct drm_device *dev, int sdvoB) /* find the sdvo output */ list_for_each_entry(output, &dev->mode_config.output_list, head) { - iout = output->driver_private; + iout = to_intel_output(output); if (iout->type != INTEL_OUTPUT_SDVO) continue; @@ -961,15 +961,13 @@ static int intel_sdvo_get_modes(struct drm_output *output) static void intel_sdvo_destroy(struct drm_output *output) { - struct intel_output *intel_output = output->driver_private; + struct intel_output *intel_output = to_intel_output(output); if (intel_output->i2c_bus) intel_i2c_destroy(intel_output->i2c_bus); - if (intel_output) { - kfree(intel_output); - output->driver_private = NULL; - } + drm_output_cleanup(output); + kfree(intel_output); } static const struct drm_output_helper_funcs intel_sdvo_helper_funcs = { @@ -985,7 +983,7 @@ static const struct drm_output_funcs intel_sdvo_output_funcs = { .restore = intel_sdvo_restore, .detect = intel_sdvo_detect, .get_modes = intel_sdvo_get_modes, - .cleanup = intel_sdvo_destroy, + .destroy = intel_sdvo_destroy, .mode_valid = intel_sdvo_mode_valid, }; @@ -1000,21 +998,19 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) int i; int output_type, output_id; - output = drm_output_create(dev, &intel_sdvo_output_funcs, - DRM_MODE_OUTPUT_NONE); - if (!output) - return; - intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); if (!intel_output) { - drm_output_destroy(output); return; } + output = &intel_output->base; + + drm_output_init(dev, output, &intel_sdvo_output_funcs, + DRM_MODE_OUTPUT_NONE); + 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->driver_private = intel_output; output->interlace_allowed = 0; output->doublescan_allowed = 0; @@ -1025,7 +1021,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) { - drm_output_destroy(output); + intel_sdvo_destroy(output); return; } @@ -1049,7 +1045,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) if (!intel_sdvo_read_byte(output, i, &ch[i])) { DRM_DEBUG("No SDVO device found on SDVO%c\n", output_device == SDVOB ? 'B' : 'C'); - drm_output_destroy(output); + intel_sdvo_destroy(output); return; } } @@ -1095,7 +1091,7 @@ 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]); - drm_output_destroy(output); + intel_sdvo_destroy(output); return; } -- cgit v1.2.3 From 6aeef92c0cad784a5019ea90d97ab81f4e51fdd9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 May 2008 13:57:27 +1000 Subject: drm: attach an encoder. Time to do some renaming on the connectors I think --- linux-core/intel_sdvo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index f4b1c6ef..2b232e9a 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -1059,14 +1059,14 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) { sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0; output->display_info.subpixel_order = SubPixelHorizontalRGB; - output_type = DRM_MODE_OUTPUT_DAC; + output_type = DRM_MODE_OUTPUT_VGA; connector_type = ConnectorVGA; } 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; + output_type = DRM_MODE_OUTPUT_VGA; connector_type = ConnectorVGA; } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) -- cgit v1.2.3 From 9d38448ed33aaff324cc4bbe1e0878593e97d07d Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 30 May 2008 15:03:12 +1000 Subject: modesetting: the great renaming. Okay we have crtc, encoder and connectors. No more outputs exposed beyond driver internals I've broken intel tv connector stuff. Really for TV we should have one TV connector, with a sub property for the type of signal been driven over it --- linux-core/intel_sdvo.c | 399 +++++++++++++++++++++++++----------------------- 1 file changed, 205 insertions(+), 194 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 2b232e9a..85bee96b 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -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_connector *connector, 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_connector *connector, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - struct drm_device *dev = output->dev; + struct drm_device *dev = connector->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_crtc *crtc = output->crtc; + struct drm_crtc *crtc = connector->crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - 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; 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(connector, 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(connector, &input_dtd); + intel_sdvo_set_input_timing(connector, &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_connector *connector, int mode) { - 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; 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) { + struct intel_output *intel_output = to_intel_output(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); + intel_sdvo_set_control_bus_switch(intel_output, SDVO_CONTROL_BUS_DDC2); + intel_ddc_get_modes(intel_output); - if (list_empty(&output->probed_modes)) + if (list_empty(&connector->probed_modes)) return 0; return 1; #if 0 @@ -959,25 +960,25 @@ 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_connector_helper_funcs intel_sdvo_helper_funcs = { .mode_fixup = intel_sdvo_mode_fixup, - .prepare = intel_output_prepare, + .prepare = intel_connector_prepare, .mode_set = intel_sdvo_mode_set, - .commit = intel_output_commit, + .commit = intel_connector_commit, }; -static const struct drm_output_funcs intel_sdvo_output_funcs = { +static const struct drm_connector_funcs intel_sdvo_connector_funcs = { .dpms = intel_sdvo_dpms, .save = intel_sdvo_save, .restore = intel_sdvo_restore, @@ -987,32 +988,43 @@ static const struct drm_output_funcs intel_sdvo_output_funcs = { .mode_valid = intel_sdvo_mode_valid, }; + +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; + connector = &intel_output->base; - drm_output_init(dev, output, &intel_sdvo_output_funcs, - DRM_MODE_OUTPUT_NONE); + drm_connector_init(dev, connector, &intel_sdvo_connector_funcs, + DRM_MODE_CONNECTOR_Unknown); 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; + drm_connector_helper_add(connector, &intel_sdvo_helper_funcs); + connector->interlace_allowed = 0; + connector->doublescan_allowed = 0; /* setup the DDC bus. */ if (output_device == SDVOB) @@ -1021,7 +1033,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 +1054,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 +1070,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_VGA; - 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_VGA; - 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 +1103,19 @@ 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); + connector->connector_type = connector_type; - drm_sysfs_output_add(output); + 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 +1139,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); } -- cgit v1.2.3 From e439e74776b215d70d8e34e8aa9cea22179dcbc6 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Jun 2008 10:05:54 +1000 Subject: drm/modesetting: another re-org of some internals. Move dpms into the helper functions. Move crtc into the encoder. Move disable unused functions into the helper. --- linux-core/intel_sdvo.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 85bee96b..498ad989 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -539,7 +539,7 @@ static bool intel_sdvo_set_clock_rate_mult(struct intel_output *intel_output, u8 return true; } -static bool intel_sdvo_mode_fixup(struct drm_connector *connector, +static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { @@ -550,15 +550,15 @@ static bool intel_sdvo_mode_fixup(struct drm_connector *connector, return true; } -static void intel_sdvo_mode_set(struct drm_connector *connector, +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 = connector->dev; + struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct drm_crtc *crtc = connector->crtc; + struct drm_crtc *crtc = encoder->crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - struct intel_output *intel_output = to_intel_output(connector); + 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; @@ -624,13 +624,13 @@ static void intel_sdvo_mode_set(struct drm_connector *connector, * output the preferred timing, and we don't support that currently. */ #if 0 - success = intel_sdvo_create_preferred_input_timing(connector, 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(connector, &input_dtd); - intel_sdvo_set_input_timing(connector, &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(intel_output, &output_dtd); @@ -683,11 +683,11 @@ static void intel_sdvo_mode_set(struct drm_connector *connector, intel_sdvo_write_sdvox(intel_output, sdvox); } -static void intel_sdvo_dpms(struct drm_connector *connector, int mode) +static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode) { - struct drm_device *dev = connector->dev; + struct drm_device *dev = encoder->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_output *intel_output = to_intel_output(connector); + struct intel_output *intel_output = enc_to_intel_output(encoder); struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; u32 temp; @@ -971,15 +971,15 @@ static void intel_sdvo_destroy(struct drm_connector *connector) kfree(intel_output); } -static const struct drm_connector_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_connector_prepare, + .prepare = intel_encoder_prepare, .mode_set = intel_sdvo_mode_set, - .commit = intel_connector_commit, + .commit = intel_encoder_commit, }; static const struct drm_connector_funcs intel_sdvo_connector_funcs = { - .dpms = intel_sdvo_dpms, .save = intel_sdvo_save, .restore = intel_sdvo_restore, .detect = intel_sdvo_detect, @@ -1022,7 +1022,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1); intel_output->type = INTEL_OUTPUT_SDVO; - drm_connector_helper_add(connector, &intel_sdvo_helper_funcs); + connector->interlace_allowed = 0; connector->doublescan_allowed = 0; @@ -1108,6 +1108,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) } 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_connector_add(connector); -- cgit v1.2.3 From 0dd000b578adec6ff101c957bce7dc9a32b76713 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Jun 2008 11:12:28 +1000 Subject: drm/modesetting: move some connector functions to helper. Migrated the output mode collection into the helper. --- linux-core/intel_sdvo.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 498ad989..d3ca2a20 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -983,11 +983,14 @@ 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, +}; void intel_sdvo_enc_destroy(struct drm_encoder *encoder) { @@ -1019,7 +1022,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) 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; -- cgit v1.2.3 From 46c78a2223802b9105a87b7125fd4872ab69c4ca Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 2 Jun 2008 11:44:35 +1000 Subject: drm/modesetting: add best encoder finding for modesetting This asks the driver to suggest the best encoder for the connector during the pick crtcs stage. Need to also do this during mode setting stages --- linux-core/intel_sdvo.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index d3ca2a20..9ae0d567 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -990,6 +990,7 @@ static const struct drm_connector_funcs intel_sdvo_connector_funcs = { 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) @@ -1114,6 +1115,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs); connector->connector_type = connector_type; + 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. */ -- cgit v1.2.3 From 58aca7485a4cd9fcccc6e4044325048abcc2f9c7 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 4 Jun 2008 13:03:23 +1000 Subject: drm: remove sysfs in driver for now.. should probably be in helper --- linux-core/intel_sdvo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 9ae0d567..ef67ef9b 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -966,7 +966,7 @@ static void intel_sdvo_destroy(struct drm_connector *connector) if (intel_output->i2c_bus) intel_i2c_destroy(intel_output->i2c_bus); - + drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); kfree(intel_output); } -- cgit v1.2.3 From 03bf1fba67413f381d2a548fe08bd634a48fcc48 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 5 Jun 2008 15:58:43 -0700 Subject: sysfs registration/teardown fixups A check in drm_sysfs_connector_remove was supposed to allow it to be called even with unregistered objects, to make cleanup paths a little simpler. However, device_is_regsitered didn't always seem to return what we thought it would, so we'd sometimes end up leaving objects lying around rather than unregistering them. Fix this situation up by requiring devices to be registered before being removed. Any problems resulting from this change should be easier to track down than the alternative (which is leaving kobjects registered after unload). --- linux-core/intel_sdvo.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index ef67ef9b..f0a47e2e 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -1036,10 +1036,8 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) else i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC"); - if (i2cbus == NULL) { - intel_sdvo_destroy(connector); - return; - } + if (!i2cbus) + goto err_connector; sdvo_priv->i2c_bus = i2cbus; @@ -1061,8 +1059,7 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) 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(connector); - return; + goto err_i2c; } } @@ -1107,8 +1104,7 @@ 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(connector); - return; + goto err_i2c; } drm_encoder_init(dev, &intel_output->enc, &intel_sdvo_enc_funcs, encoder_type); @@ -1143,6 +1139,15 @@ void intel_sdvo_init(struct drm_device *dev, int output_device) sdvo_priv->caps.output_flags & (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); - intel_output->ddc_bus = i2cbus; + intel_output->ddc_bus = i2cbus; + + return; +err_i2c: + intel_i2c_destroy(intel_output->i2c_bus); +err_connector: + drm_connector_cleanup(connector); + kfree(intel_output); + + return; } -- cgit v1.2.3 From e810cb9243fe6c4905182869d9e3272d861a14cb Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Sun, 6 Jul 2008 10:52:25 +0200 Subject: modesetting-101: rename modeflags, as to avoid conflicts with the xorg definitions --- linux-core/intel_sdvo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index f0a47e2e..2143bdc0 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -602,9 +602,9 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, ((v_sync_len & 0x30) >> 4); output_dtd.part2.dtd_flags = 0x18; - if (mode->flags & V_PHSYNC) + if (mode->flags & DRM_MODE_FLAG_PHSYNC) output_dtd.part2.dtd_flags |= 0x2; - if (mode->flags & V_PVSYNC) + if (mode->flags & DRM_MODE_FLAG_PVSYNC) output_dtd.part2.dtd_flags |= 0x4; output_dtd.part2.sdvo_flags = 0; @@ -825,7 +825,7 @@ static int intel_sdvo_mode_valid(struct drm_connector *connector, struct intel_output *intel_output = to_intel_output(connector); struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; - if (mode->flags & V_DBLSCAN) + if (mode->flags & DRM_MODE_FLAG_DBLSCAN) return MODE_NO_DBLESCAN; if (sdvo_priv->pixel_clock_min > mode->clock) -- cgit v1.2.3 From 6738e7b00bf05529303ed690873495db6d83337c Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Sun, 6 Jul 2008 11:08:49 +0200 Subject: modesetting-101: Rename DPMS modes to avoid compatibility issues with xorg definitions. --- linux-core/intel_sdvo.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'linux-core/intel_sdvo.c') diff --git a/linux-core/intel_sdvo.c b/linux-core/intel_sdvo.c index 2143bdc0..6624bde2 100644 --- a/linux-core/intel_sdvo.c +++ b/linux-core/intel_sdvo.c @@ -363,16 +363,16 @@ static bool intel_sdvo_set_encoder_power_state(struct intel_output *intel_output u8 status, state = SDVO_ENCODER_STATE_ON; switch (mode) { - case DPMSModeOn: + case DRM_MODE_DPMS_ON: state = SDVO_ENCODER_STATE_ON; break; - case DPMSModeStandby: + case DRM_MODE_DPMS_STANDBY: state = SDVO_ENCODER_STATE_STANDBY; break; - case DPMSModeSuspend: + case DRM_MODE_DPMS_SUSPEND: state = SDVO_ENCODER_STATE_SUSPEND; break; - case DPMSModeOff: + case DRM_MODE_DPMS_OFF: state = SDVO_ENCODER_STATE_OFF; break; } @@ -691,12 +691,12 @@ static void intel_sdvo_dpms(struct drm_encoder *encoder, int mode) struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; u32 temp; - if (mode != DPMSModeOn) { + if (mode != DRM_MODE_DPMS_ON) { intel_sdvo_set_active_outputs(intel_output, 0); if (0) intel_sdvo_set_encoder_power_state(intel_output, mode); - if (mode == DPMSModeOff) { + if (mode == DRM_MODE_DPMS_OFF) { temp = I915_READ(sdvo_priv->output_device); if ((temp & SDVO_ENABLE) != 0) { intel_sdvo_write_sdvox(intel_output, temp & ~SDVO_ENABLE); -- cgit v1.2.3