Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 163962
b: refs/heads/master
c: ce6feab
h: refs/heads/master
v: v3
  • Loading branch information
Zhao Yakui authored and Eric Anholt committed Sep 4, 2009
1 parent 8dd7231 commit 130f51a
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 49 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 213c2e643145fc7d8a67f2d5d54ee0f6d7193e2e
refs/heads/master: ce6feabd1b38f9adf4a962d71bc4762047e8f889
201 changes: 153 additions & 48 deletions trunk/drivers/gpu/drm/i915/intel_sdvo.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@

#undef SDVO_DEBUG
#define I915_SDVO "i915_sdvo"
static char *tv_format_names[] = {
"NTSC_M" , "NTSC_J" , "NTSC_443",
"PAL_B" , "PAL_D" , "PAL_G" ,
"PAL_H" , "PAL_I" , "PAL_M" ,
"PAL_N" , "PAL_NC" , "PAL_60" ,
"SECAM_B" , "SECAM_D" , "SECAM_G" ,
"SECAM_K" , "SECAM_K1", "SECAM_L" ,
"SECAM_60"
};

#define TV_FORMAT_NUM (sizeof(tv_format_names) / sizeof(*tv_format_names))

struct intel_sdvo_priv {
u8 slave_addr;

Expand Down Expand Up @@ -71,6 +83,15 @@ struct intel_sdvo_priv {
*/
bool is_tv;

/* This is for current tv format name */
char *tv_format_name;

/* This contains all current supported TV format */
char *tv_format_supported[TV_FORMAT_NUM];
int format_supported_num;
struct drm_property *tv_format_property;
struct drm_property *tv_format_name_property[TV_FORMAT_NUM];

/**
* This is set if we treat the device as HDMI, instead of DVI.
*/
Expand All @@ -97,14 +118,6 @@ struct intel_sdvo_priv {
*/
struct intel_sdvo_sdtv_resolution_reply sdtv_resolutions;

/**
* Current selected TV format.
*
* This is stored in the same structure that's passed to the device, for
* convenience.
*/
struct intel_sdvo_tv_format tv_format;

/*
* supported encoding mode, used to determine whether HDMI is
* supported
Expand Down Expand Up @@ -945,23 +958,28 @@ static void intel_sdvo_set_avi_infoframe(struct intel_output *output,

static void intel_sdvo_set_tv_format(struct intel_output *output)
{

struct intel_sdvo_tv_format format;
struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
struct intel_sdvo_tv_format *format, unset;
u8 status;
uint32_t format_map, i;
uint8_t status;

format = &sdvo_priv->tv_format;
memset(&unset, 0, sizeof(unset));
if (memcmp(format, &unset, sizeof(*format))) {
DRM_DEBUG("%s: Choosing default TV format of NTSC-M\n",
SDVO_NAME(sdvo_priv));
format->ntsc_m = 1;
intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, format,
sizeof(*format));
status = intel_sdvo_read_response(output, NULL, 0);
if (status != SDVO_CMD_STATUS_SUCCESS)
DRM_DEBUG("%s: Failed to set TV format\n",
SDVO_NAME(sdvo_priv));
}
for (i = 0; i < TV_FORMAT_NUM; i++)
if (tv_format_names[i] == sdvo_priv->tv_format_name)
break;

format_map = 1 << i;
memset(&format, 0, sizeof(format));
memcpy(&format, &format_map, sizeof(format_map) > sizeof(format) ?
sizeof(format) : sizeof(format_map));

intel_sdvo_write_cmd(output, SDVO_CMD_SET_TV_FORMAT, &format_map,
sizeof(format));

status = intel_sdvo_read_response(output, NULL, 0);
if (status != SDVO_CMD_STATUS_SUCCESS)
DRM_DEBUG("%s: Failed to set TV format\n",
SDVO_NAME(sdvo_priv));
}

static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
Expand Down Expand Up @@ -1516,7 +1534,8 @@ static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connect
struct intel_output *intel_output = to_intel_output(connector);
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;

intel_sdvo_write_cmd(intel_output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
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 & 0xff, response >> 8);
Expand Down Expand Up @@ -1567,25 +1586,6 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector)
#endif
}

/**
* This function checks the current TV format, and chooses a default if
* it hasn't been set.
*/
static void
intel_sdvo_check_tv_format(struct intel_output *output)
{
struct intel_sdvo_priv *dev_priv = output->dev_priv;
struct intel_sdvo_tv_format format;
uint8_t status;

intel_sdvo_write_cmd(output, SDVO_CMD_GET_TV_FORMAT, NULL, 0);
status = intel_sdvo_read_response(output, &format, sizeof(format));
if (status != SDVO_CMD_STATUS_SUCCESS)
return;

memcpy(&dev_priv->tv_format, &format, sizeof(format));
}

/*
* Set of SDVO TV modes.
* Note! This is in reply order (see loop in get_tv_modes).
Expand Down Expand Up @@ -1656,17 +1656,26 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
struct intel_output *output = to_intel_output(connector);
struct intel_sdvo_priv *sdvo_priv = output->dev_priv;
struct intel_sdvo_sdtv_resolution_request tv_res;
uint32_t reply = 0;
uint32_t reply = 0, format_map = 0;
int i;
uint8_t status;
int i = 0;

intel_sdvo_check_tv_format(output);

/* Read the list of supported input resolutions for the selected TV
* format.
*/
memset(&tv_res, 0, sizeof(tv_res));
memcpy(&tv_res, &sdvo_priv->tv_format, sizeof(tv_res));
for (i = 0; i < TV_FORMAT_NUM; i++)
if (tv_format_names[i] == sdvo_priv->tv_format_name)
break;

format_map = (1 << i);
memcpy(&tv_res, &format_map,
sizeof(struct intel_sdvo_sdtv_resolution_request) >
sizeof(format_map) ? sizeof(format_map) :
sizeof(struct intel_sdvo_sdtv_resolution_request));

intel_sdvo_set_target_output(output, sdvo_priv->controlled_output);

intel_sdvo_write_cmd(output, SDVO_CMD_GET_SDTV_RESOLUTION_SUPPORT,
&tv_res, sizeof(tv_res));
status = intel_sdvo_read_response(output, &reply, 3);
Expand All @@ -1681,6 +1690,7 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector)
if (nmode)
drm_mode_probed_add(connector, nmode);
}

}

