Skip to content

Commit

Permalink
gma500: Convert PSB LVDS to new output handling
Browse files Browse the repository at this point in the history
LVDS for PSB now uses psb_intel_encoder and psb_intel_connectors instead of
psb_intel_output. i2c_bus and ddc_bus are moved to lvds_priv. There was also a
pointer to mode_dev (for no obvious reason) that we now get directly from
dev_priv.

Signed-off-by: Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information
Patrik Jakobsson authored and Dave Airlie committed Dec 20, 2011
1 parent 1730f89 commit 9c8cee4
Showing 1 changed file with 83 additions and 69 deletions.
152 changes: 83 additions & 69 deletions drivers/gpu/drm/gma500/psb_intel_lvds.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ struct psb_intel_lvds_priv {
uint32_t savePFIT_CONTROL;
uint32_t savePFIT_PGM_RATIOS;
uint32_t saveBLC_PWM_CTL;

struct psb_intel_i2c_chan *i2c_bus;
struct psb_intel_i2c_chan *ddc_bus;
};


Expand Down Expand Up @@ -214,9 +217,10 @@ static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level)
/*
* Sets the power state for the panel.
*/
static void psb_intel_lvds_set_power(struct drm_device *dev,
struct psb_intel_output *output, bool on)
static void psb_intel_lvds_set_power(struct drm_device *dev, bool on)
{
struct drm_psb_private *dev_priv = dev->dev_private;
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
u32 pp_status;

if (!gma_power_begin(dev, true)) {
Expand All @@ -232,8 +236,7 @@ static void psb_intel_lvds_set_power(struct drm_device *dev,
} while ((pp_status & PP_ON) == 0);

psb_intel_lvds_set_backlight(dev,
output->
mode_dev->backlight_duty_cycle);
mode_dev->backlight_duty_cycle);
} else {
psb_intel_lvds_set_backlight(dev, 0);

Expand All @@ -250,12 +253,11 @@ static void psb_intel_lvds_set_power(struct drm_device *dev,
static void psb_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
struct psb_intel_output *output = enc_to_psb_intel_output(encoder);

if (mode == DRM_MODE_DPMS_ON)
psb_intel_lvds_set_power(dev, output, true);
psb_intel_lvds_set_power(dev, true);
else
psb_intel_lvds_set_power(dev, output, false);
psb_intel_lvds_set_power(dev, false);

/* XXX: We never power down the LVDS pairs. */
}
Expand All @@ -265,10 +267,10 @@ static void psb_intel_lvds_save(struct drm_connector *connector)
struct drm_device *dev = connector->dev;
struct drm_psb_private *dev_priv =
(struct drm_psb_private *)dev->dev_private;
struct psb_intel_output *psb_intel_output =
to_psb_intel_output(connector);
struct psb_intel_encoder *psb_intel_encoder =
psb_intel_attached_encoder(connector);
struct psb_intel_lvds_priv *lvds_priv =
(struct psb_intel_lvds_priv *)psb_intel_output->dev_priv;
(struct psb_intel_lvds_priv *)psb_intel_encoder->dev_priv;

lvds_priv->savePP_ON = REG_READ(LVDSPP_ON);
lvds_priv->savePP_OFF = REG_READ(LVDSPP_OFF);
Expand Down Expand Up @@ -305,10 +307,10 @@ static void psb_intel_lvds_restore(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
u32 pp_status;
struct psb_intel_output *psb_intel_output =
to_psb_intel_output(connector);
struct psb_intel_encoder *psb_intel_encoder =
psb_intel_attached_encoder(connector);
struct psb_intel_lvds_priv *lvds_priv =
(struct psb_intel_lvds_priv *)psb_intel_output->dev_priv;
(struct psb_intel_lvds_priv *)psb_intel_encoder->dev_priv;

dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
lvds_priv->savePP_ON,
Expand Down Expand Up @@ -346,13 +348,14 @@ static void psb_intel_lvds_restore(struct drm_connector *connector)
int psb_intel_lvds_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct psb_intel_output *psb_intel_output =
to_psb_intel_output(connector);
struct drm_psb_private *dev_priv = connector->dev->dev_private;
struct psb_intel_encoder *psb_intel_encoder =
psb_intel_attached_encoder(connector);
struct drm_display_mode *fixed_mode =
psb_intel_output->mode_dev->panel_fixed_mode;
dev_priv->mode_dev.panel_fixed_mode;

if (psb_intel_output->type == INTEL_OUTPUT_MIPI2)
fixed_mode = psb_intel_output->mode_dev->panel_fixed_mode2;
if (psb_intel_encoder->type == INTEL_OUTPUT_MIPI2)
fixed_mode = dev_priv->mode_dev.panel_fixed_mode2;

/* just in case */
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
Expand All @@ -375,17 +378,17 @@ bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct psb_intel_mode_device *mode_dev =
enc_to_psb_intel_output(encoder)->mode_dev;
struct drm_device *dev = encoder->dev;
struct drm_psb_private *dev_priv = dev->dev_private;
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
struct psb_intel_crtc *psb_intel_crtc =
to_psb_intel_crtc(encoder->crtc);
struct drm_encoder *tmp_encoder;
struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;
struct psb_intel_output *psb_intel_output =
enc_to_psb_intel_output(encoder);
struct psb_intel_encoder *psb_intel_encoder =
to_psb_intel_encoder(encoder);

if (psb_intel_output->type == INTEL_OUTPUT_MIPI2)
if (psb_intel_encoder->type == INTEL_OUTPUT_MIPI2)
panel_fixed_mode = mode_dev->panel_fixed_mode2;

/* PSB requires the LVDS is on pipe B, MRST has only one pipe anyway */
Expand Down Expand Up @@ -440,8 +443,8 @@ bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
static void psb_intel_lvds_prepare(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
struct psb_intel_mode_device *mode_dev = output->mode_dev;
struct drm_psb_private *dev_priv = dev->dev_private;
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;

if (!gma_power_begin(dev, true))
return;
Expand All @@ -450,22 +453,22 @@ static void psb_intel_lvds_prepare(struct drm_encoder *encoder)
mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
BACKLIGHT_DUTY_CYCLE_MASK);

psb_intel_lvds_set_power(dev, output, false);
psb_intel_lvds_set_power(dev, false);

gma_power_end(dev);
}

static void psb_intel_lvds_commit(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
struct psb_intel_mode_device *mode_dev = output->mode_dev;
struct drm_psb_private *dev_priv = dev->dev_private;
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;

if (mode_dev->backlight_duty_cycle == 0)
mode_dev->backlight_duty_cycle =
psb_intel_lvds_get_max_backlight(dev);

psb_intel_lvds_set_power(dev, output, true);
psb_intel_lvds_set_power(dev, true);
}

static void psb_intel_lvds_mode_set(struct drm_encoder *encoder,
Expand Down Expand Up @@ -520,14 +523,15 @@ static enum drm_connector_status psb_intel_lvds_detect(struct drm_connector
static int psb_intel_lvds_get_modes(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct psb_intel_output *psb_intel_output =
to_psb_intel_output(connector);
struct psb_intel_mode_device *mode_dev =
psb_intel_output->mode_dev;
struct drm_psb_private *dev_priv = dev->dev_private;
struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
struct psb_intel_encoder *psb_intel_encoder =
psb_intel_attached_encoder(connector);
struct psb_intel_lvds_priv *lvds_priv = psb_intel_encoder->dev_priv;
int ret = 0;

if (!IS_MRST(dev))
ret = psb_intel_ddc_get_modes(psb_intel_output);
ret = psb_intel_ddc_get_modes(connector, &lvds_priv->i2c_bus->adapter);

if (ret)
return ret;
Expand Down Expand Up @@ -560,11 +564,12 @@ static int psb_intel_lvds_get_modes(struct drm_connector *connector)
*/
void psb_intel_lvds_destroy(struct drm_connector *connector)
{
struct psb_intel_output *psb_intel_output =
to_psb_intel_output(connector);
struct psb_intel_encoder *psb_intel_encoder =
psb_intel_attached_encoder(connector);
struct psb_intel_lvds_priv *lvds_priv = psb_intel_encoder->dev_priv;

if (psb_intel_output->ddc_bus)
psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
if (lvds_priv->ddc_bus)
psb_intel_i2c_destroy(lvds_priv->ddc_bus);
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
kfree(connector);
Expand Down Expand Up @@ -693,9 +698,10 @@ const struct drm_encoder_funcs psb_intel_lvds_enc_funcs = {
* modes we can display on the LVDS panel (if present).
*/
void psb_intel_lvds_init(struct drm_device *dev,
struct psb_intel_mode_device *mode_dev)
struct psb_intel_mode_device *mode_dev)
{
struct psb_intel_output *psb_intel_output;
struct psb_intel_encoder *psb_intel_encoder;
struct psb_intel_connector *psb_intel_connector;
struct psb_intel_lvds_priv *lvds_priv;
struct drm_connector *connector;
struct drm_encoder *encoder;
Expand All @@ -705,33 +711,43 @@ void psb_intel_lvds_init(struct drm_device *dev,
u32 lvds;
int pipe;

psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
if (!psb_intel_output)
psb_intel_encoder =
kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL);

if (!psb_intel_encoder) {
dev_err(dev->dev, "psb_intel_encoder allocation error\n");
return;
}

psb_intel_connector =
kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL);

if (!psb_intel_connector) {
kfree(psb_intel_encoder);
dev_err(dev->dev, "psb_intel_connector allocation error\n");
}

lvds_priv = kzalloc(sizeof(struct psb_intel_lvds_priv), GFP_KERNEL);
if (!lvds_priv) {
kfree(psb_intel_output);
dev_err(dev->dev, "LVDS private allocation error\n");
return;
goto failed_connector;
}

psb_intel_output->dev_priv = lvds_priv;
psb_intel_output->mode_dev = mode_dev;
psb_intel_encoder->dev_priv = lvds_priv;

connector = &psb_intel_output->base;
encoder = &psb_intel_output->enc;
drm_connector_init(dev, &psb_intel_output->base,
connector = &psb_intel_connector->base;
encoder = &psb_intel_encoder->base;
drm_connector_init(dev, connector,
&psb_intel_lvds_connector_funcs,
DRM_MODE_CONNECTOR_LVDS);

drm_encoder_init(dev, &psb_intel_output->enc,
drm_encoder_init(dev, encoder,
&psb_intel_lvds_enc_funcs,
DRM_MODE_ENCODER_LVDS);

drm_mode_connector_attach_encoder(&psb_intel_output->base,
&psb_intel_output->enc);
psb_intel_output->type = INTEL_OUTPUT_LVDS;
psb_intel_connector_attach_encoder(psb_intel_connector,
psb_intel_encoder);
psb_intel_encoder->type = INTEL_OUTPUT_LVDS;

drm_encoder_helper_add(encoder, &psb_intel_lvds_helper_funcs);
drm_connector_helper_add(connector,
Expand All @@ -752,16 +768,14 @@ void psb_intel_lvds_init(struct drm_device *dev,
* Set up I2C bus
* FIXME: distroy i2c_bus when exit
*/
psb_intel_output->i2c_bus = psb_intel_i2c_create(dev,
GPIOB,
"LVDSBLC_B");
if (!psb_intel_output->i2c_bus) {
lvds_priv->i2c_bus = psb_intel_i2c_create(dev, GPIOB, "LVDSBLC_B");
if (!lvds_priv->i2c_bus) {
dev_printk(KERN_ERR,
&dev->pdev->dev, "I2C bus registration failed.\n");
goto failed_blc_i2c;
}
psb_intel_output->i2c_bus->slave_addr = 0x2C;
dev_priv->lvds_i2c_bus = psb_intel_output->i2c_bus;
lvds_priv->i2c_bus->slave_addr = 0x2C;
dev_priv->lvds_i2c_bus = lvds_priv->i2c_bus;

/*
* LVDS discovery:
Expand All @@ -774,10 +788,8 @@ void psb_intel_lvds_init(struct drm_device *dev,
*/

/* Set up the DDC bus. */
psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
GPIOC,
"LVDSDDC_C");
if (!psb_intel_output->ddc_bus) {
lvds_priv->ddc_bus = psb_intel_i2c_create(dev, GPIOC, "LVDSDDC_C");
if (!lvds_priv->ddc_bus) {
dev_printk(KERN_ERR, &dev->pdev->dev,
"DDC bus registration " "failed.\n");
goto failed_ddc;
Expand All @@ -787,7 +799,7 @@ void psb_intel_lvds_init(struct drm_device *dev,
* Attempt to get the fixed panel mode from DDC. Assume that the
* preferred mode is the right one.
*/
psb_intel_ddc_get_modes(psb_intel_output);
psb_intel_ddc_get_modes(connector, &lvds_priv->ddc_bus->adapter);
list_for_each_entry(scan, &connector->probed_modes, head) {
if (scan->type & DRM_MODE_TYPE_PREFERRED) {
mode_dev->panel_fixed_mode =
Expand Down Expand Up @@ -841,14 +853,16 @@ void psb_intel_lvds_init(struct drm_device *dev,
return;

failed_find:
if (psb_intel_output->ddc_bus)
psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
if (lvds_priv->ddc_bus)
psb_intel_i2c_destroy(lvds_priv->ddc_bus);
failed_ddc:
if (psb_intel_output->i2c_bus)
psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
if (lvds_priv->i2c_bus)
psb_intel_i2c_destroy(lvds_priv->i2c_bus);
failed_blc_i2c:
drm_encoder_cleanup(encoder);
drm_connector_cleanup(connector);
kfree(connector);
failed_connector:
if (psb_intel_connector)
kfree(psb_intel_connector);
}

0 comments on commit 9c8cee4

Please sign in to comment.