diff options
author | Eric Anholt <eric@anholt.net> | 2008-04-02 15:16:17 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2008-04-02 16:11:18 -0700 |
commit | 6ad2d6ba86689674876f5f4c473f11e39243ac38 (patch) | |
tree | e72f47f0c4492484701b3da79f67ca9f868d3cc1 | |
parent | 3a17400dc67534f0eb474ece080f01061469569c (diff) |
SDVO: Fix mixups with input and output channels.
The 2-bit input_mask was actually an input count -- in0 is always there, and
in1 is optional.
The output flags weren't being reported in the log, so I mistakenly took
controlled_output == RGB0 to mean that the device only reported an RGB0,
while it actually reported RGB0|SVID0|YPRPB0|misc|other. Move SVID0 up
in priority and remove the RGB-is-it-really-TV hack I had just come up with.
Finally, set the input/output mapping at mode set time. We're always
supposed to do this, but haven't had to so far as we've never handled
devices with more than one output.
-rw-r--r-- | src/i830_sdvo.c | 108 | ||||
-rw-r--r-- | src/i830_sdvo_regs.h | 5 |
2 files changed, 66 insertions, 47 deletions
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c index 59d97c66..46213a2f 100644 --- a/src/i830_sdvo.c +++ b/src/i830_sdvo.c @@ -230,7 +230,7 @@ const static struct _sdvo_cmd_name { static I2CSlaveAddr slaveAddr; -#define SDVO_NAME(dev_priv) ((dev_priv)->output_device == SDVOB ? "SDVO" : "SDVO") +#define SDVO_NAME(dev_priv) ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC") #define SDVO_PRIV(output) ((struct i830_sdvo_priv *) (output)->dev_priv) /** @@ -668,13 +668,26 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode, uint16_t width, height; uint16_t h_blank_len, h_sync_len, v_blank_len, v_sync_len; uint16_t h_sync_offset, v_sync_offset; + struct i830_sdvo_in_out_map in_out; struct i830_sdvo_dtd output_dtd; - uint16_t no_outputs; - - no_outputs = 0; + uint8_t status; if (!mode) return; + + /* First, set the input mapping for the first input to our controlled + * output. This is only correct if we're a single-input device, in + * which case the first input is the output from the appropriate SDVO + * channel on the motherboard. In a two-input device, the first input + * will be SDVOB and the second SDVOC. + */ + in_out.in0 = dev_priv->controlled_output; + in_out.in1 = 0; + + i830_sdvo_write_cmd(output, SDVO_CMD_SET_IN_OUT_MAP, + &in_out, sizeof(in_out)); + status = i830_sdvo_read_response(output, NULL, 0); + width = mode->CrtcHDisplay; height = mode->CrtcVDisplay; @@ -843,12 +856,10 @@ i830_sdvo_save(xf86OutputPtr output) dev_priv->save_sdvo_mult = i830_sdvo_get_clock_rate_mult(output); i830_sdvo_get_active_outputs(output, &dev_priv->save_active_outputs); - if (dev_priv->caps.sdvo_inputs_mask & 0x1) { - i830_sdvo_set_target_input(output, TRUE, FALSE); - i830_sdvo_get_input_timing(output, &dev_priv->save_input_dtd_1); - } + i830_sdvo_set_target_input(output, TRUE, FALSE); + i830_sdvo_get_input_timing(output, &dev_priv->save_input_dtd_1); - if (dev_priv->caps.sdvo_inputs_mask & 0x2) { + if (dev_priv->caps.sdvo_input_count >= 2) { i830_sdvo_set_target_input(output, FALSE, TRUE); i830_sdvo_get_input_timing(output, &dev_priv->save_input_dtd_2); } @@ -892,12 +903,10 @@ i830_sdvo_restore(xf86OutputPtr output) } } - if (dev_priv->caps.sdvo_inputs_mask & 0x1) { - i830_sdvo_set_target_input(output, TRUE, FALSE); - i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_1); - } + i830_sdvo_set_target_input(output, TRUE, FALSE); + i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_1); - if (dev_priv->caps.sdvo_inputs_mask & 0x2) { + if (dev_priv->caps.sdvo_input_count >= 2) { i830_sdvo_set_target_input(output, FALSE, TRUE); i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_2); } @@ -1345,7 +1354,6 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) char name[60]; char *name_prefix; char *name_suffix; - struct i830_sdvo_tv_format tv_formats; output = xf86OutputCreate (pScrn, &i830_sdvo_output_funcs,NULL); if (!output) @@ -1463,6 +1471,13 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) output->subpixel_order = SubPixelHorizontalRGB; name_prefix="TMDS"; } + else if (dev_priv->caps.output_flags & SDVO_OUTPUT_SVID0) + { + dev_priv->controlled_output = SDVO_OUTPUT_SVID0; + output->subpixel_order = SubPixelHorizontalRGB; /* XXX */ + name_prefix="TV"; + dev_priv->is_tv = TRUE; + } else if (dev_priv->caps.output_flags & SDVO_OUTPUT_RGB0) { dev_priv->controlled_output = SDVO_OUTPUT_RGB0; @@ -1475,13 +1490,6 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) output->subpixel_order = SubPixelHorizontalRGB; name_prefix="VGA"; } - else if (dev_priv->caps.output_flags & SDVO_OUTPUT_SVID0) - { - dev_priv->controlled_output = SDVO_OUTPUT_SVID0; - output->subpixel_order = SubPixelHorizontalRGB; /* XXX */ - name_prefix="S-Video"; - dev_priv->is_tv = TRUE; - } else { unsigned char bytes[2]; @@ -1495,21 +1503,6 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) name_prefix="Unknown"; } - if (dev_priv->controlled_output == SDVO_OUTPUT_RGB0 || - dev_priv->controlled_output == SDVO_OUTPUT_RGB1) { - uint8_t status; - - /* Detect if an RGB device is actually a TV device. This is the - * case for our HDMI+S-Video SDVO card. - */ - i830_sdvo_write_cmd(output, SDVO_CMD_GET_SUPPORTED_TV_FORMATS, - NULL, 0); - status = i830_sdvo_read_response(output, - &tv_formats, sizeof(tv_formats)); - if (status == SDVO_CMD_STATUS_SUCCESS) - dev_priv->is_tv = TRUE; - } - strcpy (name, name_prefix); strcat (name, name_suffix); if (!xf86OutputRename (output, name)) @@ -1526,17 +1519,40 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device) &dev_priv->pixel_clock_max); xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "%s device VID/DID: %02X:%02X.%02X, " - "clock range %.1fMHz - %.1fMHz, " - "input 1: %c, input 2: %c, " - "output 1: %c, output 2: %c\n", + "%s: device VID/DID: %02X:%02X.%02X, " + "clock range %.1fMHz - %.1fMHz\n", SDVO_NAME(dev_priv), dev_priv->caps.vendor_id, dev_priv->caps.device_id, dev_priv->caps.device_rev_id, dev_priv->pixel_clock_min / 1000.0, - dev_priv->pixel_clock_max / 1000.0, - (dev_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N', - (dev_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N', - dev_priv->caps.output_flags & (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_TMDS0) ? 'Y' : 'N', - dev_priv->caps.output_flags & (SDVO_OUTPUT_RGB1 | SDVO_OUTPUT_TMDS1) ? 'Y' : 'N'); + dev_priv->pixel_clock_max / 1000.0); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "%s: %d input channel%s\n", + SDVO_NAME(dev_priv), dev_priv->caps.sdvo_input_count, + dev_priv->caps.sdvo_input_count >= 2 ? "s" : ""); + +#define REPORT_OUTPUT_FLAG(flag, name) do { \ + if (dev_priv->caps.output_flags & flag) { \ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s: %s output reported\n", \ + SDVO_NAME(dev_priv), name); \ + } \ +} while (0) + + REPORT_OUTPUT_FLAG(SDVO_OUTPUT_TMDS0, "TMDS0"); + REPORT_OUTPUT_FLAG(SDVO_OUTPUT_RGB0, "RGB0"); + REPORT_OUTPUT_FLAG(SDVO_OUTPUT_CVBS0, "CVBS0"); + REPORT_OUTPUT_FLAG(SDVO_OUTPUT_SVID0, "SVID0"); + REPORT_OUTPUT_FLAG(SDVO_OUTPUT_YPRPB0, "YPRPB0"); + REPORT_OUTPUT_FLAG(SDVO_OUTPUT_SCART0, "SCART0"); + REPORT_OUTPUT_FLAG(SDVO_OUTPUT_LVDS0, "LVDS0"); + + REPORT_OUTPUT_FLAG(SDVO_OUTPUT_TMDS1, "TMDS1"); + REPORT_OUTPUT_FLAG(SDVO_OUTPUT_RGB1, "RGB1"); + REPORT_OUTPUT_FLAG(SDVO_OUTPUT_CVBS1, "CVBS1"); + REPORT_OUTPUT_FLAG(SDVO_OUTPUT_SVID1, "SVID1"); + REPORT_OUTPUT_FLAG(SDVO_OUTPUT_YPRPB1, "YPRPB1"); + REPORT_OUTPUT_FLAG(SDVO_OUTPUT_SCART1, "SCART1"); + REPORT_OUTPUT_FLAG(SDVO_OUTPUT_LVDS1, "LVDS1"); + } diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h index 63688acd..3a2deafd 100644 --- a/src/i830_sdvo_regs.h +++ b/src/i830_sdvo_regs.h @@ -52,7 +52,7 @@ struct i830_sdvo_caps { uint8_t device_rev_id; uint8_t sdvo_version_major; uint8_t sdvo_version_minor; - unsigned int sdvo_inputs_mask:2; + unsigned int sdvo_input_count:2; unsigned int smooth_scaling:1; unsigned int sharp_scaling:1; unsigned int up_scaling:1; @@ -174,6 +174,9 @@ struct i830_sdvo_get_trained_inputs_response { * Returns two struct i830_sdvo_output_flags structures. */ #define SDVO_CMD_GET_IN_OUT_MAP 0x06 +struct i830_sdvo_in_out_map { + uint16_t in0, in1; +}; /** * Sets the current mapping of SDVO inputs to outputs on the device. |