static void intel_sdvo_get_lvds_modes(struct drm_connector *connector)
Expand Down Expand Up @@ -1753,12 +1763,55 @@ static void intel_sdvo_destroy(struct drm_connector *connector)
drm_mode_destroy(connector->dev,
sdvo_priv->sdvo_lvds_fixed_mode);

if (sdvo_priv->tv_format_property)
drm_property_destroy(connector->dev,
sdvo_priv->tv_format_property);

drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);

kfree(intel_output);
}

static int
intel_sdvo_set_property(struct drm_connector *connector,
struct drm_property *property,
uint64_t val)
{
struct intel_output *intel_output = to_intel_output(connector);
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
struct drm_encoder *encoder = &intel_output->enc;
struct drm_crtc *crtc = encoder->crtc;
int ret = 0;
bool changed = false;

ret = drm_connector_property_set_value(connector, property, val);
if (ret < 0)
goto out;

if (property == sdvo_priv->tv_format_property) {
if (val >= TV_FORMAT_NUM) {
ret = -EINVAL;
goto out;
}
if (sdvo_priv->tv_format_name ==
sdvo_priv->tv_format_supported[val])
goto out;

sdvo_priv->tv_format_name = sdvo_priv->tv_format_supported[val];
changed = true;
} else {
ret = -EINVAL;
goto out;
}

if (changed && crtc)
drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
crtc->y, crtc->fb);
out:
return ret;
}

static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = {
.dpms = intel_sdvo_dpms,
.mode_fixup = intel_sdvo_mode_fixup,
Expand All @@ -1773,6 +1826,7 @@ static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
.restore = intel_sdvo_restore,
.detect = intel_sdvo_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = intel_sdvo_set_property,
.destroy = intel_sdvo_destroy,
};

Expand Down Expand Up @@ -2029,6 +2083,55 @@ intel_sdvo_output_setup(struct intel_output *intel_output, uint16_t flags)

}

static void intel_sdvo_tv_create_property(struct drm_connector *connector)
{
struct intel_output *intel_output = to_intel_output(connector);
struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv;
struct intel_sdvo_tv_format format;
uint32_t format_map, i;
uint8_t status;

intel_sdvo_set_target_output(intel_output,
sdvo_priv->controlled_output);

intel_sdvo_write_cmd(intel_output,
SDVO_CMD_GET_SUPPORTED_TV_FORMATS, NULL, 0);
status = intel_sdvo_read_response(intel_output,
&format, sizeof(format));
if (status != SDVO_CMD_STATUS_SUCCESS)
return;

memcpy(&format_map, &format, sizeof(format) > sizeof(format_map) ?
sizeof(format_map) : sizeof(format));

if (format_map == 0)
return;

sdvo_priv->format_supported_num = 0;
for (i = 0 ; i < TV_FORMAT_NUM; i++)
if (format_map & (1 << i)) {
sdvo_priv->tv_format_supported
[sdvo_priv->format_supported_num++] =
tv_format_names[i];
}


sdvo_priv->tv_format_property =
drm_property_create(
connector->dev, DRM_MODE_PROP_ENUM,
"mode", sdvo_priv->format_supported_num);

for (i = 0; i < sdvo_priv->format_supported_num; i++)
drm_property_add_enum(
sdvo_priv->tv_format_property, i,
i, sdvo_priv->tv_format_supported[i]);

sdvo_priv->tv_format_name = sdvo_priv->tv_format_supported[0];
drm_connector_attach_property(
connector, sdvo_priv->tv_format_property, 0);

}

bool intel_sdvo_init(struct drm_device *dev, int output_device)
{
struct drm_connector *connector;
Expand Down Expand Up @@ -2111,6 +2214,8 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device)
drm_encoder_helper_add(&intel_output->enc, &intel_sdvo_helper_funcs);

drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc);
if (sdvo_priv->is_tv)
intel_sdvo_tv_create_property(connector);
drm_sysfs_connector_add(connector);

intel_sdvo_select_ddc_bus(sdvo_priv);
Expand Down

0 comments on commit 130f51a

Please sign in to comment.