#include "i915_drm.h"
#include "i915_drv.h"
-enum tv_type {
- TV_TYPE_NONE,
- TV_TYPE_UNKNOWN,
- TV_TYPE_COMPOSITE,
- TV_TYPE_SVIDEO,
- TV_TYPE_COMPONENT
-};
-
enum tv_margin {
TV_MARGIN_LEFT, TV_MARGIN_TOP,
TV_MARGIN_RIGHT, TV_MARGIN_BOTTOM
switch (tv_priv->type) {
default:
- case TV_TYPE_UNKNOWN:
- case TV_TYPE_COMPOSITE:
+ case ConnectorUnknown:
+ case ConnectorComposite:
tv_ctl |= TV_ENC_OUTPUT_COMPOSITE;
video_levels = tv_mode->composite_levels;
color_conversion = tv_mode->composite_color;
burst_ena = tv_mode->burst_ena;
break;
- case TV_TYPE_COMPONENT:
+ case ConnectorComponent:
tv_ctl |= TV_ENC_OUTPUT_COMPONENT;
video_levels = &component_levels;
if (tv_mode->burst_ena)
color_conversion = &hdtv_csc_yprpb;
burst_ena = FALSE;
break;
- case TV_TYPE_SVIDEO:
+ case ConnectorSVIDEO:
tv_ctl |= TV_ENC_OUTPUT_SVIDEO;
video_levels = tv_mode->svideo_levels;
color_conversion = tv_mode->svideo_color;
if (tv_mode->pal_burst)
tv_ctl |= TV_PAL_BURST;
scctl1 = 0;
- if (tv_mode->dda1_inc)
+ /* dda1 implies valid video levels */
+ if (tv_mode->dda1_inc) {
scctl1 |= TV_SC_DDA1_EN;
+ scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
+ }
if (tv_mode->dda2_inc)
scctl1 |= TV_SC_DDA2_EN;
scctl1 |= TV_SC_DDA3_EN;
scctl1 |= tv_mode->sc_reset;
- scctl1 |= video_levels->burst << TV_BURST_LEVEL_SHIFT;
scctl1 |= tv_mode->dda1_inc << TV_SCDDA1_INC_SHIFT;
scctl2 = tv_mode->dda2_size << TV_SCDDA2_SIZE_SHIFT |
I915_WRITE(TV_SC_CTL_2, scctl2);
I915_WRITE(TV_SC_CTL_3, scctl3);
- I915_WRITE(TV_CSC_Y, (color_conversion->ry << 16) |
- color_conversion->gy);
- I915_WRITE(TV_CSC_Y2,(color_conversion->by << 16) |
- color_conversion->ay);
- I915_WRITE(TV_CSC_U, (color_conversion->ru << 16) |
- color_conversion->gu);
- I915_WRITE(TV_CSC_U2, (color_conversion->bu << 16) |
- color_conversion->au);
- I915_WRITE(TV_CSC_V, (color_conversion->rv << 16) |
- color_conversion->gv);
- I915_WRITE(TV_CSC_V2, (color_conversion->bv << 16) |
- color_conversion->av);
+ if (color_conversion) {
+ I915_WRITE(TV_CSC_Y, (color_conversion->ry << 16) |
+ color_conversion->gy);
+ I915_WRITE(TV_CSC_Y2,(color_conversion->by << 16) |
+ color_conversion->ay);
+ I915_WRITE(TV_CSC_U, (color_conversion->ru << 16) |
+ color_conversion->gu);
+ I915_WRITE(TV_CSC_U2, (color_conversion->bu << 16) |
+ color_conversion->au);
+ I915_WRITE(TV_CSC_V, (color_conversion->rv << 16) |
+ color_conversion->gv);
+ I915_WRITE(TV_CSC_V2, (color_conversion->bv << 16) |
+ color_conversion->av);
+ }
I915_WRITE(TV_CLR_KNOBS, 0x00606000);
- I915_WRITE(TV_CLR_LEVEL, ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
- (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
+ if (video_levels)
+ I915_WRITE(TV_CLR_LEVEL,
+ ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
+ (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
{
int pipeconf_reg = (intel_crtc->pipe == 0) ?
PIPEACONF : PIPEBCONF;
struct intel_output *intel_output = output->driver_private;
u32 tv_ctl, save_tv_ctl;
u32 tv_dac, save_tv_dac;
- int type = TV_TYPE_UNKNOWN;
+ int type = ConnectorUnknown;
tv_dac = I915_READ(TV_DAC);
/*
*/
if ((tv_dac & TVDAC_SENSE_MASK) == (TVDAC_B_SENSE | TVDAC_C_SENSE)) {
DRM_DEBUG("Detected Composite TV connection\n");
- type = TV_TYPE_COMPOSITE;
+ type = ConnectorComposite;
} else if ((tv_dac & (TVDAC_A_SENSE|TVDAC_B_SENSE)) == TVDAC_A_SENSE) {
DRM_DEBUG("Detected S-Video TV connection\n");
- type = TV_TYPE_SVIDEO;
+ type = ConnectorSVIDEO;
} else if ((tv_dac & TVDAC_SENSE_MASK) == 0) {
DRM_DEBUG("Detected Component TV connection\n");
- type = TV_TYPE_COMPONENT;
+ type = ConnectorComponent;
} else {
DRM_DEBUG("No TV connection detected\n");
- type = TV_TYPE_NONE;
+ type = -1;
}
return type;
}
-static int
-intel_tv_format_configure_property (struct drm_output *output);
-
/**
* Detect the TV connection.
*
}
if (type != tv_priv->type) {
+ struct drm_property *connector_property =
+ output->dev->mode_config.connector_type_property;
+
tv_priv->type = type;
- intel_tv_format_configure_property(output);
+ drm_output_property_set_value(output, connector_property,
+ type);
}
- switch (type) {
- case TV_TYPE_NONE:
+ if (type < 0)
return output_status_disconnected;
- case TV_TYPE_UNKNOWN:
- return output_status_unknown;
- default:
- return output_status_connected;
- }
+
+ return output_status_connected;
}
static struct input_res {
}
static bool
-intel_tv_format_set_property(struct drm_output *output,
- struct drm_property *prop, uint64_t val)
-{
-#if 0
- struct intel_output *intel_output = output->driver_private;
- struct intel_tv_priv *tv_priv = intel_output->dev_priv;
- const struct tv_mode *tv_mode =
- intel_tv_mode_lookup(tv_priv->tv_format);
- int err;
-
- if (!tv_mode)
- tv_mode = &tv_modes[0];
- err = RRChangeOutputProperty (output->randr_output, tv_format_atom,
- XA_ATOM, 32, PropModeReplace, 1,
- &tv_format_name_atoms[tv_mode - tv_modes],
- FALSE, TRUE);
- return err == Success;
-#endif
- return 0;
-}
-
-
-/**
- * Configure the TV_FORMAT property to list only supported formats
- *
- * Unless the connector is component, list only the formats supported by
- * svideo and composite
- */
-
-static int
-intel_tv_format_configure_property(struct drm_output *output)
-{
-#if 0
- struct intel_output *intel_output = output->driver_private;
- struct intel_tv_priv *tv_priv = intel_output->dev_priv;
- Atom current_atoms[NUM_TV_MODES];
- int num_atoms = 0;
- int i;
-
- if (!output->randr_output)
- return Success;
-
- for (i = 0; i < NUM_TV_MODES; i++)
- if (!tv_modes[i].component_only ||
- tv_priv->type == TV_TYPE_COMPONENT)
- current_atoms[num_atoms++] = tv_format_name_atoms[i];
-
- return RRConfigureOutputProperty(output->randr_output, tv_format_atom,
- TRUE, FALSE, FALSE,
- num_atoms, (INT32 *) current_atoms);
-#endif
- return 0;
-}
-
-static void
-intel_tv_create_resources(struct drm_output *output)
-{
- struct drm_device *dev = output->dev;
- struct intel_output *intel_output = output->driver_private;
- struct intel_tv_priv *tv_priv = intel_output->dev_priv;
- int i, err;
-
-#if 0
- /* Set up the tv_format property, which takes effect on mode set
- * and accepts strings that match exactly
- */
- tv_format_atom = MakeAtom(TV_FORMAT_NAME, sizeof(TV_FORMAT_NAME) - 1,
- TRUE);
-
- for (i = 0; i < NUM_TV_MODES; i++)
- tv_format_name_atoms[i] = MakeAtom (tv_modes[i].name,
- strlen (tv_modes[i].name),
- TRUE);
-
- err = intel_tv_format_configure_property (output);
-
- if (err != 0) {
- xf86DrvMsg(dev->scrnIndex, X_ERROR,
- "RRConfigureOutputProperty error, %d\n", err);
- }
-
- /* Set the current value of the tv_format property */
- if (!intel_tv_format_set_property (output))
- xf86DrvMsg(dev->scrnIndex, X_ERROR,
- "RRChangeOutputProperty error, %d\n", err);
-
- for (i = 0; i < 4; i++)
- {
- INT32 range[2];
- margin_atoms[i] = MakeAtom(margin_names[i], strlen (margin_names[i]),
- TRUE);
-
- range[0] = 0;
- range[1] = 100;
- err = RRConfigureOutputProperty(output->randr_output, margin_atoms[i],
- TRUE, TRUE, FALSE, 2, range);
-
- if (err != 0)
- xf86DrvMsg(dev->scrnIndex, X_ERROR,
- "RRConfigureOutputProperty error, %d\n", err);
-
- err = RRChangeOutputProperty(output->randr_output, margin_atoms[i],
- XA_INTEGER, 32, PropModeReplace,
- 1, &tv_priv->margin[i],
- FALSE, TRUE);
- if (err != 0)
- xf86DrvMsg(dev->scrnIndex, X_ERROR,
- "RRChangeOutputProperty error, %d\n", err);
- }
-#endif
-}
-
-static bool
intel_tv_set_property(struct drm_output *output, struct drm_property *property,
uint64_t val)
{
struct drm_device *dev = output->dev;
+ struct intel_output *intel_output = output->driver_private;
+ struct intel_tv_priv *tv_priv = intel_output->dev_priv;
int ret = 0;
-
- if (property == dev->mode_config.tv_left_margin_property ||
- property == dev->mode_config.tv_right_margin_property ||
- property == dev->mode_config.tv_top_margin_property ||
- property == dev->mode_config.tv_bottom_margin_property) {
- ret = drm_output_property_set_value(output, property, val);
+
+ ret = drm_output_property_set_value(output, property, val);
+ if (ret < 0)
+ goto out;
+
+ if (property == dev->mode_config.tv_left_margin_property)
+ tv_priv->margin[TV_MARGIN_LEFT] = val;
+ else if (property == dev->mode_config.tv_right_margin_property)
+ tv_priv->margin[TV_MARGIN_RIGHT] = val;
+ else if (property == dev->mode_config.tv_top_margin_property)
+ tv_priv->margin[TV_MARGIN_TOP] = val;
+ else if (property == dev->mode_config.tv_bottom_margin_property)
+ tv_priv->margin[TV_MARGIN_BOTTOM] = val;
+ else if (property == dev->mode_config.tv_mode_property) {
+ if (val >= NUM_TV_MODES) {
+ ret = -EINVAL;
+ goto out;
+ }
+ tv_priv->tv_format = tv_modes[val].name;
+ intel_tv_mode_set(output, NULL, NULL);
} else {
- /* TV mode handling here */
+ ret = -EINVAL;
+ goto out;
}
+ intel_tv_mode_set(output, NULL, NULL);
+out:
return ret;
}
struct intel_output *intel_output;
struct intel_tv_priv *tv_priv;
u32 tv_dac_on, tv_dac_off, save_tv_dac;
+ char **tv_format_names;
+ int i, initial_mode = 0;
/* FIXME: better TV detection and/or quirks */
#if 0
output->possible_crtcs = ((1 << 0) | (1 << 1));
output->possible_clones = (1 << INTEL_OUTPUT_TVOUT);
intel_output->dev_priv = tv_priv;
- tv_priv->type = TV_TYPE_UNKNOWN;
+ tv_priv->type = ConnectorUnknown;
- tv_priv->tv_format = NULL;
-
/* BIOS margin values */
tv_priv->margin[TV_MARGIN_LEFT] = 54;
tv_priv->margin[TV_MARGIN_TOP] = 36;
tv_priv->margin[TV_MARGIN_RIGHT] = 46;
tv_priv->margin[TV_MARGIN_BOTTOM] = 37;
- if (!tv_priv->tv_format)
- tv_priv->tv_format = kstrdup(tv_modes[0].name, GFP_KERNEL);
+ tv_priv->tv_format = kstrdup(tv_modes[initial_mode].name, GFP_KERNEL);
output->driver_private = intel_output;
output->interlace_allowed = FALSE;
output->doublescan_allowed = FALSE;
+ drm_output_attach_property(output,
+ dev->mode_config.connector_type_property,
+ ConnectorUnknown);
+
+ /* Create TV properties then attach current values */
+ tv_format_names = drm_alloc(sizeof(char *) * NUM_TV_MODES,
+ DRM_MEM_DRIVER);
+ if (!tv_format_names)
+ goto out;
+ for (i = 0; i < NUM_TV_MODES; i++)
+ tv_format_names[i] = tv_modes[i].name;
+ drm_create_tv_properties(dev, NUM_TV_MODES, tv_format_names);
+
+ drm_output_attach_property(output, dev->mode_config.tv_mode_property,
+ initial_mode);
+ drm_output_attach_property(output,
+ dev->mode_config.tv_left_margin_property,
+ tv_priv->margin[TV_MARGIN_LEFT]);
+ drm_output_attach_property(output,
+ dev->mode_config.tv_top_margin_property,
+ tv_priv->margin[TV_MARGIN_TOP]);
+ drm_output_attach_property(output,
+ dev->mode_config.tv_right_margin_property,
+ tv_priv->margin[TV_MARGIN_RIGHT]);
+ drm_output_attach_property(output,
+ dev->mode_config.tv_bottom_margin_property,
+ tv_priv->margin[TV_MARGIN_BOTTOM]);
+out:
drm_sysfs_output_add(output);
}