From 25e9dc69709afad2be8de4ac2ecd6015356936ca Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 8 Aug 2012 13:53:15 +0000 Subject: gma500: Fix incorrect SR issue when disabling CRTC already in disabled state Currently when trying to call the DPMS off again for one CRTC with DPMS off, it will firstly disable the SR and can't enable it again because of the incorrect check/logic. In such case the self refresh is still disabled although one CRTC pipe is active. This is wrong. Signed-off-by: Zhao Yakui [Ported to in kernel driver] Signed-off-by: Alan Cox Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/cdv_intel_display.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index a68509ba22a..5c3a3121ad1 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -791,7 +791,7 @@ static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode) case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: if (psb_intel_crtc->active) - return; + break; psb_intel_crtc->active = true; @@ -835,7 +835,6 @@ static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode) REG_WRITE(map->status, temp); REG_READ(map->status); - cdv_intel_update_watermark(dev, crtc); cdv_intel_crtc_load_lut(crtc); /* Give the overlay scaler a chance to enable @@ -845,7 +844,7 @@ static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode) break; case DRM_MODE_DPMS_OFF: if (!psb_intel_crtc->active) - return; + break; psb_intel_crtc->active = false; @@ -892,10 +891,10 @@ static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode) /* Wait for the clocks to turn off. */ udelay(150); - cdv_intel_update_watermark(dev, crtc); psb_intel_crtc->crtc_enable = false; break; } + cdv_intel_update_watermark(dev, crtc); /*Set FIFO Watermarks*/ REG_WRITE(DSPARB, 0x3F3E); } -- cgit v1.2.3-70-g09d2 From d66760962d75af12697d5197b3e97d51fe64169c Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 8 Aug 2012 13:53:48 +0000 Subject: gma500: Program the DPLL lane based on the selected digitial port Based on the spec, the CRT output doesn't use the lane. And the HDMI B output uses the Lane0/1 while the HDMI C output uses the Lane 2/3. But currently it will program all the four lanes for the CRT/HDMI. Signed-off-by: Zhao Yakui [Ported to the in-kernel driver] Signed-off-by: Alan Cox Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/cdv_intel_display.c | 82 +++++++++++++++++++----------- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 2 + drivers/gpu/drm/gma500/psb_intel_drv.h | 5 ++ 3 files changed, 58 insertions(+), 31 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index 5c3a3121ad1..f16169c95de 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -57,8 +57,14 @@ struct cdv_intel_clock_t { struct cdv_intel_limit_t { struct cdv_intel_range_t dot, vco, n, m, m1, m2, p, p1; struct cdv_intel_p2_t p2; + bool (*find_pll)(const struct cdv_intel_limit_t *, struct drm_crtc *, + int, int, struct cdv_intel_clock_t *); }; +static bool cdv_intel_find_best_PLL(const struct cdv_intel_limit_t *limit, + struct drm_crtc *crtc, int target, int refclk, + struct cdv_intel_clock_t *best_clock); + #define CDV_LIMIT_SINGLE_LVDS_96 0 #define CDV_LIMIT_SINGLE_LVDS_100 1 #define CDV_LIMIT_DAC_HDMI_27 2 @@ -76,6 +82,7 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = { .p1 = {.min = 2, .max = 10}, .p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14}, + .find_pll = cdv_intel_find_best_PLL, }, { /* CDV_SINGLE_LVDS_100MHz */ .dot = {.min = 20000, .max = 115500}, @@ -90,6 +97,7 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = { * is 80-224Mhz. Prefer single channel as much as possible. */ .p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14}, + .find_pll = cdv_intel_find_best_PLL, }, { /* CDV_DAC_HDMI_27MHz */ .dot = {.min = 20000, .max = 400000}, @@ -101,6 +109,7 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = { .p = {.min = 5, .max = 90}, .p1 = {.min = 1, .max = 9}, .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5}, + .find_pll = cdv_intel_find_best_PLL, }, { /* CDV_DAC_HDMI_96MHz */ .dot = {.min = 20000, .max = 400000}, @@ -112,6 +121,7 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = { .p = {.min = 5, .max = 100}, .p1 = {.min = 1, .max = 10}, .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5}, + .find_pll = cdv_intel_find_best_PLL, }, }; @@ -216,7 +226,7 @@ static void cdv_sb_reset(struct drm_device *dev) */ static int cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, - struct cdv_intel_clock_t *clock, bool is_lvds) + struct cdv_intel_clock_t *clock, bool is_lvds, u32 ddi_select) { struct psb_intel_crtc *psb_crtc = to_psb_intel_crtc(crtc); int pipe = psb_crtc->pipe; @@ -336,30 +346,33 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, if (ret) return ret; - lane_reg = PSB_LANE0; - cdv_sb_read(dev, lane_reg, &lane_value); - lane_value &= ~(LANE_PLL_MASK); - lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe); - cdv_sb_write(dev, lane_reg, lane_value); - - lane_reg = PSB_LANE1; - cdv_sb_read(dev, lane_reg, &lane_value); - lane_value &= ~(LANE_PLL_MASK); - lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe); - cdv_sb_write(dev, lane_reg, lane_value); - - lane_reg = PSB_LANE2; - cdv_sb_read(dev, lane_reg, &lane_value); - lane_value &= ~(LANE_PLL_MASK); - lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe); - cdv_sb_write(dev, lane_reg, lane_value); - - lane_reg = PSB_LANE3; - cdv_sb_read(dev, lane_reg, &lane_value); - lane_value &= ~(LANE_PLL_MASK); - lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe); - cdv_sb_write(dev, lane_reg, lane_value); - + if (ddi_select) { + if ((ddi_select & DDI_MASK) == DDI0_SELECT) { + lane_reg = PSB_LANE0; + cdv_sb_read(dev, lane_reg, &lane_value); + lane_value &= ~(LANE_PLL_MASK); + lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe); + cdv_sb_write(dev, lane_reg, lane_value); + + lane_reg = PSB_LANE1; + cdv_sb_read(dev, lane_reg, &lane_value); + lane_value &= ~(LANE_PLL_MASK); + lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe); + cdv_sb_write(dev, lane_reg, lane_value); + } else { + lane_reg = PSB_LANE2; + cdv_sb_read(dev, lane_reg, &lane_value); + lane_value &= ~(LANE_PLL_MASK); + lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe); + cdv_sb_write(dev, lane_reg, lane_value); + + lane_reg = PSB_LANE3; + cdv_sb_read(dev, lane_reg, &lane_value); + lane_value &= ~(LANE_PLL_MASK); + lane_value |= LANE_PLL_ENABLE | LANE_PLL_PIPE(pipe); + cdv_sb_write(dev, lane_reg, lane_value); + } + } return 0; } @@ -438,13 +451,12 @@ static bool cdv_intel_PLL_is_valid(struct drm_crtc *crtc, return true; } -static bool cdv_intel_find_best_PLL(struct drm_crtc *crtc, int target, - int refclk, - struct cdv_intel_clock_t *best_clock) +static bool cdv_intel_find_best_PLL(const struct cdv_intel_limit_t *limit, + struct drm_crtc *crtc, int target, int refclk, + struct cdv_intel_clock_t *best_clock) { struct drm_device *dev = crtc->dev; struct cdv_intel_clock_t clock; - const struct cdv_intel_limit_t *limit = cdv_intel_limit(crtc, refclk); int err = target; @@ -954,6 +966,8 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, bool is_hdmi = false; struct drm_mode_config *mode_config = &dev->mode_config; struct drm_connector *connector; + const struct cdv_intel_limit_t *limit; + u32 ddi_select = 0; list_for_each_entry(connector, &mode_config->connector_list, head) { struct psb_intel_encoder *psb_intel_encoder = @@ -963,6 +977,7 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, || connector->encoder->crtc != crtc) continue; + ddi_select = psb_intel_encoder->ddi_select; switch (psb_intel_encoder->type) { case INTEL_OUTPUT_LVDS: is_lvds = true; @@ -976,6 +991,9 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, case INTEL_OUTPUT_HDMI: is_hdmi = true; break; + default: + DRM_ERROR("invalid output type.\n"); + return 0; } } @@ -992,8 +1010,10 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, } drm_mode_debug_printmodeline(adjusted_mode); + + limit = cdv_intel_limit(crtc, refclk); - ok = cdv_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, + ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); if (!ok) { dev_err(dev->dev, "Couldn't find PLL settings for mode!\n"); @@ -1032,7 +1052,7 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, REG_WRITE(map->dpll, dpll | DPLL_VGA_MODE_DIS | DPLL_SYNCLOCK_ENABLE); REG_READ(map->dpll); - cdv_dpll_set_clock_cdv(dev, crtc, &clock, is_lvds); + cdv_dpll_set_clock_cdv(dev, crtc, &clock, is_lvds, ddi_select); udelay(150); diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c index a86f87b9ddd..0c90f0316db 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c @@ -352,9 +352,11 @@ void cdv_hdmi_init(struct drm_device *dev, switch (reg) { case SDVOB: ddc_bus = GPIOE; + psb_intel_encoder->ddi_select = DDI0_SELECT; break; case SDVOC: ddc_bus = GPIOD; + psb_intel_encoder->ddi_select = DDI1_SELECT; break; default: DRM_ERROR("unknown reg 0x%x for HDMI\n", reg); diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h index ebe1a28f60e..7b357b04d4e 100644 --- a/drivers/gpu/drm/gma500/psb_intel_drv.h +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h @@ -133,6 +133,11 @@ struct psb_intel_encoder { void (*hot_plug)(struct psb_intel_encoder *); int crtc_mask; int clone_mask; + u32 ddi_select; /* Channel info */ +#define DDI0_SELECT 0x01 +#define DDI1_SELECT 0x02 +#define DP_MASK 0x8000; +#define DDI_MASK 0x03 void *dev_priv; /* For sdvo_priv, lvds_priv, etc... */ /* FIXME: Either make SDVO and LVDS store it's i2c here or give CDV it's -- cgit v1.2.3-70-g09d2 From 8695b612943561478fd22f28f45e5692e5d078db Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 8 Aug 2012 13:54:15 +0000 Subject: gma500: Add the support of display port on CDV Import the pieces we need in order to do DisplayPort. Don't wire them up yet as there is work to do to integrate them. Signed-off-by: Zhao Yakui Signed-off-by: Alan Cox Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/cdv_intel_dp.c | 1504 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/gma500/psb_intel_drv.h | 6 +- drivers/gpu/drm/gma500/psb_intel_reg.h | 155 ++++ 3 files changed, 1661 insertions(+), 4 deletions(-) create mode 100644 drivers/gpu/drm/gma500/cdv_intel_dp.c (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c new file mode 100644 index 00000000000..c6d545d4292 --- /dev/null +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -0,0 +1,1504 @@ +/* + * Copyright © 2012 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: + * Keith Packard + * + */ + +#include +#include +#include "drmP.h" +#include "drm.h" +#include "drm_crtc.h" +#include "drm_crtc_helper.h" +#include "psb_drv.h" +#include "psb_intel_drv.h" +#include "psb_drm.h" +#include "psb_intel_reg.h" +#include "drm_dp_helper.h" + + +#define DP_LINK_STATUS_SIZE 6 +#define DP_LINK_CHECK_TIMEOUT (10 * 1000) + +#define DP_LINK_CONFIGURATION_SIZE 9 + +#define CDV_FAST_LINK_TRAIN 1 + +struct psb_intel_dp { + uint32_t output_reg; + uint32_t DP; + uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; + bool has_audio; + int force_audio; + uint32_t color_range; + uint8_t link_bw; + uint8_t lane_count; + uint8_t dpcd[4]; + struct psb_intel_output *output; + struct i2c_adapter adapter; + struct i2c_algo_dp_aux_data algo; + uint8_t train_set[4]; + uint8_t link_status[DP_LINK_STATUS_SIZE]; +}; + +struct ddi_regoff { + uint32_t PreEmph1; + uint32_t PreEmph2; + uint32_t VSwing1; + uint32_t VSwing2; + uint32_t VSwing3; + uint32_t VSwing4; + uint32_t VSwing5; +}; + +static struct ddi_regoff ddi_DP_train_table[] = { + {.PreEmph1 = 0x812c, .PreEmph2 = 0x8124, .VSwing1 = 0x8154, + .VSwing2 = 0x8148, .VSwing3 = 0x814C, .VSwing4 = 0x8150, + .VSwing5 = 0x8158,}, + {.PreEmph1 = 0x822c, .PreEmph2 = 0x8224, .VSwing1 = 0x8254, + .VSwing2 = 0x8248, .VSwing3 = 0x824C, .VSwing4 = 0x8250, + .VSwing5 = 0x8258,}, +}; + +static uint32_t dp_vswing_premph_table[] = { + 0x55338954, 0x4000, + 0x554d8954, 0x2000, + 0x55668954, 0, + 0x559ac0d4, 0x6000, +}; +/** + * is_edp - is the given port attached to an eDP panel (either CPU or PCH) + * @intel_dp: DP struct + * + * If a CPU or PCH DP output is attached to an eDP panel, this function + * will return true, and false otherwise. + */ +static bool is_edp(struct psb_intel_output *output) +{ + return output->type == INTEL_OUTPUT_EDP; +} + + +static void psb_intel_dp_start_link_train(struct psb_intel_output *output); +static void psb_intel_dp_complete_link_train(struct psb_intel_output *output); +static void psb_intel_dp_link_down(struct psb_intel_output *output); + +static int +psb_intel_dp_max_lane_count(struct psb_intel_output *output) +{ + struct psb_intel_dp *intel_dp = output->dev_priv; + int max_lane_count = 4; + + if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) { + max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f; + switch (max_lane_count) { + case 1: case 2: case 4: + break; + default: + max_lane_count = 4; + } + } + return max_lane_count; +} + +static int +psb_intel_dp_max_link_bw(struct psb_intel_output *output) +{ + struct psb_intel_dp *intel_dp = output->dev_priv; + int max_link_bw = intel_dp->dpcd[DP_MAX_LINK_RATE]; + + switch (max_link_bw) { + case DP_LINK_BW_1_62: + case DP_LINK_BW_2_7: + break; + default: + max_link_bw = DP_LINK_BW_1_62; + break; + } + return max_link_bw; +} + +static int +psb_intel_dp_link_clock(uint8_t link_bw) +{ + if (link_bw == DP_LINK_BW_2_7) + return 270000; + else + return 162000; +} + +static int +psb_intel_dp_link_required(int pixel_clock, int bpp) +{ + return (pixel_clock * bpp + 7) / 8; +} + +static int +psb_intel_dp_max_data_rate(int max_link_clock, int max_lanes) +{ + return (max_link_clock * max_lanes * 19) / 20; +} + +static int +psb_intel_dp_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + struct psb_intel_output *output = to_psb_intel_output(connector); + struct drm_device *dev = connector->dev; + struct drm_psb_private *dev_priv = dev->dev_private; + int max_link_clock = psb_intel_dp_link_clock(psb_intel_dp_max_link_bw(output)); + int max_lanes = psb_intel_dp_max_lane_count(output); + + if (is_edp(output) && dev_priv->panel_fixed_mode) { + if (mode->hdisplay > dev_priv->panel_fixed_mode->hdisplay) + return MODE_PANEL; + + if (mode->vdisplay > dev_priv->panel_fixed_mode->vdisplay) + return MODE_PANEL; + } + + /* only refuse the mode on non eDP since we have seen some weird eDP panels + which are outside spec tolerances but somehow work by magic */ + if (!is_edp(output) && + (psb_intel_dp_link_required(mode->clock, 24) + > psb_intel_dp_max_data_rate(max_link_clock, max_lanes))) + return MODE_CLOCK_HIGH; + + if (mode->clock < 10000) + return MODE_CLOCK_LOW; + + return MODE_OK; +} + +static uint32_t +pack_aux(uint8_t *src, int src_bytes) +{ + int i; + uint32_t v = 0; + + if (src_bytes > 4) + src_bytes = 4; + for (i = 0; i < src_bytes; i++) + v |= ((uint32_t) src[i]) << ((3-i) * 8); + return v; +} + +static void +unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) +{ + int i; + if (dst_bytes > 4) + dst_bytes = 4; + for (i = 0; i < dst_bytes; i++) + dst[i] = src >> ((3-i) * 8); +} + +static int +psb_intel_dp_aux_ch(struct psb_intel_output *output, + uint8_t *send, int send_bytes, + uint8_t *recv, int recv_size) +{ + struct psb_intel_dp *intel_dp = output->dev_priv; + uint32_t output_reg = intel_dp->output_reg; + struct drm_device *dev = output->base.dev; + uint32_t ch_ctl = output_reg + 0x10; + uint32_t ch_data = ch_ctl + 4; + int i; + int recv_bytes; + uint32_t status; + uint32_t aux_clock_divider; + int try, precharge; + + /* The clock divider is based off the hrawclk, + * and would like to run at 2MHz. So, take the + * hrawclk value and divide by 2 and use that + * On CDV platform it uses 200MHz as hrawclk. + * + */ + aux_clock_divider = 200 / 2; + + precharge = 4; + + if (REG_READ(ch_ctl) & DP_AUX_CH_CTL_SEND_BUSY) { + DRM_ERROR("dp_aux_ch not started status 0x%08x\n", + REG_READ(ch_ctl)); + return -EBUSY; + } + + /* Must try at least 3 times according to DP spec */ + for (try = 0; try < 5; try++) { + /* Load the send data into the aux channel data registers */ + for (i = 0; i < send_bytes; i += 4) + REG_WRITE(ch_data + i, + pack_aux(send + i, send_bytes - i)); + + /* Send the command and wait for it to complete */ + REG_WRITE(ch_ctl, + DP_AUX_CH_CTL_SEND_BUSY | + DP_AUX_CH_CTL_TIME_OUT_400us | + (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | + (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | + (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | + DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR); + for (;;) { + status = REG_READ(ch_ctl); + if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) + break; + udelay(100); + } + + /* Clear done status and any errors */ + REG_WRITE(ch_ctl, + status | + DP_AUX_CH_CTL_DONE | + DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR); + if (status & DP_AUX_CH_CTL_DONE) + break; + } + + if ((status & DP_AUX_CH_CTL_DONE) == 0) { + DRM_ERROR("dp_aux_ch not done status 0x%08x\n", status); + return -EBUSY; + } + + /* Check for timeout or receive error. + * Timeouts occur when the sink is not connected + */ + if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { + DRM_ERROR("dp_aux_ch receive error status 0x%08x\n", status); + return -EIO; + } + + /* Timeouts occur when the device isn't connected, so they're + * "normal" -- don't fill the kernel log with these */ + if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) { + DRM_DEBUG_KMS("dp_aux_ch timeout status 0x%08x\n", status); + return -ETIMEDOUT; + } + + /* Unload any bytes sent back from the other side */ + recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> + DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); + if (recv_bytes > recv_size) + recv_bytes = recv_size; + + for (i = 0; i < recv_bytes; i += 4) + unpack_aux(REG_READ(ch_data + i), + recv + i, recv_bytes - i); + + return recv_bytes; +} + +/* Write data to the aux channel in native mode */ +static int +psb_intel_dp_aux_native_write(struct psb_intel_output *output, + uint16_t address, uint8_t *send, int send_bytes) +{ + int ret; + uint8_t msg[20]; + int msg_bytes; + uint8_t ack; + + if (send_bytes > 16) + return -1; + msg[0] = AUX_NATIVE_WRITE << 4; + msg[1] = address >> 8; + msg[2] = address & 0xff; + msg[3] = send_bytes - 1; + memcpy(&msg[4], send, send_bytes); + msg_bytes = send_bytes + 4; + for (;;) { + ret = psb_intel_dp_aux_ch(output, msg, msg_bytes, &ack, 1); + if (ret < 0) + return ret; + if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) + break; + else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) + udelay(100); + else + return -EIO; + } + return send_bytes; +} + +/* Write a single byte to the aux channel in native mode */ +static int +psb_intel_dp_aux_native_write_1(struct psb_intel_output *output, + uint16_t address, uint8_t byte) +{ + return psb_intel_dp_aux_native_write(output, address, &byte, 1); +} + +/* read bytes from a native aux channel */ +static int +psb_intel_dp_aux_native_read(struct psb_intel_output *output, + uint16_t address, uint8_t *recv, int recv_bytes) +{ + uint8_t msg[4]; + int msg_bytes; + uint8_t reply[20]; + int reply_bytes; + uint8_t ack; + int ret; + + msg[0] = AUX_NATIVE_READ << 4; + msg[1] = address >> 8; + msg[2] = address & 0xff; + msg[3] = recv_bytes - 1; + + msg_bytes = 4; + reply_bytes = recv_bytes + 1; + + for (;;) { + ret = psb_intel_dp_aux_ch(output, msg, msg_bytes, + reply, reply_bytes); + if (ret == 0) + return -EPROTO; + if (ret < 0) + return ret; + ack = reply[0]; + if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) { + memcpy(recv, reply + 1, ret - 1); + return ret - 1; + } + else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) + udelay(100); + else + return -EIO; + } +} + +static int +psb_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, + uint8_t write_byte, uint8_t *read_byte) +{ + struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; + struct psb_intel_dp *intel_dp = container_of(adapter, + struct psb_intel_dp, + adapter); + struct psb_intel_output *output = intel_dp->output; + uint16_t address = algo_data->address; + uint8_t msg[5]; + uint8_t reply[2]; + unsigned retry; + int msg_bytes; + int reply_bytes; + int ret; + + /* Set up the command byte */ + if (mode & MODE_I2C_READ) + msg[0] = AUX_I2C_READ << 4; + else + msg[0] = AUX_I2C_WRITE << 4; + + if (!(mode & MODE_I2C_STOP)) + msg[0] |= AUX_I2C_MOT << 4; + + msg[1] = address >> 8; + msg[2] = address; + + switch (mode) { + case MODE_I2C_WRITE: + msg[3] = 0; + msg[4] = write_byte; + msg_bytes = 5; + reply_bytes = 1; + break; + case MODE_I2C_READ: + msg[3] = 0; + msg_bytes = 4; + reply_bytes = 2; + break; + default: + msg_bytes = 3; + reply_bytes = 1; + break; + } + + for (retry = 0; retry < 5; retry++) { + ret = psb_intel_dp_aux_ch(output, + msg, msg_bytes, + reply, reply_bytes); + if (ret < 0) { + DRM_DEBUG_KMS("aux_ch failed %d\n", ret); + return ret; + } + + switch (reply[0] & AUX_NATIVE_REPLY_MASK) { + case AUX_NATIVE_REPLY_ACK: + /* I2C-over-AUX Reply field is only valid + * when paired with AUX ACK. + */ + break; + case AUX_NATIVE_REPLY_NACK: + DRM_DEBUG_KMS("aux_ch native nack\n"); + return -EREMOTEIO; + case AUX_NATIVE_REPLY_DEFER: + udelay(100); + continue; + default: + DRM_ERROR("aux_ch invalid native reply 0x%02x\n", + reply[0]); + return -EREMOTEIO; + } + + switch (reply[0] & AUX_I2C_REPLY_MASK) { + case AUX_I2C_REPLY_ACK: + if (mode == MODE_I2C_READ) { + *read_byte = reply[1]; + } + return reply_bytes - 1; + case AUX_I2C_REPLY_NACK: + DRM_DEBUG_KMS("aux_i2c nack\n"); + return -EREMOTEIO; + case AUX_I2C_REPLY_DEFER: + DRM_DEBUG_KMS("aux_i2c defer\n"); + udelay(100); + break; + default: + DRM_ERROR("aux_i2c invalid reply 0x%02x\n", reply[0]); + return -EREMOTEIO; + } + } + + DRM_ERROR("too many retries, giving up\n"); + return -EREMOTEIO; +} + +static int +psb_intel_dp_i2c_init(struct psb_intel_output *output, const char *name) +{ + struct psb_intel_dp *intel_dp = output->dev_priv; + DRM_DEBUG_KMS("i2c_init %s\n", name); + intel_dp->algo.running = false; + intel_dp->algo.address = 0; + intel_dp->algo.aux_ch = psb_intel_dp_i2c_aux_ch; + + memset(&intel_dp->adapter, '\0', sizeof (intel_dp->adapter)); + intel_dp->adapter.owner = THIS_MODULE; + intel_dp->adapter.class = I2C_CLASS_DDC; + strncpy (intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1); + intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0'; + intel_dp->adapter.algo_data = &intel_dp->algo; + intel_dp->adapter.dev.parent = &output->base.kdev; + + return i2c_dp_aux_add_bus(&intel_dp->adapter); +} + +static bool +psb_intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct psb_intel_output *output = enc_to_psb_intel_output(encoder); + struct psb_intel_dp *intel_dp = output->dev_priv; + int lane_count, clock; + int max_lane_count = psb_intel_dp_max_lane_count(output); + int max_clock = psb_intel_dp_max_link_bw(output) == DP_LINK_BW_2_7 ? 1 : 0; + static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; + + + for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { + for (clock = max_clock; clock >= 0; clock--) { + int link_avail = psb_intel_dp_max_data_rate(psb_intel_dp_link_clock(bws[clock]), lane_count); + + if (psb_intel_dp_link_required(mode->clock, 24) + <= link_avail) { + intel_dp->link_bw = bws[clock]; + intel_dp->lane_count = lane_count; + adjusted_mode->clock = psb_intel_dp_link_clock(intel_dp->link_bw); + DRM_DEBUG_KMS("Display port link bw %02x lane " + "count %d clock %d\n", + intel_dp->link_bw, intel_dp->lane_count, + adjusted_mode->clock); + return true; + } + } + } + + return false; +} + +struct psb_intel_dp_m_n { + uint32_t tu; + uint32_t gmch_m; + uint32_t gmch_n; + uint32_t link_m; + uint32_t link_n; +}; + +static void +psb_intel_reduce_ratio(uint32_t *num, uint32_t *den) +{ + /* + while (*num > 0xffffff || *den > 0xffffff) { + *num >>= 1; + *den >>= 1; + }*/ + uint64_t value, m; + m = *num; + value = m * (0x800000); + m = do_div(value, *den); + *num = value; + *den = 0x800000; +} + +static void +psb_intel_dp_compute_m_n(int bpp, + int nlanes, + int pixel_clock, + int link_clock, + struct psb_intel_dp_m_n *m_n) +{ + m_n->tu = 64; + m_n->gmch_m = (pixel_clock * bpp + 7) >> 3; + m_n->gmch_n = link_clock * nlanes; + psb_intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); + m_n->link_m = pixel_clock; + m_n->link_n = link_clock; + psb_intel_reduce_ratio(&m_n->link_m, &m_n->link_n); +} + +void +psb_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct drm_device *dev = crtc->dev; + struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_encoder *encoder; + struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); + int lane_count = 4, bpp = 24; + struct psb_intel_dp_m_n m_n; + int pipe = intel_crtc->pipe; + + /* + * Find the lane count in the intel_encoder private + */ + list_for_each_entry(encoder, &mode_config->encoder_list, head) { + struct psb_intel_output *intel_output; + struct psb_intel_dp *intel_dp; + + if (encoder->crtc != crtc) + continue; + + intel_output = enc_to_psb_intel_output(encoder); + intel_dp = intel_output->dev_priv; + if (intel_output->type == INTEL_OUTPUT_DISPLAYPORT) { + lane_count = intel_dp->lane_count; + break; + } else if (is_edp(intel_output)) { + lane_count = intel_dp->lane_count; + break; + } + } + + /* + * Compute the GMCH and Link ratios. The '3' here is + * the number of bytes_per_pixel post-LUT, which we always + * set up for 8-bits of R/G/B, or 3 bytes total. + */ + psb_intel_dp_compute_m_n(bpp, lane_count, + mode->clock, adjusted_mode->clock, &m_n); + + { + REG_WRITE(PIPE_GMCH_DATA_M(pipe), + ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | + m_n.gmch_m); + REG_WRITE(PIPE_GMCH_DATA_N(pipe), m_n.gmch_n); + REG_WRITE(PIPE_DP_LINK_M(pipe), m_n.link_m); + REG_WRITE(PIPE_DP_LINK_N(pipe), m_n.link_n); + } +} + +static void +psb_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct psb_intel_output *intel_output = enc_to_psb_intel_output(encoder); + struct drm_crtc *crtc = encoder->crtc; + struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); + struct psb_intel_dp *intel_dp = intel_output->dev_priv; + + + intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; + intel_dp->DP |= intel_dp->color_range; + + if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) + intel_dp->DP |= DP_SYNC_HS_HIGH; + if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) + intel_dp->DP |= DP_SYNC_VS_HIGH; + + intel_dp->DP |= DP_LINK_TRAIN_OFF; + + switch (intel_dp->lane_count) { + case 1: + intel_dp->DP |= DP_PORT_WIDTH_1; + break; + case 2: + intel_dp->DP |= DP_PORT_WIDTH_2; + break; + case 4: + intel_dp->DP |= DP_PORT_WIDTH_4; + break; + } + if (intel_dp->has_audio) + intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE; + + memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); + intel_dp->link_configuration[0] = intel_dp->link_bw; + intel_dp->link_configuration[1] = intel_dp->lane_count; + + /* + * Check for DPCD version > 1.1 and enhanced framing support + */ + if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 && + (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) { + intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; + intel_dp->DP |= DP_ENHANCED_FRAMING; + } + + /* CPT DP's pipe select is decided in TRANS_DP_CTL */ + if (intel_crtc->pipe == 1) + intel_dp->DP |= DP_PIPEB_SELECT; + + DRM_DEBUG_KMS("DP expected reg is %x\n", intel_dp->DP); +} + + +/* If the sink supports it, try to set the power state appropriately */ +static void psb_intel_dp_sink_dpms(struct psb_intel_output *output, int mode) +{ + struct psb_intel_dp *intel_dp = output->dev_priv; + int ret, i; + + /* Should have a valid DPCD by this point */ + if (intel_dp->dpcd[DP_DPCD_REV] < 0x11) + return; + + if (mode != DRM_MODE_DPMS_ON) { + ret = psb_intel_dp_aux_native_write_1(output, DP_SET_POWER, + DP_SET_POWER_D3); + if (ret != 1) + DRM_DEBUG_DRIVER("failed to write sink power state\n"); + } else { + /* + * When turning on, we need to retry for 1ms to give the sink + * time to wake up. + */ + for (i = 0; i < 3; i++) { + ret = psb_intel_dp_aux_native_write_1(output, + DP_SET_POWER, + DP_SET_POWER_D0); + if (ret == 1) + break; + udelay(1000); + } + } +} + +static void psb_intel_dp_prepare(struct drm_encoder *encoder) +{ + struct psb_intel_output *output = enc_to_psb_intel_output(encoder); + + /* Wake up the sink first */ + psb_intel_dp_sink_dpms(output, DRM_MODE_DPMS_ON); + + psb_intel_dp_link_down(output); +} + +static void psb_intel_dp_commit(struct drm_encoder *encoder) +{ + struct psb_intel_output *output = enc_to_psb_intel_output(encoder); + + psb_intel_dp_start_link_train(output); + + psb_intel_dp_complete_link_train(output); + +} + +static void +psb_intel_dp_dpms(struct drm_encoder *encoder, int mode) +{ + struct psb_intel_output *intel_output = enc_to_psb_intel_output(encoder); + struct psb_intel_dp *intel_dp = intel_output->dev_priv; + struct drm_device *dev = encoder->dev; + uint32_t dp_reg = REG_READ(intel_dp->output_reg); + + if (mode != DRM_MODE_DPMS_ON) { + psb_intel_dp_sink_dpms(intel_output, mode); + psb_intel_dp_link_down(intel_output); + } else { + psb_intel_dp_sink_dpms(intel_output, mode); + if (!(dp_reg & DP_PORT_EN)) { + psb_intel_dp_start_link_train(intel_output); + psb_intel_dp_complete_link_train(intel_output); + } + } +} + +/* + * Native read with retry for link status and receiver capability reads for + * cases where the sink may still be asleep. + */ +static bool +psb_intel_dp_aux_native_read_retry(struct psb_intel_output *output, uint16_t address, + uint8_t *recv, int recv_bytes) +{ + int ret, i; + + /* + * Sinks are *supposed* to come up within 1ms from an off state, + * but we're also supposed to retry 3 times per the spec. + */ + for (i = 0; i < 3; i++) { + ret = psb_intel_dp_aux_native_read(output, address, recv, + recv_bytes); + if (ret == recv_bytes) + return true; + udelay(1000); + } + + return false; +} + +/* + * Fetch AUX CH registers 0x202 - 0x207 which contain + * link status information + */ +static bool +psb_intel_dp_get_link_status(struct psb_intel_output *output) +{ + struct psb_intel_dp *intel_dp = output->dev_priv; + return psb_intel_dp_aux_native_read_retry(output, + DP_LANE0_1_STATUS, + intel_dp->link_status, + DP_LINK_STATUS_SIZE); +} + +static uint8_t +psb_intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE], + int r) +{ + return link_status[r - DP_LANE0_1_STATUS]; +} + +static uint8_t +psb_intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE], + int lane) +{ + int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); + int s = ((lane & 1) ? + DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : + DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); + uint8_t l = psb_intel_dp_link_status(link_status, i); + + return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; +} + +static uint8_t +psb_intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE], + int lane) +{ + int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); + int s = ((lane & 1) ? + DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT : + DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); + uint8_t l = psb_intel_dp_link_status(link_status, i); + + return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; +} + + +#if 0 +static char *voltage_names[] = { + "0.4V", "0.6V", "0.8V", "1.2V" +}; +static char *pre_emph_names[] = { + "0dB", "3.5dB", "6dB", "9.5dB" +}; +static char *link_train_names[] = { + "pattern 1", "pattern 2", "idle", "off" +}; +#endif + +#define CDV_DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 +/* +static uint8_t +psb_intel_dp_pre_emphasis_max(uint8_t voltage_swing) +{ + switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { + case DP_TRAIN_VOLTAGE_SWING_400: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_600: + return DP_TRAIN_PRE_EMPHASIS_6; + case DP_TRAIN_VOLTAGE_SWING_800: + return DP_TRAIN_PRE_EMPHASIS_3_5; + case DP_TRAIN_VOLTAGE_SWING_1200: + default: + return DP_TRAIN_PRE_EMPHASIS_0; + } +} +*/ +static void +psb_intel_get_adjust_train(struct psb_intel_output *output) +{ + struct psb_intel_dp *intel_dp = output->dev_priv; + uint8_t v = 0; + uint8_t p = 0; + int lane; + + for (lane = 0; lane < intel_dp->lane_count; lane++) { + uint8_t this_v = psb_intel_get_adjust_request_voltage(intel_dp->link_status, lane); + uint8_t this_p = psb_intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane); + + if (this_v > v) + v = this_v; + if (this_p > p) + p = this_p; + } + + if (v >= CDV_DP_VOLTAGE_MAX) + v = CDV_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED; + + if (p == DP_TRAIN_PRE_EMPHASIS_MASK) + p |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; + + for (lane = 0; lane < 4; lane++) + intel_dp->train_set[lane] = v | p; +} + + +static uint8_t +psb_intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], + int lane) +{ + int i = DP_LANE0_1_STATUS + (lane >> 1); + int s = (lane & 1) * 4; + uint8_t l = psb_intel_dp_link_status(link_status, i); + + return (l >> s) & 0xf; +} + +/* Check for clock recovery is done on all channels */ +static bool +psb_intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) +{ + int lane; + uint8_t lane_status; + + for (lane = 0; lane < lane_count; lane++) { + lane_status = psb_intel_get_lane_status(link_status, lane); + if ((lane_status & DP_LANE_CR_DONE) == 0) + return false; + } + return true; +} + +/* Check to see if channel eq is done on all channels */ +#define CHANNEL_EQ_BITS (DP_LANE_CR_DONE|\ + DP_LANE_CHANNEL_EQ_DONE|\ + DP_LANE_SYMBOL_LOCKED) +static bool +psb_intel_channel_eq_ok(struct psb_intel_output *output) +{ + struct psb_intel_dp *intel_dp = output->dev_priv; + uint8_t lane_align; + uint8_t lane_status; + int lane; + + lane_align = psb_intel_dp_link_status(intel_dp->link_status, + DP_LANE_ALIGN_STATUS_UPDATED); + if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) + return false; + for (lane = 0; lane < intel_dp->lane_count; lane++) { + lane_status = psb_intel_get_lane_status(intel_dp->link_status, lane); + if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS) + return false; + } + return true; +} + +static bool +psb_intel_dp_set_link_train(struct psb_intel_output *output, + uint32_t dp_reg_value, + uint8_t dp_train_pat) +{ + + struct drm_device *dev = output->base.dev; + int ret; + struct psb_intel_dp *intel_dp = output->dev_priv; + + REG_WRITE(intel_dp->output_reg, dp_reg_value); + REG_READ(intel_dp->output_reg); + + ret = psb_intel_dp_aux_native_write_1(output, + DP_TRAINING_PATTERN_SET, + dp_train_pat); + + if (ret != 1) { + DRM_DEBUG_KMS("Failure in setting link pattern %x\n", + dp_train_pat); + return false; + } + + return true; +} + + +static bool +psb_intel_dplink_set_level(struct psb_intel_output *output, + uint8_t dp_train_pat) +{ + + int ret; + struct psb_intel_dp *intel_dp = output->dev_priv; + + ret = psb_intel_dp_aux_native_write(output, + DP_TRAINING_LANE0_SET, + intel_dp->train_set, + intel_dp->lane_count); + + if (ret != intel_dp->lane_count) { + DRM_DEBUG_KMS("Failure in setting level %d, lane_cnt= %d\n", + intel_dp->train_set[0], intel_dp->lane_count); + return false; + } + return true; +} + +static void +psb_intel_dp_set_vswing_premph(struct psb_intel_output *output, uint8_t signal_level) +{ + struct drm_device *dev = output->base.dev; + struct psb_intel_dp *intel_dp = output->dev_priv; + struct ddi_regoff *ddi_reg; + int vswing, premph, index; + + if (intel_dp->output_reg == DP_B) + ddi_reg = &ddi_DP_train_table[0]; + else + ddi_reg = &ddi_DP_train_table[1]; + + vswing = (signal_level & DP_TRAIN_VOLTAGE_SWING_MASK); + premph = ((signal_level & DP_TRAIN_PRE_EMPHASIS_MASK)) >> + DP_TRAIN_PRE_EMPHASIS_SHIFT; + + if (vswing + premph > 3) + return; +#ifdef CDV_FAST_LINK_TRAIN + return; +#endif + DRM_DEBUG_KMS("Test2\n"); + //return ; + psb_sb_reset(dev); + /* ;Swing voltage programming + ;gfx_dpio_set_reg(0xc058, 0x0505313A) */ + psb_sb_write(dev, ddi_reg->VSwing5, 0x0505313A); + + /* ;gfx_dpio_set_reg(0x8154, 0x43406055) */ + psb_sb_write(dev, ddi_reg->VSwing1, 0x43406055); + + /* ;gfx_dpio_set_reg(0x8148, 0x55338954) + * The VSwing_PreEmph table is also considered based on the vswing/premp + */ + index = (vswing + premph) * 2; + if (premph == 1 && vswing == 1) { + psb_sb_write(dev, ddi_reg->VSwing2, 0x055738954); + } else + psb_sb_write(dev, ddi_reg->VSwing2, dp_vswing_premph_table[index]); + + /* ;gfx_dpio_set_reg(0x814c, 0x40802040) */ + if ((vswing + premph) == DP_TRAIN_VOLTAGE_SWING_1200) + psb_sb_write(dev, ddi_reg->VSwing3, 0x70802040); + else + psb_sb_write(dev, ddi_reg->VSwing3, 0x40802040); + + /* ;gfx_dpio_set_reg(0x8150, 0x2b405555) */ + //psb_sb_write(dev, ddi_reg->VSwing4, 0x2b405555); + + /* ;gfx_dpio_set_reg(0x8154, 0xc3406055) */ + psb_sb_write(dev, ddi_reg->VSwing1, 0xc3406055); + + /* ;Pre emphasis programming + * ;gfx_dpio_set_reg(0xc02c, 0x1f030040) + */ + psb_sb_write(dev, ddi_reg->PreEmph1, 0x1f030040); + + /* ;gfx_dpio_set_reg(0x8124, 0x00004000) */ + index = 2 * premph + 1; + psb_sb_write(dev, ddi_reg->PreEmph2, dp_vswing_premph_table[index]); + return; +} + + +/* Enable corresponding port and start training pattern 1 */ +static void +psb_intel_dp_start_link_train(struct psb_intel_output *output) +{ + struct drm_device *dev = output->base.dev; + struct psb_intel_dp *intel_dp = output->dev_priv; + int i; + uint8_t voltage; + bool clock_recovery = false; + int tries; + u32 reg; + uint32_t DP = intel_dp->DP; + + DP |= DP_PORT_EN; + DP &= ~DP_LINK_TRAIN_MASK; + + reg = DP; + reg |= DP_LINK_TRAIN_PAT_1; + /* Enable output, wait for it to become active */ + REG_WRITE(intel_dp->output_reg, reg); + REG_READ(intel_dp->output_reg); + psb_intel_wait_for_vblank(dev); + + DRM_DEBUG_KMS("Link config\n"); + /* Write the link configuration data */ + psb_intel_dp_aux_native_write(output, DP_LINK_BW_SET, + intel_dp->link_configuration, + 2); + + memset(intel_dp->train_set, 0, 4); + voltage = 0; + tries = 0; + clock_recovery = false; + + DRM_DEBUG_KMS("Start train\n"); + reg = DP | DP_LINK_TRAIN_PAT_1; + + + for (;;) { + /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ + + if (!psb_intel_dp_set_link_train(output, reg, DP_TRAINING_PATTERN_1)) { + DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 1\n"); + } + psb_intel_dp_set_vswing_premph(output, intel_dp->train_set[0]); + /* Set training pattern 1 */ + + psb_intel_dplink_set_level(output, DP_TRAINING_PATTERN_1); + + udelay(200); + if (!psb_intel_dp_get_link_status(output)) + break; + + if (psb_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { + DRM_DEBUG_KMS("PT1 train is done\n"); + clock_recovery = true; + break; + } + + /* Check to see if we've tried the max voltage */ + for (i = 0; i < intel_dp->lane_count; i++) + if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) + break; + if (i == intel_dp->lane_count) + break; + + /* Check to see if we've tried the same voltage 5 times */ + if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { + ++tries; + if (tries == 5) + break; + } else + tries = 0; + voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; + + /* Compute new intel_dp->train_set as requested by target */ + psb_intel_get_adjust_train(output); + + } + + if (!clock_recovery) { + DRM_DEBUG_KMS("failure in DP patter 1 training, train set %x\n", intel_dp->train_set[0]); + } + + intel_dp->DP = DP; +} + +static void +psb_intel_dp_complete_link_train(struct psb_intel_output *output) +{ + struct drm_device *dev = output->base.dev; + struct psb_intel_dp *intel_dp = output->dev_priv; + bool channel_eq = false; + int tries, cr_tries; + u32 reg; + uint32_t DP = intel_dp->DP; + + /* channel equalization */ + tries = 0; + cr_tries = 0; + channel_eq = false; + + DRM_DEBUG_KMS("\n"); + reg = DP | DP_LINK_TRAIN_PAT_2; + + for (;;) { + /* channel eq pattern */ + if (!psb_intel_dp_set_link_train(output, reg, + DP_TRAINING_PATTERN_2)) { + DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 2\n"); + } + /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ + + if (cr_tries > 5) { + DRM_ERROR("failed to train DP, aborting\n"); + psb_intel_dp_link_down(output); + break; + } + + psb_intel_dp_set_vswing_premph(output, intel_dp->train_set[0]); + + psb_intel_dplink_set_level(output, DP_TRAINING_PATTERN_2); + + udelay(1000); + if (!psb_intel_dp_get_link_status(output)) + break; + + /* Make sure clock is still ok */ + if (!psb_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { + psb_intel_dp_start_link_train(output); + cr_tries++; + continue; + } + + if (psb_intel_channel_eq_ok(output)) { + DRM_DEBUG_KMS("PT2 train is done\n"); + channel_eq = true; + break; + } + + /* Try 5 times, then try clock recovery if that fails */ + if (tries > 5) { + psb_intel_dp_link_down(output); + psb_intel_dp_start_link_train(output); + tries = 0; + cr_tries++; + continue; + } + + /* Compute new intel_dp->train_set as requested by target */ + psb_intel_get_adjust_train(output); + ++tries; + + } + + reg = DP | DP_LINK_TRAIN_OFF; + + REG_WRITE(intel_dp->output_reg, reg); + REG_READ(intel_dp->output_reg); + psb_intel_dp_aux_native_write_1(output, + DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE); +} + +static void +psb_intel_dp_link_down(struct psb_intel_output *output) +{ + struct drm_device *dev = output->base.dev; + struct psb_intel_dp *intel_dp = output->dev_priv; + uint32_t DP = intel_dp->DP; + + if ((REG_READ(intel_dp->output_reg) & DP_PORT_EN) == 0) + return; + + DRM_DEBUG_KMS("\n"); + + + { + DP &= ~DP_LINK_TRAIN_MASK; + REG_WRITE(intel_dp->output_reg, DP | DP_LINK_TRAIN_PAT_IDLE); + } + REG_READ(intel_dp->output_reg); + + msleep(17); + + REG_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN); + REG_READ(intel_dp->output_reg); +} + +static enum drm_connector_status +cdv_dp_detect(struct psb_intel_output *output) +{ + struct psb_intel_dp *intel_dp = output->dev_priv; + enum drm_connector_status status; + + status = connector_status_disconnected; + if (psb_intel_dp_aux_native_read(output, 0x000, intel_dp->dpcd, + sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd)) + { + if (intel_dp->dpcd[DP_DPCD_REV] != 0) + status = connector_status_connected; + } + if (status == connector_status_connected) + DRM_DEBUG_KMS("DPCD: Rev=%x LN_Rate=%x LN_CNT=%x LN_DOWNSP=%x\n", + intel_dp->dpcd[0], intel_dp->dpcd[1], + intel_dp->dpcd[2], intel_dp->dpcd[3]); + return status; +} + +/** + * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection. + * + * \return true if DP port is connected. + * \return false if DP port is disconnected. + */ +static enum drm_connector_status +psb_intel_dp_detect(struct drm_connector *connector, bool force) +{ + struct psb_intel_output *output = to_psb_intel_output(connector); + struct psb_intel_dp *intel_dp = output->dev_priv; + enum drm_connector_status status; + struct edid *edid = NULL; + + intel_dp->has_audio = false; + + status = cdv_dp_detect(output); + if (status != connector_status_connected) + return status; + + if (intel_dp->force_audio) { + intel_dp->has_audio = intel_dp->force_audio > 0; + } else { + edid = drm_get_edid(connector, &intel_dp->adapter); + if (edid) { + intel_dp->has_audio = drm_detect_monitor_audio(edid); + connector->display_info.raw_edid = NULL; + kfree(edid); + } + } + + return connector_status_connected; +} + +static int psb_intel_dp_get_modes(struct drm_connector *connector) +{ + struct psb_intel_output *intel_output = to_psb_intel_output(connector); + struct psb_intel_dp *intel_dp = intel_output->dev_priv; + struct edid *edid = NULL; + int ret = 0; + + + edid = drm_get_edid(&intel_output->base, + &intel_dp->adapter); + if (edid) { + drm_mode_connector_update_edid_property(&intel_output-> + base, edid); + ret = drm_add_edid_modes(&intel_output->base, edid); + kfree(edid); + } + + return ret; +} + +static bool +psb_intel_dp_detect_audio(struct drm_connector *connector) +{ + struct psb_intel_output *output = to_psb_intel_output(connector); + struct psb_intel_dp *intel_dp = output->dev_priv; + struct edid *edid; + bool has_audio = false; + + edid = drm_get_edid(connector, &intel_dp->adapter); + if (edid) { + has_audio = drm_detect_monitor_audio(edid); + + connector->display_info.raw_edid = NULL; + kfree(edid); + } + + return has_audio; +} + +static int +psb_intel_dp_set_property(struct drm_connector *connector, + struct drm_property *property, + uint64_t val) +{ + struct drm_psb_private *dev_priv = connector->dev->dev_private; + struct psb_intel_output *output = to_psb_intel_output(connector); + struct psb_intel_dp *intel_dp = output->dev_priv; + int ret; + + ret = drm_connector_property_set_value(connector, property, val); + if (ret) + return ret; + + if (property == dev_priv->force_audio_property) { + int i = val; + bool has_audio; + + if (i == intel_dp->force_audio) + return 0; + + intel_dp->force_audio = i; + + if (i == 0) + has_audio = psb_intel_dp_detect_audio(connector); + else + has_audio = i > 0; + + if (has_audio == intel_dp->has_audio) + return 0; + + intel_dp->has_audio = has_audio; + goto done; + } + + if (property == dev_priv->broadcast_rgb_property) { + if (val == !!intel_dp->color_range) + return 0; + + intel_dp->color_range = val ? DP_COLOR_RANGE_16_235 : 0; + goto done; + } + + return -EINVAL; + +done: + if (output->enc.crtc) { + struct drm_crtc *crtc = output->enc.crtc; + drm_crtc_helper_set_mode(crtc, &crtc->mode, + crtc->x, crtc->y, + crtc->fb); + } + + return 0; +} + +static void +psb_intel_dp_destroy (struct drm_connector *connector) +{ + struct psb_intel_output *output = to_psb_intel_output(connector); + struct psb_intel_dp *intel_dp = output->dev_priv; + + i2c_del_adapter(&intel_dp->adapter); + drm_sysfs_connector_remove(connector); + drm_connector_cleanup(connector); + kfree(connector); +} + +static void psb_intel_dp_encoder_destroy(struct drm_encoder *encoder) +{ + drm_encoder_cleanup(encoder); +} + +static const struct drm_encoder_helper_funcs psb_intel_dp_helper_funcs = { + .dpms = psb_intel_dp_dpms, + .mode_fixup = psb_intel_dp_mode_fixup, + .prepare = psb_intel_dp_prepare, + .mode_set = psb_intel_dp_mode_set, + .commit = psb_intel_dp_commit, +}; + +static const struct drm_connector_funcs psb_intel_dp_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .detect = psb_intel_dp_detect, + .fill_modes = drm_helper_probe_single_connector_modes, + .set_property = psb_intel_dp_set_property, + .destroy = psb_intel_dp_destroy, +}; + +static const struct drm_connector_helper_funcs psb_intel_dp_connector_helper_funcs = { + .get_modes = psb_intel_dp_get_modes, + .mode_valid = psb_intel_dp_mode_valid, + .best_encoder = psb_intel_best_encoder, +}; + +static const struct drm_encoder_funcs psb_intel_dp_enc_funcs = { + .destroy = psb_intel_dp_encoder_destroy, +}; + + +static void +psb_intel_dp_add_properties(struct psb_intel_output *output, struct drm_connector *connector) +{ + psb_intel_attach_force_audio_property(connector); + psb_intel_attach_broadcast_rgb_property(connector); +} + +void +psb_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, int output_reg) +{ + struct drm_connector *connector; + struct drm_encoder *encoder; + struct psb_intel_output *psb_intel_output; + struct psb_intel_dp *intel_dp; + const char *name = NULL; + int type; + + psb_intel_output = kzalloc(sizeof(struct psb_intel_output) + + sizeof(struct psb_intel_dp), GFP_KERNEL); + if (!psb_intel_output) + return; + + intel_dp = (struct psb_intel_dp *)(psb_intel_output + 1); + psb_intel_output->mode_dev = mode_dev; + connector = &psb_intel_output->base; + encoder = &psb_intel_output->enc; + psb_intel_output->dev_priv=intel_dp; + intel_dp->output = psb_intel_output; + + intel_dp->output_reg = output_reg; + + type = DRM_MODE_CONNECTOR_DisplayPort; + psb_intel_output->type = INTEL_OUTPUT_DISPLAYPORT; + + drm_connector_init(dev, connector, &psb_intel_dp_connector_funcs, type); + drm_connector_helper_add(connector, &psb_intel_dp_connector_helper_funcs); + + connector->polled = DRM_CONNECTOR_POLL_HPD; + + connector->interlace_allowed = 0; + connector->doublescan_allowed = 0; + + drm_encoder_init(dev, encoder, &psb_intel_dp_enc_funcs, + DRM_MODE_ENCODER_TMDS); + drm_encoder_helper_add(encoder, &psb_intel_dp_helper_funcs); + + drm_mode_connector_attach_encoder(&psb_intel_output->base, + &psb_intel_output->enc); + + drm_sysfs_connector_add(connector); + + /* Set up the DDC bus. */ + switch (output_reg) { + case DP_B: + name = "DPDDC-B"; + psb_intel_output->ddi_select = (DP_MASK | DDI0_SELECT); + break; + case DP_C: + name = "DPDDC-C"; + psb_intel_output->ddi_select = (DP_MASK | DDI1_SELECT); + break; + } + + psb_intel_dp_i2c_init(psb_intel_output, name); + psb_intel_dp_add_properties(psb_intel_output, connector); + +} diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h index 7b357b04d4e..73214e281fa 100644 --- a/drivers/gpu/drm/gma500/psb_intel_drv.h +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h @@ -29,10 +29,6 @@ * Display related stuff */ -/* store information about an Ixxx DVO */ -/* The i830->i865 use multiple DVOs with multiple i2cs */ -/* the i915, i945 have a single sDVO i2c bus - which is different */ -#define MAX_OUTPUTS 6 /* maximum connectors per crtcs in the mode set */ #define INTELFB_CONN_LIMIT 4 @@ -69,6 +65,8 @@ #define INTEL_OUTPUT_HDMI 6 #define INTEL_OUTPUT_MIPI 7 #define INTEL_OUTPUT_MIPI2 8 +#define INTEL_OUTPUT_DISPLAYPORT 9 +#define INTEL_OUTPUT_EDP 10 #define INTEL_DVO_CHIP_NONE 0 #define INTEL_DVO_CHIP_LVDS 1 diff --git a/drivers/gpu/drm/gma500/psb_intel_reg.h b/drivers/gpu/drm/gma500/psb_intel_reg.h index 8e8c8efb0a8..d3091fc72b9 100644 --- a/drivers/gpu/drm/gma500/psb_intel_reg.h +++ b/drivers/gpu/drm/gma500/psb_intel_reg.h @@ -1347,5 +1347,160 @@ No status bits are changed. #define LANE_PLL_ENABLE (0x3 << 20) #define LANE_PLL_PIPE(p) (((p) == 0) ? (1 << 21) : (0 << 21)) +#define DP_B 0x64100 +#define DP_C 0x64200 + +#define DP_PORT_EN (1 << 31) +#define DP_PIPEB_SELECT (1 << 30) +#define DP_PIPE_MASK (1 << 30) + +/* Link training mode - select a suitable mode for each stage */ +#define DP_LINK_TRAIN_PAT_1 (0 << 28) +#define DP_LINK_TRAIN_PAT_2 (1 << 28) +#define DP_LINK_TRAIN_PAT_IDLE (2 << 28) +#define DP_LINK_TRAIN_OFF (3 << 28) +#define DP_LINK_TRAIN_MASK (3 << 28) +#define DP_LINK_TRAIN_SHIFT 28 + +/* Signal voltages. These are mostly controlled by the other end */ +#define DP_VOLTAGE_0_4 (0 << 25) +#define DP_VOLTAGE_0_6 (1 << 25) +#define DP_VOLTAGE_0_8 (2 << 25) +#define DP_VOLTAGE_1_2 (3 << 25) +#define DP_VOLTAGE_MASK (7 << 25) +#define DP_VOLTAGE_SHIFT 25 + +/* Signal pre-emphasis levels, like voltages, the other end tells us what + * they want + */ +#define DP_PRE_EMPHASIS_0 (0 << 22) +#define DP_PRE_EMPHASIS_3_5 (1 << 22) +#define DP_PRE_EMPHASIS_6 (2 << 22) +#define DP_PRE_EMPHASIS_9_5 (3 << 22) +#define DP_PRE_EMPHASIS_MASK (7 << 22) +#define DP_PRE_EMPHASIS_SHIFT 22 + +/* How many wires to use. I guess 3 was too hard */ +#define DP_PORT_WIDTH_1 (0 << 19) +#define DP_PORT_WIDTH_2 (1 << 19) +#define DP_PORT_WIDTH_4 (3 << 19) +#define DP_PORT_WIDTH_MASK (7 << 19) + +/* Mystic DPCD version 1.1 special mode */ +#define DP_ENHANCED_FRAMING (1 << 18) + +/** locked once port is enabled */ +#define DP_PORT_REVERSAL (1 << 15) + +/** sends the clock on lane 15 of the PEG for debug */ +#define DP_CLOCK_OUTPUT_ENABLE (1 << 13) + +#define DP_SCRAMBLING_DISABLE (1 << 12) +#define DP_SCRAMBLING_DISABLE_IRONLAKE (1 << 7) + +/** limit RGB values to avoid confusing TVs */ +#define DP_COLOR_RANGE_16_235 (1 << 8) + +/** Turn on the audio link */ +#define DP_AUDIO_OUTPUT_ENABLE (1 << 6) + +/** vs and hs sync polarity */ +#define DP_SYNC_VS_HIGH (1 << 4) +#define DP_SYNC_HS_HIGH (1 << 3) + +/** A fantasy */ +#define DP_DETECTED (1 << 2) + +/** The aux channel provides a way to talk to the + * signal sink for DDC etc. Max packet size supported + * is 20 bytes in each direction, hence the 5 fixed + * data registers + */ +#define DPB_AUX_CH_CTL 0x64110 +#define DPB_AUX_CH_DATA1 0x64114 +#define DPB_AUX_CH_DATA2 0x64118 +#define DPB_AUX_CH_DATA3 0x6411c +#define DPB_AUX_CH_DATA4 0x64120 +#define DPB_AUX_CH_DATA5 0x64124 + +#define DPC_AUX_CH_CTL 0x64210 +#define DPC_AUX_CH_DATA1 0x64214 +#define DPC_AUX_CH_DATA2 0x64218 +#define DPC_AUX_CH_DATA3 0x6421c +#define DPC_AUX_CH_DATA4 0x64220 +#define DPC_AUX_CH_DATA5 0x64224 + +#define DP_AUX_CH_CTL_SEND_BUSY (1 << 31) +#define DP_AUX_CH_CTL_DONE (1 << 30) +#define DP_AUX_CH_CTL_INTERRUPT (1 << 29) +#define DP_AUX_CH_CTL_TIME_OUT_ERROR (1 << 28) +#define DP_AUX_CH_CTL_TIME_OUT_400us (0 << 26) +#define DP_AUX_CH_CTL_TIME_OUT_600us (1 << 26) +#define DP_AUX_CH_CTL_TIME_OUT_800us (2 << 26) +#define DP_AUX_CH_CTL_TIME_OUT_1600us (3 << 26) +#define DP_AUX_CH_CTL_TIME_OUT_MASK (3 << 26) +#define DP_AUX_CH_CTL_RECEIVE_ERROR (1 << 25) +#define DP_AUX_CH_CTL_MESSAGE_SIZE_MASK (0x1f << 20) +#define DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT 20 +#define DP_AUX_CH_CTL_PRECHARGE_2US_MASK (0xf << 16) +#define DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT 16 +#define DP_AUX_CH_CTL_AUX_AKSV_SELECT (1 << 15) +#define DP_AUX_CH_CTL_MANCHESTER_TEST (1 << 14) +#define DP_AUX_CH_CTL_SYNC_TEST (1 << 13) +#define DP_AUX_CH_CTL_DEGLITCH_TEST (1 << 12) +#define DP_AUX_CH_CTL_PRECHARGE_TEST (1 << 11) +#define DP_AUX_CH_CTL_BIT_CLOCK_2X_MASK (0x7ff) +#define DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT 0 + +/* + * Computing GMCH M and N values for the Display Port link + * + * GMCH M/N = dot clock * bytes per pixel / ls_clk * # of lanes + * + * ls_clk (we assume) is the DP link clock (1.62 or 2.7 GHz) + * + * The GMCH value is used internally + * + * bytes_per_pixel is the number of bytes coming out of the plane, + * which is after the LUTs, so we want the bytes for our color format. + * For our current usage, this is always 3, one byte for R, G and B. + */ + +#define _PIPEA_GMCH_DATA_M 0x70050 +#define _PIPEB_GMCH_DATA_M 0x71050 + +/* Transfer unit size for display port - 1, default is 0x3f (for TU size 64) */ +#define PIPE_GMCH_DATA_M_TU_SIZE_MASK (0x3f << 25) +#define PIPE_GMCH_DATA_M_TU_SIZE_SHIFT 25 + +#define PIPE_GMCH_DATA_M_MASK (0xffffff) + +#define _PIPEA_GMCH_DATA_N 0x70054 +#define _PIPEB_GMCH_DATA_N 0x71054 +#define PIPE_GMCH_DATA_N_MASK (0xffffff) + +/* + * Computing Link M and N values for the Display Port link + * + * Link M / N = pixel_clock / ls_clk + * + * (the DP spec calls pixel_clock the 'strm_clk') + * + * The Link value is transmitted in the Main Stream + * Attributes and VB-ID. + */ + +#define _PIPEA_DP_LINK_M 0x70060 +#define _PIPEB_DP_LINK_M 0x71060 +#define PIPEA_DP_LINK_M_MASK (0xffffff) + +#define _PIPEA_DP_LINK_N 0x70064 +#define _PIPEB_DP_LINK_N 0x71064 +#define PIPEA_DP_LINK_N_MASK (0xffffff) + +#define PIPE_GMCH_DATA_M(pipe) _PIPE(pipe, _PIPEA_GMCH_DATA_M, _PIPEB_GMCH_DATA_M) +#define PIPE_GMCH_DATA_N(pipe) _PIPE(pipe, _PIPEA_GMCH_DATA_N, _PIPEB_GMCH_DATA_N) +#define PIPE_DP_LINK_M(pipe) _PIPE(pipe, _PIPEA_DP_LINK_M, _PIPEB_DP_LINK_M) +#define PIPE_DP_LINK_N(pipe) _PIPE(pipe, _PIPEA_DP_LINK_N, _PIPEB_DP_LINK_N) #endif -- cgit v1.2.3-70-g09d2 From 220801bdb53ceeac01d021ac459d112acc7deb0b Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 8 Aug 2012 13:54:41 +0000 Subject: gma500/cdv: add the bits that don't need the new code Based on bits from Yakui We can import various little bits of code before we plumb it all in and hopefully this way catch any regressions more easily. Signed-off-by: Alan Cox Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/cdv_device.c | 59 ++++++++++++++++++ drivers/gpu/drm/gma500/cdv_intel_display.c | 99 +++++++++++++++++++++++++++++- drivers/gpu/drm/gma500/framebuffer.c | 4 ++ drivers/gpu/drm/gma500/psb_intel_drv.h | 2 +- 4 files changed, 161 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index b7e7b49d8f6..e2fff244a59 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -488,6 +488,65 @@ static void cdv_hotplug_enable(struct drm_device *dev, bool on) } } +static const char *force_audio_names[] = { + "off", + "auto", + "on", +}; + +void cdv_intel_attach_force_audio_property(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_psb_private *dev_priv = dev->dev_private; + struct drm_property *prop; + int i; + + prop = dev_priv->force_audio_property; + if (prop == NULL) { + prop = drm_property_create(dev, DRM_MODE_PROP_ENUM, + "audio", + ARRAY_SIZE(force_audio_names)); + if (prop == NULL) + return; + + for (i = 0; i < ARRAY_SIZE(force_audio_names); i++) + drm_property_add_enum(prop, i, i-1, force_audio_names[i]); + + dev_priv->force_audio_property = prop; + } + drm_connector_attach_property(connector, prop, 0); +} + + +static const char *broadcast_rgb_names[] = { + "Full", + "Limited 16:235", +}; + +void cdv_intel_attach_broadcast_rgb_property(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_psb_private *dev_priv = dev->dev_private; + struct drm_property *prop; + int i; + + prop = dev_priv->broadcast_rgb_property; + if (prop == NULL) { + prop = drm_property_create(dev, DRM_MODE_PROP_ENUM, + "Broadcast RGB", + ARRAY_SIZE(broadcast_rgb_names)); + if (prop == NULL) + return; + + for (i = 0; i < ARRAY_SIZE(broadcast_rgb_names); i++) + drm_property_add_enum(prop, i, i, broadcast_rgb_names[i]); + + dev_priv->broadcast_rgb_property = prop; + } + + drm_connector_attach_property(connector, prop, 0); +} + /* Cedarview */ static const struct psb_offset cdv_regmap[2] = { { diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index f16169c95de..2e0231e909f 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -64,11 +64,16 @@ struct cdv_intel_limit_t { static bool cdv_intel_find_best_PLL(const struct cdv_intel_limit_t *limit, struct drm_crtc *crtc, int target, int refclk, struct cdv_intel_clock_t *best_clock); +static bool cdv_intel_find_dp_pll(const struct cdv_intel_limit_t *limit, struct drm_crtc *crtc, int target, + int refclk, + struct cdv_intel_clock_t *best_clock); #define CDV_LIMIT_SINGLE_LVDS_96 0 #define CDV_LIMIT_SINGLE_LVDS_100 1 #define CDV_LIMIT_DAC_HDMI_27 2 #define CDV_LIMIT_DAC_HDMI_96 3 +#define CDV_LIMIT_DP_27 4 +#define CDV_LIMIT_DP_100 5 static const struct cdv_intel_limit_t cdv_intel_limits[] = { { /* CDV_SIGNLE_LVDS_96MHz */ @@ -123,6 +128,30 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = { .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5}, .find_pll = cdv_intel_find_best_PLL, }, + { /* CDV_DP_27MHz */ + .dot = {.min = 160000, .max = 272000}, + .vco = {.min = 1809000, .max = 3564000}, + .n = {.min = 1, .max = 1}, + .m = {.min = 67, .max = 132}, + .m1 = {.min = 0, .max = 0}, + .m2 = {.min = 65, .max = 130}, + .p = {.min = 5, .max = 90}, + .p1 = {.min = 1, .max = 9}, + .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 10}, + .find_pll = cdv_intel_find_dp_pll, + }, + { /* CDV_DP_100MHz */ + .dot = {.min = 160000, .max = 272000}, + .vco = {.min = 1800000, .max = 3600000}, + .n = {.min = 2, .max = 6}, + .m = {.min = 60, .max = 164}, + .m1 = {.min = 0, .max = 0}, + .m2 = {.min = 58, .max = 162}, + .p = {.min = 5, .max = 100}, + .p1 = {.min = 1, .max = 10}, + .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 10}, + .find_pll = cdv_intel_find_dp_pll, + } }; #define _wait_for(COND, MS, W) ({ \ @@ -269,7 +298,7 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc, ref_value &= ~(REF_CLK_MASK); /* use DPLL_A for pipeB on CRT/HDMI */ - if (pipe == 1 && !is_lvds) { + if (pipe == 1 && !is_lvds && !(ddi_select & DP_MASK)) { DRM_DEBUG_KMS("use DPLLA for pipe B\n"); ref_value |= REF_CLK_DPLLA; } else { @@ -409,6 +438,11 @@ static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc, limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96]; else limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100]; + } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { + if (refclk == 27000) + limit = &cdv_intel_limits[CDV_LIMIT_DP_27]; + else + limit = &cdv_intel_limits[CDV_LIMIT_DP_100]; } else { if (refclk == 27000) limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27]; @@ -510,6 +544,49 @@ static bool cdv_intel_find_best_PLL(const struct cdv_intel_limit_t *limit, return err != target; } +static bool cdv_intel_find_dp_pll(const struct cdv_intel_limit_t *limit, struct drm_crtc *crtc, int target, + int refclk, + struct cdv_intel_clock_t *best_clock) +{ + struct cdv_intel_clock_t clock; + if (refclk == 27000) { + if (target < 200000) { + clock.p1 = 2; + clock.p2 = 10; + clock.n = 1; + clock.m1 = 0; + clock.m2 = 118; + } else { + clock.p1 = 1; + clock.p2 = 10; + clock.n = 1; + clock.m1 = 0; + clock.m2 = 98; + } + } else if (refclk == 100000) { + if (target < 200000) { + clock.p1 = 2; + clock.p2 = 10; + clock.n = 5; + clock.m1 = 0; + clock.m2 = 160; + } else { + clock.p1 = 1; + clock.p2 = 10; + clock.n = 5; + clock.m1 = 0; + clock.m2 = 133; + } + } else + return false; + clock.m = clock.m2 + 2; + clock.p = clock.p1 * clock.p2; + clock.vco = (refclk * clock.m) / clock.n; + clock.dot = clock.vco / clock.p; + memcpy(best_clock, &clock, sizeof(struct cdv_intel_clock_t)); + return true; +} + static int cdv_intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) { @@ -963,7 +1040,7 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, u32 dpll = 0, dspcntr, pipeconf; bool ok; bool is_crt = false, is_lvds = false, is_tv = false; - bool is_hdmi = false; + bool is_hdmi = false, is_dp = false; struct drm_mode_config *mode_config = &dev->mode_config; struct drm_connector *connector; const struct cdv_intel_limit_t *limit; @@ -991,6 +1068,9 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, case INTEL_OUTPUT_HDMI: is_hdmi = true; break; + case INTEL_OUTPUT_DISPLAYPORT: + is_dp = true; + break; default: DRM_ERROR("invalid output type.\n"); return 0; @@ -1003,6 +1083,12 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, else /* high-end sku, 27/100 mhz */ refclk = 27000; + if (is_dp) { + if (pipe == 0) + refclk = 27000; + else + refclk = 100000; + } if (is_lvds && dev_priv->lvds_use_ssc) { refclk = dev_priv->lvds_ssc_freq * 1000; @@ -1028,6 +1114,15 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, } /* dpll |= PLL_REF_INPUT_DREFCLK; */ + if (is_dp) { +/*FIXME cdv_intel_dp_set_m_n(crtc, mode, adjusted_mode); */ + } else { + REG_WRITE(PIPE_GMCH_DATA_M(pipe), 0); + REG_WRITE(PIPE_GMCH_DATA_N(pipe), 0); + REG_WRITE(PIPE_DP_LINK_M(pipe), 0); + REG_WRITE(PIPE_DP_LINK_N(pipe), 0); + } + dpll |= DPLL_SYNCLOCK_ENABLE; /* if (is_lvds) dpll |= DPLLB_MODE_LVDS; diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 5732b5702e1..2de6b1fcc13 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -764,6 +764,10 @@ static void psb_setup_outputs(struct drm_device *dev) crtc_mask = dev_priv->ops->hdmi_mask; clone_mask = (1 << INTEL_OUTPUT_HDMI); break; + case INTEL_OUTPUT_DISPLAYPORT: + crtc_mask = (1 << 0) | (1 << 1); + clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT); + break; } encoder->possible_crtcs = crtc_mask; encoder->possible_clones = diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h index 73214e281fa..c574c019910 100644 --- a/drivers/gpu/drm/gma500/psb_intel_drv.h +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h @@ -134,7 +134,7 @@ struct psb_intel_encoder { u32 ddi_select; /* Channel info */ #define DDI0_SELECT 0x01 #define DDI1_SELECT 0x02 -#define DP_MASK 0x8000; +#define DP_MASK 0x8000 #define DDI_MASK 0x03 void *dev_priv; /* For sdvo_priv, lvds_priv, etc... */ -- cgit v1.2.3-70-g09d2 From 37e7b184da18a9cf42e19f3c3cb42cb30874ac22 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 8 Aug 2012 13:55:03 +0000 Subject: gma500/cdv: sync up and add the displayport code to the build This is mostly just aligning bits of behaviour Signed-off-by: Alan Cox Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/Makefile | 3 +- drivers/gpu/drm/gma500/cdv_intel_display.c | 6 +- drivers/gpu/drm/gma500/cdv_intel_dp.c | 480 ++++++++++++++--------------- drivers/gpu/drm/gma500/psb_intel_drv.h | 16 + 4 files changed, 260 insertions(+), 245 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/Makefile b/drivers/gpu/drm/gma500/Makefile index abfa2a93f0d..56a0f2ac82c 100644 --- a/drivers/gpu/drm/gma500/Makefile +++ b/drivers/gpu/drm/gma500/Makefile @@ -30,7 +30,8 @@ gma500_gfx-$(CONFIG_DRM_GMA3600) += cdv_device.o \ cdv_intel_crt.o \ cdv_intel_display.o \ cdv_intel_hdmi.o \ - cdv_intel_lvds.o + cdv_intel_lvds.o \ + cdv_intel_dp.o gma500_gfx-$(CONFIG_DRM_GMA600) += oaktrail_device.o \ oaktrail_crtc.o \ diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index 2e0231e909f..3f1106096ad 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -171,7 +171,7 @@ static const struct cdv_intel_limit_t cdv_intel_limits[] = { #define wait_for(COND, MS) _wait_for(COND, MS, 1) -static int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val) +int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val) { int ret; @@ -198,7 +198,7 @@ static int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val) return 0; } -static int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val) +int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val) { int ret; static bool dpio_debug = true; @@ -240,7 +240,7 @@ static int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val) /* Reset the DPIO configuration register. The BIOS does this at every * mode set. */ -static void cdv_sb_reset(struct drm_device *dev) +void cdv_sb_reset(struct drm_device *dev) { REG_WRITE(DPIO_CFG, 0); diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index c6d545d4292..b29b6026b6e 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -33,7 +33,6 @@ #include "drm_crtc_helper.h" #include "psb_drv.h" #include "psb_intel_drv.h" -#include "psb_drm.h" #include "psb_intel_reg.h" #include "drm_dp_helper.h" @@ -45,7 +44,7 @@ #define CDV_FAST_LINK_TRAIN 1 -struct psb_intel_dp { +struct cdv_intel_dp { uint32_t output_reg; uint32_t DP; uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; @@ -55,7 +54,7 @@ struct psb_intel_dp { uint8_t link_bw; uint8_t lane_count; uint8_t dpcd[4]; - struct psb_intel_output *output; + struct psb_intel_encoder *encoder; struct i2c_adapter adapter; struct i2c_algo_dp_aux_data algo; uint8_t train_set[4]; @@ -94,20 +93,20 @@ static uint32_t dp_vswing_premph_table[] = { * If a CPU or PCH DP output is attached to an eDP panel, this function * will return true, and false otherwise. */ -static bool is_edp(struct psb_intel_output *output) +static bool is_edp(struct psb_intel_encoder *encoder) { - return output->type == INTEL_OUTPUT_EDP; + return encoder->type == INTEL_OUTPUT_EDP; } -static void psb_intel_dp_start_link_train(struct psb_intel_output *output); -static void psb_intel_dp_complete_link_train(struct psb_intel_output *output); -static void psb_intel_dp_link_down(struct psb_intel_output *output); +static void cdv_intel_dp_start_link_train(struct psb_intel_encoder *encoder); +static void cdv_intel_dp_complete_link_train(struct psb_intel_encoder *encoder); +static void cdv_intel_dp_link_down(struct psb_intel_encoder *encoder); static int -psb_intel_dp_max_lane_count(struct psb_intel_output *output) +cdv_intel_dp_max_lane_count(struct psb_intel_encoder *encoder) { - struct psb_intel_dp *intel_dp = output->dev_priv; + struct cdv_intel_dp *intel_dp = encoder->dev_priv; int max_lane_count = 4; if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) { @@ -123,9 +122,9 @@ psb_intel_dp_max_lane_count(struct psb_intel_output *output) } static int -psb_intel_dp_max_link_bw(struct psb_intel_output *output) +cdv_intel_dp_max_link_bw(struct psb_intel_encoder *encoder) { - struct psb_intel_dp *intel_dp = output->dev_priv; + struct cdv_intel_dp *intel_dp = encoder->dev_priv; int max_link_bw = intel_dp->dpcd[DP_MAX_LINK_RATE]; switch (max_link_bw) { @@ -140,7 +139,7 @@ psb_intel_dp_max_link_bw(struct psb_intel_output *output) } static int -psb_intel_dp_link_clock(uint8_t link_bw) +cdv_intel_dp_link_clock(uint8_t link_bw) { if (link_bw == DP_LINK_BW_2_7) return 270000; @@ -149,28 +148,28 @@ psb_intel_dp_link_clock(uint8_t link_bw) } static int -psb_intel_dp_link_required(int pixel_clock, int bpp) +cdv_intel_dp_link_required(int pixel_clock, int bpp) { return (pixel_clock * bpp + 7) / 8; } static int -psb_intel_dp_max_data_rate(int max_link_clock, int max_lanes) +cdv_intel_dp_max_data_rate(int max_link_clock, int max_lanes) { return (max_link_clock * max_lanes * 19) / 20; } static int -psb_intel_dp_mode_valid(struct drm_connector *connector, +cdv_intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { - struct psb_intel_output *output = to_psb_intel_output(connector); + struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector); struct drm_device *dev = connector->dev; struct drm_psb_private *dev_priv = dev->dev_private; - int max_link_clock = psb_intel_dp_link_clock(psb_intel_dp_max_link_bw(output)); - int max_lanes = psb_intel_dp_max_lane_count(output); + int max_link_clock = cdv_intel_dp_link_clock(cdv_intel_dp_max_link_bw(encoder)); + int max_lanes = cdv_intel_dp_max_lane_count(encoder); - if (is_edp(output) && dev_priv->panel_fixed_mode) { + if (is_edp(encoder) && dev_priv->panel_fixed_mode) { if (mode->hdisplay > dev_priv->panel_fixed_mode->hdisplay) return MODE_PANEL; @@ -180,9 +179,9 @@ psb_intel_dp_mode_valid(struct drm_connector *connector, /* only refuse the mode on non eDP since we have seen some weird eDP panels which are outside spec tolerances but somehow work by magic */ - if (!is_edp(output) && - (psb_intel_dp_link_required(mode->clock, 24) - > psb_intel_dp_max_data_rate(max_link_clock, max_lanes))) + if (!is_edp(encoder) && + (cdv_intel_dp_link_required(mode->clock, 24) + > cdv_intel_dp_max_data_rate(max_link_clock, max_lanes))) return MODE_CLOCK_HIGH; if (mode->clock < 10000) @@ -215,13 +214,13 @@ unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) } static int -psb_intel_dp_aux_ch(struct psb_intel_output *output, +cdv_intel_dp_aux_ch(struct psb_intel_encoder *encoder, uint8_t *send, int send_bytes, uint8_t *recv, int recv_size) { - struct psb_intel_dp *intel_dp = output->dev_priv; + struct cdv_intel_dp *intel_dp = encoder->dev_priv; uint32_t output_reg = intel_dp->output_reg; - struct drm_device *dev = output->base.dev; + struct drm_device *dev = encoder->base.dev; uint32_t ch_ctl = output_reg + 0x10; uint32_t ch_data = ch_ctl + 4; int i; @@ -315,7 +314,7 @@ psb_intel_dp_aux_ch(struct psb_intel_output *output, /* Write data to the aux channel in native mode */ static int -psb_intel_dp_aux_native_write(struct psb_intel_output *output, +cdv_intel_dp_aux_native_write(struct psb_intel_encoder *encoder, uint16_t address, uint8_t *send, int send_bytes) { int ret; @@ -332,7 +331,7 @@ psb_intel_dp_aux_native_write(struct psb_intel_output *output, memcpy(&msg[4], send, send_bytes); msg_bytes = send_bytes + 4; for (;;) { - ret = psb_intel_dp_aux_ch(output, msg, msg_bytes, &ack, 1); + ret = cdv_intel_dp_aux_ch(encoder, msg, msg_bytes, &ack, 1); if (ret < 0) return ret; if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) @@ -347,15 +346,15 @@ psb_intel_dp_aux_native_write(struct psb_intel_output *output, /* Write a single byte to the aux channel in native mode */ static int -psb_intel_dp_aux_native_write_1(struct psb_intel_output *output, +cdv_intel_dp_aux_native_write_1(struct psb_intel_encoder *encoder, uint16_t address, uint8_t byte) { - return psb_intel_dp_aux_native_write(output, address, &byte, 1); + return cdv_intel_dp_aux_native_write(encoder, address, &byte, 1); } /* read bytes from a native aux channel */ static int -psb_intel_dp_aux_native_read(struct psb_intel_output *output, +cdv_intel_dp_aux_native_read(struct psb_intel_encoder *encoder, uint16_t address, uint8_t *recv, int recv_bytes) { uint8_t msg[4]; @@ -374,7 +373,7 @@ psb_intel_dp_aux_native_read(struct psb_intel_output *output, reply_bytes = recv_bytes + 1; for (;;) { - ret = psb_intel_dp_aux_ch(output, msg, msg_bytes, + ret = cdv_intel_dp_aux_ch(encoder, msg, msg_bytes, reply, reply_bytes); if (ret == 0) return -EPROTO; @@ -393,14 +392,14 @@ psb_intel_dp_aux_native_read(struct psb_intel_output *output, } static int -psb_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, +cdv_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, uint8_t write_byte, uint8_t *read_byte) { struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; - struct psb_intel_dp *intel_dp = container_of(adapter, - struct psb_intel_dp, + struct cdv_intel_dp *intel_dp = container_of(adapter, + struct cdv_intel_dp, adapter); - struct psb_intel_output *output = intel_dp->output; + struct psb_intel_encoder *encoder = intel_dp->encoder; uint16_t address = algo_data->address; uint8_t msg[5]; uint8_t reply[2]; @@ -440,7 +439,7 @@ psb_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, } for (retry = 0; retry < 5; retry++) { - ret = psb_intel_dp_aux_ch(output, + ret = cdv_intel_dp_aux_ch(encoder, msg, msg_bytes, reply, reply_bytes); if (ret < 0) { @@ -490,13 +489,13 @@ psb_intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, } static int -psb_intel_dp_i2c_init(struct psb_intel_output *output, const char *name) +cdv_intel_dp_i2c_init(struct psb_intel_connector *connector, struct psb_intel_encoder *encoder, const char *name) { - struct psb_intel_dp *intel_dp = output->dev_priv; + struct cdv_intel_dp *intel_dp = encoder->dev_priv; DRM_DEBUG_KMS("i2c_init %s\n", name); intel_dp->algo.running = false; intel_dp->algo.address = 0; - intel_dp->algo.aux_ch = psb_intel_dp_i2c_aux_ch; + intel_dp->algo.aux_ch = cdv_intel_dp_i2c_aux_ch; memset(&intel_dp->adapter, '\0', sizeof (intel_dp->adapter)); intel_dp->adapter.owner = THIS_MODULE; @@ -504,32 +503,32 @@ psb_intel_dp_i2c_init(struct psb_intel_output *output, const char *name) strncpy (intel_dp->adapter.name, name, sizeof(intel_dp->adapter.name) - 1); intel_dp->adapter.name[sizeof(intel_dp->adapter.name) - 1] = '\0'; intel_dp->adapter.algo_data = &intel_dp->algo; - intel_dp->adapter.dev.parent = &output->base.kdev; + intel_dp->adapter.dev.parent = &connector->base.kdev; return i2c_dp_aux_add_bus(&intel_dp->adapter); } static bool -psb_intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, +cdv_intel_dp_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - struct psb_intel_output *output = enc_to_psb_intel_output(encoder); - struct psb_intel_dp *intel_dp = output->dev_priv; + struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); + struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; int lane_count, clock; - int max_lane_count = psb_intel_dp_max_lane_count(output); - int max_clock = psb_intel_dp_max_link_bw(output) == DP_LINK_BW_2_7 ? 1 : 0; + int max_lane_count = cdv_intel_dp_max_lane_count(intel_encoder); + int max_clock = cdv_intel_dp_max_link_bw(intel_encoder) == DP_LINK_BW_2_7 ? 1 : 0; static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { for (clock = max_clock; clock >= 0; clock--) { - int link_avail = psb_intel_dp_max_data_rate(psb_intel_dp_link_clock(bws[clock]), lane_count); + int link_avail = cdv_intel_dp_max_data_rate(cdv_intel_dp_link_clock(bws[clock]), lane_count); - if (psb_intel_dp_link_required(mode->clock, 24) + if (cdv_intel_dp_link_required(mode->clock, 24) <= link_avail) { intel_dp->link_bw = bws[clock]; intel_dp->lane_count = lane_count; - adjusted_mode->clock = psb_intel_dp_link_clock(intel_dp->link_bw); + adjusted_mode->clock = cdv_intel_dp_link_clock(intel_dp->link_bw); DRM_DEBUG_KMS("Display port link bw %02x lane " "count %d clock %d\n", intel_dp->link_bw, intel_dp->lane_count, @@ -542,7 +541,7 @@ psb_intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mo return false; } -struct psb_intel_dp_m_n { +struct cdv_intel_dp_m_n { uint32_t tu; uint32_t gmch_m; uint32_t gmch_n; @@ -567,11 +566,11 @@ psb_intel_reduce_ratio(uint32_t *num, uint32_t *den) } static void -psb_intel_dp_compute_m_n(int bpp, +cdv_intel_dp_compute_m_n(int bpp, int nlanes, int pixel_clock, int link_clock, - struct psb_intel_dp_m_n *m_n) + struct cdv_intel_dp_m_n *m_n) { m_n->tu = 64; m_n->gmch_m = (pixel_clock * bpp + 7) >> 3; @@ -583,7 +582,7 @@ psb_intel_dp_compute_m_n(int bpp, } void -psb_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, +cdv_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = crtc->dev; @@ -591,25 +590,25 @@ psb_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_encoder *encoder; struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); int lane_count = 4, bpp = 24; - struct psb_intel_dp_m_n m_n; + struct cdv_intel_dp_m_n m_n; int pipe = intel_crtc->pipe; /* * Find the lane count in the intel_encoder private */ list_for_each_entry(encoder, &mode_config->encoder_list, head) { - struct psb_intel_output *intel_output; - struct psb_intel_dp *intel_dp; + struct psb_intel_encoder *intel_encoder; + struct cdv_intel_dp *intel_dp; if (encoder->crtc != crtc) continue; - intel_output = enc_to_psb_intel_output(encoder); - intel_dp = intel_output->dev_priv; - if (intel_output->type == INTEL_OUTPUT_DISPLAYPORT) { + intel_encoder = to_psb_intel_encoder(encoder); + intel_dp = intel_encoder->dev_priv; + if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) { lane_count = intel_dp->lane_count; break; - } else if (is_edp(intel_output)) { + } else if (is_edp(intel_encoder)) { lane_count = intel_dp->lane_count; break; } @@ -620,7 +619,7 @@ psb_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, * the number of bytes_per_pixel post-LUT, which we always * set up for 8-bits of R/G/B, or 3 bytes total. */ - psb_intel_dp_compute_m_n(bpp, lane_count, + cdv_intel_dp_compute_m_n(bpp, lane_count, mode->clock, adjusted_mode->clock, &m_n); { @@ -634,13 +633,13 @@ psb_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, } static void -psb_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, +cdv_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - struct psb_intel_output *intel_output = enc_to_psb_intel_output(encoder); + struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); struct drm_crtc *crtc = encoder->crtc; struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); - struct psb_intel_dp *intel_dp = intel_output->dev_priv; + struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; @@ -689,9 +688,9 @@ psb_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode /* If the sink supports it, try to set the power state appropriately */ -static void psb_intel_dp_sink_dpms(struct psb_intel_output *output, int mode) +static void cdv_intel_dp_sink_dpms(struct psb_intel_encoder *encoder, int mode) { - struct psb_intel_dp *intel_dp = output->dev_priv; + struct cdv_intel_dp *intel_dp = encoder->dev_priv; int ret, i; /* Should have a valid DPCD by this point */ @@ -699,7 +698,7 @@ static void psb_intel_dp_sink_dpms(struct psb_intel_output *output, int mode) return; if (mode != DRM_MODE_DPMS_ON) { - ret = psb_intel_dp_aux_native_write_1(output, DP_SET_POWER, + ret = cdv_intel_dp_aux_native_write_1(encoder, DP_SET_POWER, DP_SET_POWER_D3); if (ret != 1) DRM_DEBUG_DRIVER("failed to write sink power state\n"); @@ -709,7 +708,7 @@ static void psb_intel_dp_sink_dpms(struct psb_intel_output *output, int mode) * time to wake up. */ for (i = 0; i < 3; i++) { - ret = psb_intel_dp_aux_native_write_1(output, + ret = cdv_intel_dp_aux_native_write_1(encoder, DP_SET_POWER, DP_SET_POWER_D0); if (ret == 1) @@ -719,42 +718,39 @@ static void psb_intel_dp_sink_dpms(struct psb_intel_output *output, int mode) } } -static void psb_intel_dp_prepare(struct drm_encoder *encoder) +static void cdv_intel_dp_prepare(struct drm_encoder *encoder) { - struct psb_intel_output *output = enc_to_psb_intel_output(encoder); + struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); /* Wake up the sink first */ - psb_intel_dp_sink_dpms(output, DRM_MODE_DPMS_ON); - - psb_intel_dp_link_down(output); + cdv_intel_dp_sink_dpms(intel_encoder, DRM_MODE_DPMS_ON); + cdv_intel_dp_link_down(intel_encoder); } -static void psb_intel_dp_commit(struct drm_encoder *encoder) +static void cdv_intel_dp_commit(struct drm_encoder *encoder) { - struct psb_intel_output *output = enc_to_psb_intel_output(encoder); - - psb_intel_dp_start_link_train(output); - - psb_intel_dp_complete_link_train(output); + struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); + cdv_intel_dp_start_link_train(intel_encoder); + cdv_intel_dp_complete_link_train(intel_encoder); } static void -psb_intel_dp_dpms(struct drm_encoder *encoder, int mode) +cdv_intel_dp_dpms(struct drm_encoder *encoder, int mode) { - struct psb_intel_output *intel_output = enc_to_psb_intel_output(encoder); - struct psb_intel_dp *intel_dp = intel_output->dev_priv; + struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); + struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; struct drm_device *dev = encoder->dev; uint32_t dp_reg = REG_READ(intel_dp->output_reg); if (mode != DRM_MODE_DPMS_ON) { - psb_intel_dp_sink_dpms(intel_output, mode); - psb_intel_dp_link_down(intel_output); + cdv_intel_dp_sink_dpms(intel_encoder, mode); + cdv_intel_dp_link_down(intel_encoder); } else { - psb_intel_dp_sink_dpms(intel_output, mode); + cdv_intel_dp_sink_dpms(intel_encoder, mode); if (!(dp_reg & DP_PORT_EN)) { - psb_intel_dp_start_link_train(intel_output); - psb_intel_dp_complete_link_train(intel_output); + cdv_intel_dp_start_link_train(intel_encoder); + cdv_intel_dp_complete_link_train(intel_encoder); } } } @@ -764,7 +760,7 @@ psb_intel_dp_dpms(struct drm_encoder *encoder, int mode) * cases where the sink may still be asleep. */ static bool -psb_intel_dp_aux_native_read_retry(struct psb_intel_output *output, uint16_t address, +cdv_intel_dp_aux_native_read_retry(struct psb_intel_encoder *encoder, uint16_t address, uint8_t *recv, int recv_bytes) { int ret, i; @@ -774,7 +770,7 @@ psb_intel_dp_aux_native_read_retry(struct psb_intel_output *output, uint16_t add * but we're also supposed to retry 3 times per the spec. */ for (i = 0; i < 3; i++) { - ret = psb_intel_dp_aux_native_read(output, address, recv, + ret = cdv_intel_dp_aux_native_read(encoder, address, recv, recv_bytes); if (ret == recv_bytes) return true; @@ -789,44 +785,44 @@ psb_intel_dp_aux_native_read_retry(struct psb_intel_output *output, uint16_t add * link status information */ static bool -psb_intel_dp_get_link_status(struct psb_intel_output *output) +cdv_intel_dp_get_link_status(struct psb_intel_encoder *encoder) { - struct psb_intel_dp *intel_dp = output->dev_priv; - return psb_intel_dp_aux_native_read_retry(output, + struct cdv_intel_dp *intel_dp = encoder->dev_priv; + return cdv_intel_dp_aux_native_read_retry(encoder, DP_LANE0_1_STATUS, intel_dp->link_status, DP_LINK_STATUS_SIZE); } static uint8_t -psb_intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE], +cdv_intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE], int r) { return link_status[r - DP_LANE0_1_STATUS]; } static uint8_t -psb_intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE], +cdv_intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane) { int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); int s = ((lane & 1) ? DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); - uint8_t l = psb_intel_dp_link_status(link_status, i); + uint8_t l = cdv_intel_dp_link_status(link_status, i); return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; } static uint8_t -psb_intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE], +cdv_intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane) { int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); int s = ((lane & 1) ? DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT : DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); - uint8_t l = psb_intel_dp_link_status(link_status, i); + uint8_t l = cdv_intel_dp_link_status(link_status, i); return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; } @@ -847,7 +843,7 @@ static char *link_train_names[] = { #define CDV_DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_1200 /* static uint8_t -psb_intel_dp_pre_emphasis_max(uint8_t voltage_swing) +cdv_intel_dp_pre_emphasis_max(uint8_t voltage_swing) { switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { case DP_TRAIN_VOLTAGE_SWING_400: @@ -863,16 +859,16 @@ psb_intel_dp_pre_emphasis_max(uint8_t voltage_swing) } */ static void -psb_intel_get_adjust_train(struct psb_intel_output *output) +cdv_intel_get_adjust_train(struct psb_intel_encoder *encoder) { - struct psb_intel_dp *intel_dp = output->dev_priv; + struct cdv_intel_dp *intel_dp = encoder->dev_priv; uint8_t v = 0; uint8_t p = 0; int lane; for (lane = 0; lane < intel_dp->lane_count; lane++) { - uint8_t this_v = psb_intel_get_adjust_request_voltage(intel_dp->link_status, lane); - uint8_t this_p = psb_intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane); + uint8_t this_v = cdv_intel_get_adjust_request_voltage(intel_dp->link_status, lane); + uint8_t this_p = cdv_intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane); if (this_v > v) v = this_v; @@ -892,25 +888,25 @@ psb_intel_get_adjust_train(struct psb_intel_output *output) static uint8_t -psb_intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], +cdv_intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane) { int i = DP_LANE0_1_STATUS + (lane >> 1); int s = (lane & 1) * 4; - uint8_t l = psb_intel_dp_link_status(link_status, i); + uint8_t l = cdv_intel_dp_link_status(link_status, i); return (l >> s) & 0xf; } /* Check for clock recovery is done on all channels */ static bool -psb_intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) +cdv_intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) { int lane; uint8_t lane_status; for (lane = 0; lane < lane_count; lane++) { - lane_status = psb_intel_get_lane_status(link_status, lane); + lane_status = cdv_intel_get_lane_status(link_status, lane); if ((lane_status & DP_LANE_CR_DONE) == 0) return false; } @@ -922,19 +918,19 @@ psb_intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_c DP_LANE_CHANNEL_EQ_DONE|\ DP_LANE_SYMBOL_LOCKED) static bool -psb_intel_channel_eq_ok(struct psb_intel_output *output) +cdv_intel_channel_eq_ok(struct psb_intel_encoder *encoder) { - struct psb_intel_dp *intel_dp = output->dev_priv; + struct cdv_intel_dp *intel_dp = encoder->dev_priv; uint8_t lane_align; uint8_t lane_status; int lane; - lane_align = psb_intel_dp_link_status(intel_dp->link_status, + lane_align = cdv_intel_dp_link_status(intel_dp->link_status, DP_LANE_ALIGN_STATUS_UPDATED); if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) return false; for (lane = 0; lane < intel_dp->lane_count; lane++) { - lane_status = psb_intel_get_lane_status(intel_dp->link_status, lane); + lane_status = cdv_intel_get_lane_status(intel_dp->link_status, lane); if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS) return false; } @@ -942,19 +938,19 @@ psb_intel_channel_eq_ok(struct psb_intel_output *output) } static bool -psb_intel_dp_set_link_train(struct psb_intel_output *output, +cdv_intel_dp_set_link_train(struct psb_intel_encoder *encoder, uint32_t dp_reg_value, uint8_t dp_train_pat) { - struct drm_device *dev = output->base.dev; + struct drm_device *dev = encoder->base.dev; int ret; - struct psb_intel_dp *intel_dp = output->dev_priv; + struct cdv_intel_dp *intel_dp = encoder->dev_priv; REG_WRITE(intel_dp->output_reg, dp_reg_value); REG_READ(intel_dp->output_reg); - ret = psb_intel_dp_aux_native_write_1(output, + ret = cdv_intel_dp_aux_native_write_1(encoder, DP_TRAINING_PATTERN_SET, dp_train_pat); @@ -969,14 +965,14 @@ psb_intel_dp_set_link_train(struct psb_intel_output *output, static bool -psb_intel_dplink_set_level(struct psb_intel_output *output, +cdv_intel_dplink_set_level(struct psb_intel_encoder *encoder, uint8_t dp_train_pat) { int ret; - struct psb_intel_dp *intel_dp = output->dev_priv; + struct cdv_intel_dp *intel_dp = encoder->dev_priv; - ret = psb_intel_dp_aux_native_write(output, + ret = cdv_intel_dp_aux_native_write(encoder, DP_TRAINING_LANE0_SET, intel_dp->train_set, intel_dp->lane_count); @@ -990,10 +986,10 @@ psb_intel_dplink_set_level(struct psb_intel_output *output, } static void -psb_intel_dp_set_vswing_premph(struct psb_intel_output *output, uint8_t signal_level) +cdv_intel_dp_set_vswing_premph(struct psb_intel_encoder *encoder, uint8_t signal_level) { - struct drm_device *dev = output->base.dev; - struct psb_intel_dp *intel_dp = output->dev_priv; + struct drm_device *dev = encoder->base.dev; + struct cdv_intel_dp *intel_dp = encoder->dev_priv; struct ddi_regoff *ddi_reg; int vswing, premph, index; @@ -1013,53 +1009,53 @@ psb_intel_dp_set_vswing_premph(struct psb_intel_output *output, uint8_t signal_l #endif DRM_DEBUG_KMS("Test2\n"); //return ; - psb_sb_reset(dev); + cdv_sb_reset(dev); /* ;Swing voltage programming ;gfx_dpio_set_reg(0xc058, 0x0505313A) */ - psb_sb_write(dev, ddi_reg->VSwing5, 0x0505313A); + cdv_sb_write(dev, ddi_reg->VSwing5, 0x0505313A); /* ;gfx_dpio_set_reg(0x8154, 0x43406055) */ - psb_sb_write(dev, ddi_reg->VSwing1, 0x43406055); + cdv_sb_write(dev, ddi_reg->VSwing1, 0x43406055); /* ;gfx_dpio_set_reg(0x8148, 0x55338954) * The VSwing_PreEmph table is also considered based on the vswing/premp */ index = (vswing + premph) * 2; if (premph == 1 && vswing == 1) { - psb_sb_write(dev, ddi_reg->VSwing2, 0x055738954); + cdv_sb_write(dev, ddi_reg->VSwing2, 0x055738954); } else - psb_sb_write(dev, ddi_reg->VSwing2, dp_vswing_premph_table[index]); + cdv_sb_write(dev, ddi_reg->VSwing2, dp_vswing_premph_table[index]); /* ;gfx_dpio_set_reg(0x814c, 0x40802040) */ if ((vswing + premph) == DP_TRAIN_VOLTAGE_SWING_1200) - psb_sb_write(dev, ddi_reg->VSwing3, 0x70802040); + cdv_sb_write(dev, ddi_reg->VSwing3, 0x70802040); else - psb_sb_write(dev, ddi_reg->VSwing3, 0x40802040); + cdv_sb_write(dev, ddi_reg->VSwing3, 0x40802040); /* ;gfx_dpio_set_reg(0x8150, 0x2b405555) */ - //psb_sb_write(dev, ddi_reg->VSwing4, 0x2b405555); + /* cdv_sb_write(dev, ddi_reg->VSwing4, 0x2b405555); */ /* ;gfx_dpio_set_reg(0x8154, 0xc3406055) */ - psb_sb_write(dev, ddi_reg->VSwing1, 0xc3406055); + cdv_sb_write(dev, ddi_reg->VSwing1, 0xc3406055); /* ;Pre emphasis programming * ;gfx_dpio_set_reg(0xc02c, 0x1f030040) */ - psb_sb_write(dev, ddi_reg->PreEmph1, 0x1f030040); + cdv_sb_write(dev, ddi_reg->PreEmph1, 0x1f030040); /* ;gfx_dpio_set_reg(0x8124, 0x00004000) */ index = 2 * premph + 1; - psb_sb_write(dev, ddi_reg->PreEmph2, dp_vswing_premph_table[index]); + cdv_sb_write(dev, ddi_reg->PreEmph2, dp_vswing_premph_table[index]); return; } /* Enable corresponding port and start training pattern 1 */ static void -psb_intel_dp_start_link_train(struct psb_intel_output *output) +cdv_intel_dp_start_link_train(struct psb_intel_encoder *encoder) { - struct drm_device *dev = output->base.dev; - struct psb_intel_dp *intel_dp = output->dev_priv; + struct drm_device *dev = encoder->base.dev; + struct cdv_intel_dp *intel_dp = encoder->dev_priv; int i; uint8_t voltage; bool clock_recovery = false; @@ -1068,10 +1064,10 @@ psb_intel_dp_start_link_train(struct psb_intel_output *output) uint32_t DP = intel_dp->DP; DP |= DP_PORT_EN; - DP &= ~DP_LINK_TRAIN_MASK; + DP &= ~DP_LINK_TRAIN_MASK; - reg = DP; - reg |= DP_LINK_TRAIN_PAT_1; + reg = DP; + reg |= DP_LINK_TRAIN_PAT_1; /* Enable output, wait for it to become active */ REG_WRITE(intel_dp->output_reg, reg); REG_READ(intel_dp->output_reg); @@ -1079,7 +1075,7 @@ psb_intel_dp_start_link_train(struct psb_intel_output *output) DRM_DEBUG_KMS("Link config\n"); /* Write the link configuration data */ - psb_intel_dp_aux_native_write(output, DP_LINK_BW_SET, + cdv_intel_dp_aux_native_write(encoder, DP_LINK_BW_SET, intel_dp->link_configuration, 2); @@ -1095,19 +1091,19 @@ psb_intel_dp_start_link_train(struct psb_intel_output *output) for (;;) { /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ - if (!psb_intel_dp_set_link_train(output, reg, DP_TRAINING_PATTERN_1)) { + if (!cdv_intel_dp_set_link_train(encoder, reg, DP_TRAINING_PATTERN_1)) { DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 1\n"); } - psb_intel_dp_set_vswing_premph(output, intel_dp->train_set[0]); + cdv_intel_dp_set_vswing_premph(encoder, intel_dp->train_set[0]); /* Set training pattern 1 */ - psb_intel_dplink_set_level(output, DP_TRAINING_PATTERN_1); + cdv_intel_dplink_set_level(encoder, DP_TRAINING_PATTERN_1); udelay(200); - if (!psb_intel_dp_get_link_status(output)) + if (!cdv_intel_dp_get_link_status(encoder)) break; - if (psb_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { + if (cdv_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { DRM_DEBUG_KMS("PT1 train is done\n"); clock_recovery = true; break; @@ -1130,7 +1126,7 @@ psb_intel_dp_start_link_train(struct psb_intel_output *output) voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; /* Compute new intel_dp->train_set as requested by target */ - psb_intel_get_adjust_train(output); + cdv_intel_get_adjust_train(encoder); } @@ -1142,10 +1138,10 @@ psb_intel_dp_start_link_train(struct psb_intel_output *output) } static void -psb_intel_dp_complete_link_train(struct psb_intel_output *output) +cdv_intel_dp_complete_link_train(struct psb_intel_encoder *encoder) { - struct drm_device *dev = output->base.dev; - struct psb_intel_dp *intel_dp = output->dev_priv; + struct drm_device *dev = encoder->base.dev; + struct cdv_intel_dp *intel_dp = encoder->dev_priv; bool channel_eq = false; int tries, cr_tries; u32 reg; @@ -1161,7 +1157,7 @@ psb_intel_dp_complete_link_train(struct psb_intel_output *output) for (;;) { /* channel eq pattern */ - if (!psb_intel_dp_set_link_train(output, reg, + if (!cdv_intel_dp_set_link_train(encoder, reg, DP_TRAINING_PATTERN_2)) { DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 2\n"); } @@ -1169,26 +1165,26 @@ psb_intel_dp_complete_link_train(struct psb_intel_output *output) if (cr_tries > 5) { DRM_ERROR("failed to train DP, aborting\n"); - psb_intel_dp_link_down(output); + cdv_intel_dp_link_down(encoder); break; } - psb_intel_dp_set_vswing_premph(output, intel_dp->train_set[0]); + cdv_intel_dp_set_vswing_premph(encoder, intel_dp->train_set[0]); - psb_intel_dplink_set_level(output, DP_TRAINING_PATTERN_2); + cdv_intel_dplink_set_level(encoder, DP_TRAINING_PATTERN_2); udelay(1000); - if (!psb_intel_dp_get_link_status(output)) + if (!cdv_intel_dp_get_link_status(encoder)) break; /* Make sure clock is still ok */ - if (!psb_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { - psb_intel_dp_start_link_train(output); + if (!cdv_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { + cdv_intel_dp_start_link_train(encoder); cr_tries++; continue; } - if (psb_intel_channel_eq_ok(output)) { + if (cdv_intel_channel_eq_ok(encoder)) { DRM_DEBUG_KMS("PT2 train is done\n"); channel_eq = true; break; @@ -1196,15 +1192,15 @@ psb_intel_dp_complete_link_train(struct psb_intel_output *output) /* Try 5 times, then try clock recovery if that fails */ if (tries > 5) { - psb_intel_dp_link_down(output); - psb_intel_dp_start_link_train(output); + cdv_intel_dp_link_down(encoder); + cdv_intel_dp_start_link_train(encoder); tries = 0; cr_tries++; continue; } /* Compute new intel_dp->train_set as requested by target */ - psb_intel_get_adjust_train(output); + cdv_intel_get_adjust_train(encoder); ++tries; } @@ -1213,15 +1209,15 @@ psb_intel_dp_complete_link_train(struct psb_intel_output *output) REG_WRITE(intel_dp->output_reg, reg); REG_READ(intel_dp->output_reg); - psb_intel_dp_aux_native_write_1(output, + cdv_intel_dp_aux_native_write_1(encoder, DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE); } static void -psb_intel_dp_link_down(struct psb_intel_output *output) +cdv_intel_dp_link_down(struct psb_intel_encoder *encoder) { - struct drm_device *dev = output->base.dev; - struct psb_intel_dp *intel_dp = output->dev_priv; + struct drm_device *dev = encoder->base.dev; + struct cdv_intel_dp *intel_dp = encoder->dev_priv; uint32_t DP = intel_dp->DP; if ((REG_READ(intel_dp->output_reg) & DP_PORT_EN) == 0) @@ -1243,13 +1239,13 @@ psb_intel_dp_link_down(struct psb_intel_output *output) } static enum drm_connector_status -cdv_dp_detect(struct psb_intel_output *output) +cdv_dp_detect(struct psb_intel_encoder *encoder) { - struct psb_intel_dp *intel_dp = output->dev_priv; + struct cdv_intel_dp *intel_dp = encoder->dev_priv; enum drm_connector_status status; status = connector_status_disconnected; - if (psb_intel_dp_aux_native_read(output, 0x000, intel_dp->dpcd, + if (cdv_intel_dp_aux_native_read(encoder, 0x000, intel_dp->dpcd, sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd)) { if (intel_dp->dpcd[DP_DPCD_REV] != 0) @@ -1269,16 +1265,16 @@ cdv_dp_detect(struct psb_intel_output *output) * \return false if DP port is disconnected. */ static enum drm_connector_status -psb_intel_dp_detect(struct drm_connector *connector, bool force) +cdv_intel_dp_detect(struct drm_connector *connector, bool force) { - struct psb_intel_output *output = to_psb_intel_output(connector); - struct psb_intel_dp *intel_dp = output->dev_priv; + struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector); + struct cdv_intel_dp *intel_dp = encoder->dev_priv; enum drm_connector_status status; struct edid *edid = NULL; intel_dp->has_audio = false; - status = cdv_dp_detect(output); + status = cdv_dp_detect(encoder); if (status != connector_status_connected) return status; @@ -1296,20 +1292,18 @@ psb_intel_dp_detect(struct drm_connector *connector, bool force) return connector_status_connected; } -static int psb_intel_dp_get_modes(struct drm_connector *connector) +static int cdv_intel_dp_get_modes(struct drm_connector *connector) { - struct psb_intel_output *intel_output = to_psb_intel_output(connector); - struct psb_intel_dp *intel_dp = intel_output->dev_priv; + struct psb_intel_encoder *intel_encoder = psb_intel_attached_encoder(connector); + struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; struct edid *edid = NULL; int ret = 0; - edid = drm_get_edid(&intel_output->base, - &intel_dp->adapter); + edid = drm_get_edid(connector, &intel_dp->adapter); if (edid) { - drm_mode_connector_update_edid_property(&intel_output-> - base, edid); - ret = drm_add_edid_modes(&intel_output->base, edid); + drm_mode_connector_update_edid_property(connector, edid); + ret = drm_add_edid_modes(connector, edid); kfree(edid); } @@ -1317,10 +1311,10 @@ static int psb_intel_dp_get_modes(struct drm_connector *connector) } static bool -psb_intel_dp_detect_audio(struct drm_connector *connector) +cdv_intel_dp_detect_audio(struct drm_connector *connector) { - struct psb_intel_output *output = to_psb_intel_output(connector); - struct psb_intel_dp *intel_dp = output->dev_priv; + struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector); + struct cdv_intel_dp *intel_dp = encoder->dev_priv; struct edid *edid; bool has_audio = false; @@ -1336,13 +1330,13 @@ psb_intel_dp_detect_audio(struct drm_connector *connector) } static int -psb_intel_dp_set_property(struct drm_connector *connector, +cdv_intel_dp_set_property(struct drm_connector *connector, struct drm_property *property, uint64_t val) { struct drm_psb_private *dev_priv = connector->dev->dev_private; - struct psb_intel_output *output = to_psb_intel_output(connector); - struct psb_intel_dp *intel_dp = output->dev_priv; + struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector); + struct cdv_intel_dp *intel_dp = encoder->dev_priv; int ret; ret = drm_connector_property_set_value(connector, property, val); @@ -1359,7 +1353,7 @@ psb_intel_dp_set_property(struct drm_connector *connector, intel_dp->force_audio = i; if (i == 0) - has_audio = psb_intel_dp_detect_audio(connector); + has_audio = cdv_intel_dp_detect_audio(connector); else has_audio = i > 0; @@ -1381,8 +1375,8 @@ psb_intel_dp_set_property(struct drm_connector *connector, return -EINVAL; done: - if (output->enc.crtc) { - struct drm_crtc *crtc = output->enc.crtc; + if (encoder->base.crtc) { + struct drm_crtc *crtc = encoder->base.crtc; drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->fb); @@ -1392,10 +1386,11 @@ done: } static void -psb_intel_dp_destroy (struct drm_connector *connector) +cdv_intel_dp_destroy (struct drm_connector *connector) { - struct psb_intel_output *output = to_psb_intel_output(connector); - struct psb_intel_dp *intel_dp = output->dev_priv; + struct psb_intel_encoder *psb_intel_encoder = + psb_intel_attached_encoder(connector); + struct cdv_intel_dp *intel_dp = psb_intel_encoder->dev_priv; i2c_del_adapter(&intel_dp->adapter); drm_sysfs_connector_remove(connector); @@ -1403,86 +1398,83 @@ psb_intel_dp_destroy (struct drm_connector *connector) kfree(connector); } -static void psb_intel_dp_encoder_destroy(struct drm_encoder *encoder) +static void cdv_intel_dp_encoder_destroy(struct drm_encoder *encoder) { drm_encoder_cleanup(encoder); } -static const struct drm_encoder_helper_funcs psb_intel_dp_helper_funcs = { - .dpms = psb_intel_dp_dpms, - .mode_fixup = psb_intel_dp_mode_fixup, - .prepare = psb_intel_dp_prepare, - .mode_set = psb_intel_dp_mode_set, - .commit = psb_intel_dp_commit, +static const struct drm_encoder_helper_funcs cdv_intel_dp_helper_funcs = { + .dpms = cdv_intel_dp_dpms, + .mode_fixup = cdv_intel_dp_mode_fixup, + .prepare = cdv_intel_dp_prepare, + .mode_set = cdv_intel_dp_mode_set, + .commit = cdv_intel_dp_commit, }; -static const struct drm_connector_funcs psb_intel_dp_connector_funcs = { +static const struct drm_connector_funcs cdv_intel_dp_connector_funcs = { .dpms = drm_helper_connector_dpms, - .detect = psb_intel_dp_detect, + .detect = cdv_intel_dp_detect, .fill_modes = drm_helper_probe_single_connector_modes, - .set_property = psb_intel_dp_set_property, - .destroy = psb_intel_dp_destroy, + .set_property = cdv_intel_dp_set_property, + .destroy = cdv_intel_dp_destroy, }; -static const struct drm_connector_helper_funcs psb_intel_dp_connector_helper_funcs = { - .get_modes = psb_intel_dp_get_modes, - .mode_valid = psb_intel_dp_mode_valid, +static const struct drm_connector_helper_funcs cdv_intel_dp_connector_helper_funcs = { + .get_modes = cdv_intel_dp_get_modes, + .mode_valid = cdv_intel_dp_mode_valid, .best_encoder = psb_intel_best_encoder, }; -static const struct drm_encoder_funcs psb_intel_dp_enc_funcs = { - .destroy = psb_intel_dp_encoder_destroy, +static const struct drm_encoder_funcs cdv_intel_dp_enc_funcs = { + .destroy = cdv_intel_dp_encoder_destroy, }; -static void -psb_intel_dp_add_properties(struct psb_intel_output *output, struct drm_connector *connector) +static void cdv_intel_dp_add_properties(struct drm_connector *connector) { - psb_intel_attach_force_audio_property(connector); - psb_intel_attach_broadcast_rgb_property(connector); + cdv_intel_attach_force_audio_property(connector); + cdv_intel_attach_broadcast_rgb_property(connector); } void -psb_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, int output_reg) +cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, int output_reg) { + struct psb_intel_encoder *psb_intel_encoder; + struct psb_intel_connector *psb_intel_connector; struct drm_connector *connector; struct drm_encoder *encoder; - struct psb_intel_output *psb_intel_output; - struct psb_intel_dp *intel_dp; + struct cdv_intel_dp *intel_dp; const char *name = NULL; - int type; - psb_intel_output = kzalloc(sizeof(struct psb_intel_output) + - sizeof(struct psb_intel_dp), GFP_KERNEL); - if (!psb_intel_output) + psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL); + if (!psb_intel_encoder) return; + psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL); + if (!psb_intel_connector) + goto err_connector; + intel_dp = kzalloc(sizeof(struct cdv_intel_dp), GFP_KERNEL); + if (!intel_dp) + goto err_priv; + + connector = &psb_intel_connector->base; + encoder = &psb_intel_encoder->base; - intel_dp = (struct psb_intel_dp *)(psb_intel_output + 1); - psb_intel_output->mode_dev = mode_dev; - connector = &psb_intel_output->base; - encoder = &psb_intel_output->enc; - psb_intel_output->dev_priv=intel_dp; - intel_dp->output = psb_intel_output; + drm_connector_init(dev, connector, &cdv_intel_dp_connector_funcs, DRM_MODE_CONNECTOR_DisplayPort); + drm_encoder_init(dev, encoder, &cdv_intel_dp_enc_funcs, DRM_MODE_ENCODER_TMDS); + psb_intel_connector_attach_encoder(psb_intel_connector, psb_intel_encoder); + psb_intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; + + psb_intel_encoder->dev_priv=intel_dp; + intel_dp->encoder = psb_intel_encoder; intel_dp->output_reg = output_reg; - type = DRM_MODE_CONNECTOR_DisplayPort; - psb_intel_output->type = INTEL_OUTPUT_DISPLAYPORT; - - drm_connector_init(dev, connector, &psb_intel_dp_connector_funcs, type); - drm_connector_helper_add(connector, &psb_intel_dp_connector_helper_funcs); + drm_encoder_helper_add(encoder, &cdv_intel_dp_helper_funcs); + drm_connector_helper_add(connector, &cdv_intel_dp_connector_helper_funcs); connector->polled = DRM_CONNECTOR_POLL_HPD; - - connector->interlace_allowed = 0; - connector->doublescan_allowed = 0; - - drm_encoder_init(dev, encoder, &psb_intel_dp_enc_funcs, - DRM_MODE_ENCODER_TMDS); - drm_encoder_helper_add(encoder, &psb_intel_dp_helper_funcs); - - drm_mode_connector_attach_encoder(&psb_intel_output->base, - &psb_intel_output->enc); + connector->interlace_allowed = false; + connector->doublescan_allowed = false; drm_sysfs_connector_add(connector); @@ -1490,15 +1482,21 @@ psb_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev switch (output_reg) { case DP_B: name = "DPDDC-B"; - psb_intel_output->ddi_select = (DP_MASK | DDI0_SELECT); + psb_intel_encoder->ddi_select = (DP_MASK | DDI0_SELECT); break; case DP_C: name = "DPDDC-C"; - psb_intel_output->ddi_select = (DP_MASK | DDI1_SELECT); + psb_intel_encoder->ddi_select = (DP_MASK | DDI1_SELECT); break; } - psb_intel_dp_i2c_init(psb_intel_output, name); - psb_intel_dp_add_properties(psb_intel_output, connector); + cdv_intel_dp_i2c_init(psb_intel_connector, psb_intel_encoder, name); + /* FIXME:fail check */ + cdv_intel_dp_add_properties(connector); + return; +err_priv: + kfree(psb_intel_connector); +err_connector: + kfree(psb_intel_encoder); } diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h index c574c019910..c53e592604c 100644 --- a/drivers/gpu/drm/gma500/psb_intel_drv.h +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h @@ -288,4 +288,20 @@ extern void gma_intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed); extern void gma_intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit); extern void gma_intel_teardown_gmbus(struct drm_device *dev); +/* DP support */ +extern void cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, int output_reg); +extern void psb_intel_dp_set_m_n(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); + +extern void psb_intel_attach_force_audio_property(struct drm_connector *connector); +extern void psb_intel_attach_broadcast_rgb_property(struct drm_connector *connector); + +extern int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val); +extern int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val); +extern void cdv_sb_reset(struct drm_device *dev); + +extern void cdv_intel_attach_force_audio_property(struct drm_connector *connector); +extern void cdv_intel_attach_broadcast_rgb_property(struct drm_connector *connector); + #endif /* __INTEL_DRV_H__ */ -- cgit v1.2.3-70-g09d2 From 35659715c42b5cd148935e8ebd4e5e8e4e256b96 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 8 Aug 2012 13:55:26 +0000 Subject: gma500/cdv: enable the DisplayPort support This will give the basic support only Signed-off-by: Alan Cox Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/cdv_device.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index e2fff244a59..68f100e6713 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -58,10 +58,17 @@ static int cdv_output_init(struct drm_device *dev) cdv_intel_lvds_init(dev, &dev_priv->mode_dev); /* These bits indicate HDMI not SDVO on CDV */ - if (REG_READ(SDVOB) & SDVO_DETECTED) + if (REG_READ(SDVOB) & SDVO_DETECTED) { cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB); - if (REG_READ(SDVOC) & SDVO_DETECTED) + if (REG_READ(DP_B) & DP_DETECTED) + cdv_intel_dp_init(dev, &dev_priv->mode_dev, DP_B); + } + + if (REG_READ(SDVOC) & SDVO_DETECTED) { cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOC); + if (REG_READ(DP_C) & DP_DETECTED) + cdv_intel_dp_init(dev, &dev_priv->mode_dev, DP_C); + } return 0; } -- cgit v1.2.3-70-g09d2 From d112a8163f83752361dd639a9a579ae5cc05c6cf Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 8 Aug 2012 13:55:55 +0000 Subject: gma500/cdv: Add eDP support Introduce the eDP support into the driver. This has been reworked a bit because kernel driver proper uses encoder/connectors while the legacy Intel driver uses the old output stuff. It also diverges on the backlight handling. The legacy Intel driver adds a panel abstraction based upon the i915 one. It's only really used for backlight bits and we have a perfectly good backlight abstraction which can extend instead. Signed-off-by: Zhao Yakui [ported to upstream driver, redid backlight abstraction] Signed-off-by: Alan Cox Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/backlight.c | 45 +++ drivers/gpu/drm/gma500/cdv_device.c | 1 + drivers/gpu/drm/gma500/cdv_intel_display.c | 42 ++- drivers/gpu/drm/gma500/cdv_intel_dp.c | 468 +++++++++++++++++++++++++++-- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 12 +- drivers/gpu/drm/gma500/framebuffer.c | 3 + drivers/gpu/drm/gma500/intel_bios.c | 101 +++++++ drivers/gpu/drm/gma500/intel_bios.h | 46 +++ drivers/gpu/drm/gma500/mdfld_dsi_output.c | 13 +- drivers/gpu/drm/gma500/mid_bios.c | 8 +- drivers/gpu/drm/gma500/opregion.c | 3 +- drivers/gpu/drm/gma500/psb_drv.h | 19 ++ drivers/gpu/drm/gma500/psb_intel_lvds.c | 13 +- drivers/gpu/drm/gma500/psb_intel_reg.h | 38 ++- 14 files changed, 751 insertions(+), 61 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/backlight.c b/drivers/gpu/drm/gma500/backlight.c index 20793951fca..143eba3309c 100644 --- a/drivers/gpu/drm/gma500/backlight.c +++ b/drivers/gpu/drm/gma500/backlight.c @@ -26,10 +26,55 @@ #include "intel_bios.h" #include "power.h" +static void do_gma_backlight_set(struct drm_device *dev) +{ +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE + struct drm_psb_private *dev_priv = dev->dev_private; + backlight_update_status(dev_priv->backlight_device); +#endif +} + +void gma_backlight_enable(struct drm_device *dev) +{ +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE + struct drm_psb_private *dev_priv = dev->dev_private; + dev_priv->backlight_enabled = true; + if (dev_priv->backlight_device) { + dev_priv->backlight_device->props.brightness = dev_priv->backlight_level; + do_gma_backlight_set(dev); + } +#endif +} + +void gma_backlight_disable(struct drm_device *dev) +{ +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE + struct drm_psb_private *dev_priv = dev->dev_private; + dev_priv->backlight_enabled = false; + if (dev_priv->backlight_device) { + dev_priv->backlight_device->props.brightness = 0; + do_gma_backlight_set(dev); + } +#endif +} + +void gma_backlight_set(struct drm_device *dev, int v) +{ +#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE + struct drm_psb_private *dev_priv = dev->dev_private; + dev_priv->backlight_level = v; + if (dev_priv->backlight_device && dev_priv->backlight_enabled) { + dev_priv->backlight_device->props.brightness = v; + do_gma_backlight_set(dev); + } +#endif +} + int gma_backlight_init(struct drm_device *dev) { #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE struct drm_psb_private *dev_priv = dev->dev_private; + dev_priv->backlight_enabled = true; return dev_priv->ops->backlight_init(dev); #else return 0; diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index 68f100e6713..4882e642eec 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -170,6 +170,7 @@ static int cdv_backlight_init(struct drm_device *dev) cdv_get_brightness(cdv_backlight_device); backlight_update_status(cdv_backlight_device); dev_priv->backlight_device = cdv_backlight_device; + dev_priv->backlight_enabled = true; return 0; } diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index 3f1106096ad..bfb05656177 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -438,7 +438,8 @@ static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc, limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96]; else limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100]; - } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) { + } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) || + psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) { if (refclk == 27000) limit = &cdv_intel_limits[CDV_LIMIT_DP_27]; else @@ -1045,6 +1046,7 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, struct drm_connector *connector; const struct cdv_intel_limit_t *limit; u32 ddi_select = 0; + bool is_edp = false; list_for_each_entry(connector, &mode_config->connector_list, head) { struct psb_intel_encoder *psb_intel_encoder = @@ -1071,6 +1073,9 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, case INTEL_OUTPUT_DISPLAYPORT: is_dp = true; break; + case INTEL_OUTPUT_EDP: + is_edp = true; + break; default: DRM_ERROR("invalid output type.\n"); return 0; @@ -1083,7 +1088,15 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, else /* high-end sku, 27/100 mhz */ refclk = 27000; - if (is_dp) { + if (is_dp || is_edp) { + /* + * Based on the spec the low-end SKU has only CRT/LVDS. So it is + * unnecessary to consider it for DP/eDP. + * On the high-end SKU, it will use the 27/100M reference clk + * for DP/eDP. When using SSC clock, the ref clk is 100MHz.Otherwise + * it will be 27MHz. From the VBIOS code it seems that the pipe A choose + * 27MHz for DP/eDP while the Pipe B chooses the 100MHz. + */ if (pipe == 0) refclk = 27000; else @@ -1133,6 +1146,31 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, /* setup pipeconf */ pipeconf = REG_READ(map->conf); + pipeconf &= ~(PIPE_BPC_MASK); + if (is_edp) { + switch (dev_priv->edp.bpp) { + case 24: + pipeconf |= PIPE_8BPC; + break; + case 18: + pipeconf |= PIPE_6BPC; + break; + case 30: + pipeconf |= PIPE_10BPC; + break; + default: + pipeconf |= PIPE_8BPC; + break; + } + } else if (is_lvds) { + /* the BPC will be 6 if it is 18-bit LVDS panel */ + if ((REG_READ(LVDS) & LVDS_A3_POWER_MASK) == LVDS_A3_POWER_UP) + pipeconf |= PIPE_8BPC; + else + pipeconf |= PIPE_6BPC; + } else + pipeconf |= PIPE_8BPC; + /* Set up the display plane register */ dspcntr = DISPPLANE_GAMMA_ENABLE; diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index b29b6026b6e..0571ef9b889 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -36,6 +36,20 @@ #include "psb_intel_reg.h" #include "drm_dp_helper.h" +#define _wait_for(COND, MS, W) ({ \ + unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \ + int ret__ = 0; \ + while (! (COND)) { \ + if (time_after(jiffies, timeout__)) { \ + ret__ = -ETIMEDOUT; \ + break; \ + } \ + if (W && !in_dbg_master()) msleep(W); \ + } \ + ret__; \ +}) + +#define wait_for(COND, MS) _wait_for(COND, MS, 1) #define DP_LINK_STATUS_SIZE 6 #define DP_LINK_CHECK_TIMEOUT (10 * 1000) @@ -59,6 +73,13 @@ struct cdv_intel_dp { struct i2c_algo_dp_aux_data algo; uint8_t train_set[4]; uint8_t link_status[DP_LINK_STATUS_SIZE]; + int panel_power_up_delay; + int panel_power_down_delay; + int panel_power_cycle_delay; + int backlight_on_delay; + int backlight_off_delay; + struct drm_display_mode *panel_fixed_mode; /* for eDP */ + bool panel_on; }; struct ddi_regoff { @@ -159,31 +180,166 @@ cdv_intel_dp_max_data_rate(int max_link_clock, int max_lanes) return (max_link_clock * max_lanes * 19) / 20; } +static void cdv_intel_edp_panel_vdd_on(struct psb_intel_encoder *intel_encoder) +{ + struct drm_device *dev = intel_encoder->base.dev; + struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; + u32 pp; + + if (intel_dp->panel_on) { + DRM_DEBUG_KMS("Skip VDD on because of panel on\n"); + return; + } + DRM_DEBUG_KMS("\n"); + + pp = REG_READ(PP_CONTROL); + + pp |= EDP_FORCE_VDD; + REG_WRITE(PP_CONTROL, pp); + REG_READ(PP_CONTROL); + msleep(intel_dp->panel_power_up_delay); +} + +static void cdv_intel_edp_panel_vdd_off(struct psb_intel_encoder *intel_encoder) +{ + struct drm_device *dev = intel_encoder->base.dev; + u32 pp; + + DRM_DEBUG_KMS("\n"); + pp = REG_READ(PP_CONTROL); + + pp &= ~EDP_FORCE_VDD; + REG_WRITE(PP_CONTROL, pp); + REG_READ(PP_CONTROL); + +} + +/* Returns true if the panel was already on when called */ +static bool cdv_intel_edp_panel_on(struct psb_intel_encoder *intel_encoder) +{ + struct drm_device *dev = intel_encoder->base.dev; + struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; + u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_NONE; + + if (intel_dp->panel_on) + return true; + + DRM_DEBUG_KMS("\n"); + pp = REG_READ(PP_CONTROL); + pp &= ~PANEL_UNLOCK_MASK; + + pp |= (PANEL_UNLOCK_REGS | POWER_TARGET_ON); + REG_WRITE(PP_CONTROL, pp); + REG_READ(PP_CONTROL); + + if (wait_for(((REG_READ(PP_STATUS) & idle_on_mask) == idle_on_mask), 1000)) { + DRM_DEBUG_KMS("Error in Powering up eDP panel, status %x\n", REG_READ(PP_STATUS)); + intel_dp->panel_on = false; + } else + intel_dp->panel_on = true; + msleep(intel_dp->panel_power_up_delay); + + return false; +} + +static void cdv_intel_edp_panel_off (struct psb_intel_encoder *intel_encoder) +{ + struct drm_device *dev = intel_encoder->base.dev; + u32 pp, idle_off_mask = PP_ON ; + struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; + + DRM_DEBUG_KMS("\n"); + + pp = REG_READ(PP_CONTROL); + + if ((pp & POWER_TARGET_ON) == 0) + return; + + intel_dp->panel_on = false; + pp &= ~PANEL_UNLOCK_MASK; + /* ILK workaround: disable reset around power sequence */ + + pp &= ~POWER_TARGET_ON; + pp &= ~EDP_FORCE_VDD; + pp &= ~EDP_BLC_ENABLE; + REG_WRITE(PP_CONTROL, pp); + REG_READ(PP_CONTROL); + DRM_DEBUG_KMS("PP_STATUS %x\n", REG_READ(PP_STATUS)); + + if (wait_for((REG_READ(PP_STATUS) & idle_off_mask) == 0, 1000)) { + DRM_DEBUG_KMS("Error in turning off Panel\n"); + } + + msleep(intel_dp->panel_power_cycle_delay); + DRM_DEBUG_KMS("Over\n"); +} + +static void cdv_intel_edp_backlight_on (struct psb_intel_encoder *intel_encoder) +{ + struct drm_device *dev = intel_encoder->base.dev; + u32 pp; + + DRM_DEBUG_KMS("\n"); + /* + * If we enable the backlight right away following a panel power + * on, we may see slight flicker as the panel syncs with the eDP + * link. So delay a bit to make sure the image is solid before + * allowing it to appear. + */ + msleep(300); + pp = REG_READ(PP_CONTROL); + + pp |= EDP_BLC_ENABLE; + REG_WRITE(PP_CONTROL, pp); + gma_backlight_enable(dev); +} + +static void cdv_intel_edp_backlight_off (struct psb_intel_encoder *intel_encoder) +{ + struct drm_device *dev = intel_encoder->base.dev; + struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; + u32 pp; + + DRM_DEBUG_KMS("\n"); + gma_backlight_disable(dev); + msleep(10); + pp = REG_READ(PP_CONTROL); + + pp &= ~EDP_BLC_ENABLE; + REG_WRITE(PP_CONTROL, pp); + msleep(intel_dp->backlight_off_delay); +} + static int cdv_intel_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct psb_intel_encoder *encoder = psb_intel_attached_encoder(connector); - struct drm_device *dev = connector->dev; - struct drm_psb_private *dev_priv = dev->dev_private; + struct cdv_intel_dp *intel_dp = encoder->dev_priv; int max_link_clock = cdv_intel_dp_link_clock(cdv_intel_dp_max_link_bw(encoder)); int max_lanes = cdv_intel_dp_max_lane_count(encoder); + struct drm_psb_private *dev_priv = connector->dev->dev_private; - if (is_edp(encoder) && dev_priv->panel_fixed_mode) { - if (mode->hdisplay > dev_priv->panel_fixed_mode->hdisplay) + if (is_edp(encoder) && intel_dp->panel_fixed_mode) { + if (mode->hdisplay > intel_dp->panel_fixed_mode->hdisplay) return MODE_PANEL; - - if (mode->vdisplay > dev_priv->panel_fixed_mode->vdisplay) + if (mode->vdisplay > intel_dp->panel_fixed_mode->vdisplay) return MODE_PANEL; } /* only refuse the mode on non eDP since we have seen some weird eDP panels which are outside spec tolerances but somehow work by magic */ if (!is_edp(encoder) && - (cdv_intel_dp_link_required(mode->clock, 24) + (cdv_intel_dp_link_required(mode->clock, dev_priv->edp.bpp) > cdv_intel_dp_max_data_rate(max_link_clock, max_lanes))) return MODE_CLOCK_HIGH; + if (is_edp(encoder)) { + if (cdv_intel_dp_link_required(mode->clock, 24) + > cdv_intel_dp_max_data_rate(max_link_clock, max_lanes)) + return MODE_CLOCK_HIGH; + + } if (mode->clock < 10000) return MODE_CLOCK_LOW; @@ -238,6 +394,8 @@ cdv_intel_dp_aux_ch(struct psb_intel_encoder *encoder, aux_clock_divider = 200 / 2; precharge = 4; + if (is_edp(encoder)) + precharge = 10; if (REG_READ(ch_ctl) & DP_AUX_CH_CTL_SEND_BUSY) { DRM_ERROR("dp_aux_ch not started status 0x%08x\n", @@ -492,7 +650,10 @@ static int cdv_intel_dp_i2c_init(struct psb_intel_connector *connector, struct psb_intel_encoder *encoder, const char *name) { struct cdv_intel_dp *intel_dp = encoder->dev_priv; + int ret; + DRM_DEBUG_KMS("i2c_init %s\n", name); + intel_dp->algo.running = false; intel_dp->algo.address = 0; intel_dp->algo.aux_ch = cdv_intel_dp_i2c_aux_ch; @@ -505,27 +666,58 @@ cdv_intel_dp_i2c_init(struct psb_intel_connector *connector, struct psb_intel_en intel_dp->adapter.algo_data = &intel_dp->algo; intel_dp->adapter.dev.parent = &connector->base.kdev; - return i2c_dp_aux_add_bus(&intel_dp->adapter); + if (is_edp(encoder)) + cdv_intel_edp_panel_vdd_on(encoder); + ret = i2c_dp_aux_add_bus(&intel_dp->adapter); + if (is_edp(encoder)) + cdv_intel_edp_panel_vdd_off(encoder); + + return ret; +} + +void cdv_intel_fixed_panel_mode(struct drm_display_mode *fixed_mode, + struct drm_display_mode *adjusted_mode) +{ + adjusted_mode->hdisplay = fixed_mode->hdisplay; + adjusted_mode->hsync_start = fixed_mode->hsync_start; + adjusted_mode->hsync_end = fixed_mode->hsync_end; + adjusted_mode->htotal = fixed_mode->htotal; + + adjusted_mode->vdisplay = fixed_mode->vdisplay; + adjusted_mode->vsync_start = fixed_mode->vsync_start; + adjusted_mode->vsync_end = fixed_mode->vsync_end; + adjusted_mode->vtotal = fixed_mode->vtotal; + + adjusted_mode->clock = fixed_mode->clock; + + drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); } static bool cdv_intel_dp_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { + struct drm_psb_private *dev_priv = encoder->dev->dev_private; struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; int lane_count, clock; int max_lane_count = cdv_intel_dp_max_lane_count(intel_encoder); int max_clock = cdv_intel_dp_max_link_bw(intel_encoder) == DP_LINK_BW_2_7 ? 1 : 0; static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; + int refclock = mode->clock; + int bpp = 24; + if (is_edp(intel_encoder) && intel_dp->panel_fixed_mode) { + cdv_intel_fixed_panel_mode(intel_dp->panel_fixed_mode, adjusted_mode); + refclock = intel_dp->panel_fixed_mode->clock; + bpp = dev_priv->edp.bpp; + } for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { for (clock = max_clock; clock >= 0; clock--) { int link_avail = cdv_intel_dp_max_data_rate(cdv_intel_dp_link_clock(bws[clock]), lane_count); - if (cdv_intel_dp_link_required(mode->clock, 24) - <= link_avail) { + if (cdv_intel_dp_link_required(refclock, bpp) <= link_avail) { intel_dp->link_bw = bws[clock]; intel_dp->lane_count = lane_count; adjusted_mode->clock = cdv_intel_dp_link_clock(intel_dp->link_bw); @@ -537,7 +729,18 @@ cdv_intel_dp_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mo } } } - + if (is_edp(intel_encoder)) { + /* okay we failed just pick the highest */ + intel_dp->lane_count = max_lane_count; + intel_dp->link_bw = bws[max_clock]; + adjusted_mode->clock = cdv_intel_dp_link_clock(intel_dp->link_bw); + DRM_DEBUG_KMS("Force picking display port link bw %02x lane " + "count %d clock %d\n", + intel_dp->link_bw, intel_dp->lane_count, + adjusted_mode->clock); + + return true; + } return false; } @@ -550,7 +753,7 @@ struct cdv_intel_dp_m_n { }; static void -psb_intel_reduce_ratio(uint32_t *num, uint32_t *den) +cdv_intel_reduce_ratio(uint32_t *num, uint32_t *den) { /* while (*num > 0xffffff || *den > 0xffffff) { @@ -575,10 +778,10 @@ cdv_intel_dp_compute_m_n(int bpp, m_n->tu = 64; m_n->gmch_m = (pixel_clock * bpp + 7) >> 3; m_n->gmch_n = link_clock * nlanes; - psb_intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); + cdv_intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); m_n->link_m = pixel_clock; m_n->link_n = link_clock; - psb_intel_reduce_ratio(&m_n->link_m, &m_n->link_n); + cdv_intel_reduce_ratio(&m_n->link_m, &m_n->link_n); } void @@ -586,6 +789,7 @@ cdv_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = crtc->dev; + struct drm_psb_private *dev_priv = dev->dev_private; struct drm_mode_config *mode_config = &dev->mode_config; struct drm_encoder *encoder; struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); @@ -610,6 +814,7 @@ cdv_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, break; } else if (is_edp(intel_encoder)) { lane_count = intel_dp->lane_count; + bpp = dev_priv->edp.bpp; break; } } @@ -640,7 +845,7 @@ cdv_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode struct drm_crtc *crtc = encoder->crtc; struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc); struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; - + struct drm_device *dev = encoder->dev; intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; intel_dp->DP |= intel_dp->color_range; @@ -683,7 +888,22 @@ cdv_intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode if (intel_crtc->pipe == 1) intel_dp->DP |= DP_PIPEB_SELECT; + REG_WRITE(intel_dp->output_reg, (intel_dp->DP | DP_PORT_EN)); DRM_DEBUG_KMS("DP expected reg is %x\n", intel_dp->DP); + if (is_edp(intel_encoder)) { + uint32_t pfit_control; + cdv_intel_edp_panel_on(intel_encoder); + + if (mode->hdisplay != adjusted_mode->hdisplay || + mode->vdisplay != adjusted_mode->vdisplay) + pfit_control = PFIT_ENABLE; + else + pfit_control = 0; + + pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT; + + REG_WRITE(PFIT_CONTROL, pfit_control); + } } @@ -721,18 +941,31 @@ static void cdv_intel_dp_sink_dpms(struct psb_intel_encoder *encoder, int mode) static void cdv_intel_dp_prepare(struct drm_encoder *encoder) { struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); + int edp = is_edp(intel_encoder); + if (edp) { + cdv_intel_edp_backlight_off(intel_encoder); + cdv_intel_edp_panel_off(intel_encoder); + cdv_intel_edp_panel_vdd_on(intel_encoder); + } /* Wake up the sink first */ cdv_intel_dp_sink_dpms(intel_encoder, DRM_MODE_DPMS_ON); cdv_intel_dp_link_down(intel_encoder); + if (edp) + cdv_intel_edp_panel_vdd_off(intel_encoder); } static void cdv_intel_dp_commit(struct drm_encoder *encoder) { struct psb_intel_encoder *intel_encoder = to_psb_intel_encoder(encoder); + int edp = is_edp(intel_encoder); + if (edp) + cdv_intel_edp_panel_on(intel_encoder); cdv_intel_dp_start_link_train(intel_encoder); cdv_intel_dp_complete_link_train(intel_encoder); + if (edp) + cdv_intel_edp_backlight_on(intel_encoder); } static void @@ -742,16 +975,29 @@ cdv_intel_dp_dpms(struct drm_encoder *encoder, int mode) struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; struct drm_device *dev = encoder->dev; uint32_t dp_reg = REG_READ(intel_dp->output_reg); + int edp = is_edp(intel_encoder); if (mode != DRM_MODE_DPMS_ON) { + if (edp) { + cdv_intel_edp_backlight_off(intel_encoder); + cdv_intel_edp_panel_vdd_on(intel_encoder); + } cdv_intel_dp_sink_dpms(intel_encoder, mode); cdv_intel_dp_link_down(intel_encoder); + if (edp) { + cdv_intel_edp_panel_vdd_off(intel_encoder); + cdv_intel_edp_panel_off(intel_encoder); + } } else { + if (edp) + cdv_intel_edp_panel_on(intel_encoder); cdv_intel_dp_sink_dpms(intel_encoder, mode); if (!(dp_reg & DP_PORT_EN)) { cdv_intel_dp_start_link_train(intel_encoder); cdv_intel_dp_complete_link_train(intel_encoder); } + if (edp) + cdv_intel_edp_backlight_on(intel_encoder); } } @@ -1090,6 +1336,10 @@ cdv_intel_dp_start_link_train(struct psb_intel_encoder *encoder) for (;;) { /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ + DRM_DEBUG_KMS("DP Link Train Set %x, Link_config %x, %x\n", + intel_dp->train_set[0], + intel_dp->link_configuration[0], + intel_dp->link_configuration[1]); if (!cdv_intel_dp_set_link_train(encoder, reg, DP_TRAINING_PATTERN_1)) { DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 1\n"); @@ -1103,6 +1353,10 @@ cdv_intel_dp_start_link_train(struct psb_intel_encoder *encoder) if (!cdv_intel_dp_get_link_status(encoder)) break; + DRM_DEBUG_KMS("DP Link status %x, %x, %x, %x, %x, %x\n", + intel_dp->link_status[0], intel_dp->link_status[1], intel_dp->link_status[2], + intel_dp->link_status[3], intel_dp->link_status[4], intel_dp->link_status[5]); + if (cdv_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { DRM_DEBUG_KMS("PT1 train is done\n"); clock_recovery = true; @@ -1156,7 +1410,13 @@ cdv_intel_dp_complete_link_train(struct psb_intel_encoder *encoder) reg = DP | DP_LINK_TRAIN_PAT_2; for (;;) { - /* channel eq pattern */ + + DRM_DEBUG_KMS("DP Link Train Set %x, Link_config %x, %x\n", + intel_dp->train_set[0], + intel_dp->link_configuration[0], + intel_dp->link_configuration[1]); + /* channel eq pattern */ + if (!cdv_intel_dp_set_link_train(encoder, reg, DP_TRAINING_PATTERN_2)) { DRM_DEBUG_KMS("Failure in aux-transfer setting pattern 2\n"); @@ -1177,6 +1437,10 @@ cdv_intel_dp_complete_link_train(struct psb_intel_encoder *encoder) if (!cdv_intel_dp_get_link_status(encoder)) break; + DRM_DEBUG_KMS("DP Link status %x, %x, %x, %x, %x, %x\n", + intel_dp->link_status[0], intel_dp->link_status[1], intel_dp->link_status[2], + intel_dp->link_status[3], intel_dp->link_status[4], intel_dp->link_status[5]); + /* Make sure clock is still ok */ if (!cdv_intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) { cdv_intel_dp_start_link_train(encoder); @@ -1271,12 +1535,18 @@ cdv_intel_dp_detect(struct drm_connector *connector, bool force) struct cdv_intel_dp *intel_dp = encoder->dev_priv; enum drm_connector_status status; struct edid *edid = NULL; + int edp = is_edp(encoder); intel_dp->has_audio = false; + if (edp) + cdv_intel_edp_panel_vdd_on(encoder); status = cdv_dp_detect(encoder); - if (status != connector_status_connected) + if (status != connector_status_connected) { + if (edp) + cdv_intel_edp_panel_vdd_off(encoder); return status; + } if (intel_dp->force_audio) { intel_dp->has_audio = intel_dp->force_audio > 0; @@ -1288,6 +1558,8 @@ cdv_intel_dp_detect(struct drm_connector *connector, bool force) kfree(edid); } } + if (edp) + cdv_intel_edp_panel_vdd_off(encoder); return connector_status_connected; } @@ -1298,6 +1570,7 @@ static int cdv_intel_dp_get_modes(struct drm_connector *connector) struct cdv_intel_dp *intel_dp = intel_encoder->dev_priv; struct edid *edid = NULL; int ret = 0; + int edp = is_edp(intel_encoder); edid = drm_get_edid(connector, &intel_dp->adapter); @@ -1307,6 +1580,42 @@ static int cdv_intel_dp_get_modes(struct drm_connector *connector) kfree(edid); } + if (is_edp(intel_encoder)) { + struct drm_device *dev = connector->dev; + struct drm_psb_private *dev_priv = dev->dev_private; + + cdv_intel_edp_panel_vdd_off(intel_encoder); + if (ret) { + if (edp && !intel_dp->panel_fixed_mode) { + struct drm_display_mode *newmode; + list_for_each_entry(newmode, &connector->probed_modes, + head) { + if (newmode->type & DRM_MODE_TYPE_PREFERRED) { + intel_dp->panel_fixed_mode = + drm_mode_duplicate(dev, newmode); + break; + } + } + } + + return ret; + } + if (!intel_dp->panel_fixed_mode && dev_priv->lfp_lvds_vbt_mode) { + intel_dp->panel_fixed_mode = + drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); + if (intel_dp->panel_fixed_mode) { + intel_dp->panel_fixed_mode->type |= + DRM_MODE_TYPE_PREFERRED; + } + } + if (intel_dp->panel_fixed_mode != NULL) { + struct drm_display_mode *mode; + mode = drm_mode_duplicate(dev, intel_dp->panel_fixed_mode); + drm_mode_probed_add(connector, mode); + return 1; + } + } + return ret; } @@ -1317,6 +1626,10 @@ cdv_intel_dp_detect_audio(struct drm_connector *connector) struct cdv_intel_dp *intel_dp = encoder->dev_priv; struct edid *edid; bool has_audio = false; + int edp = is_edp(encoder); + + if (edp) + cdv_intel_edp_panel_vdd_on(encoder); edid = drm_get_edid(connector, &intel_dp->adapter); if (edid) { @@ -1325,6 +1638,8 @@ cdv_intel_dp_detect_audio(struct drm_connector *connector) connector->display_info.raw_edid = NULL; kfree(edid); } + if (edp) + cdv_intel_edp_panel_vdd_off(encoder); return has_audio; } @@ -1386,12 +1701,19 @@ done: } static void -cdv_intel_dp_destroy (struct drm_connector *connector) +cdv_intel_dp_destroy(struct drm_connector *connector) { struct psb_intel_encoder *psb_intel_encoder = psb_intel_attached_encoder(connector); struct cdv_intel_dp *intel_dp = psb_intel_encoder->dev_priv; + if (is_edp(psb_intel_encoder)) { + /* cdv_intel_panel_destroy_backlight(connector->dev); */ + if (intel_dp->panel_fixed_mode) { + kfree(intel_dp->panel_fixed_mode); + intel_dp->panel_fixed_mode = NULL; + } + } i2c_del_adapter(&intel_dp->adapter); drm_sysfs_connector_remove(connector); drm_connector_cleanup(connector); @@ -1436,6 +1758,26 @@ static void cdv_intel_dp_add_properties(struct drm_connector *connector) cdv_intel_attach_broadcast_rgb_property(connector); } +/* check the VBT to see whether the eDP is on DP-D port */ +static bool cdv_intel_dpc_is_edp(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = dev->dev_private; + struct child_device_config *p_child; + int i; + + if (!dev_priv->child_dev_num) + return false; + + for (i = 0; i < dev_priv->child_dev_num; i++) { + p_child = dev_priv->child_dev + i; + + if (p_child->dvo_port == PORT_IDPC && + p_child->device_type == DEVICE_TYPE_eDP) + return true; + } + return false; +} + void cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, int output_reg) { @@ -1445,6 +1787,7 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev struct drm_encoder *encoder; struct cdv_intel_dp *intel_dp; const char *name = NULL; + int type = DRM_MODE_CONNECTOR_DisplayPort; psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL); if (!psb_intel_encoder) @@ -1456,14 +1799,22 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev if (!intel_dp) goto err_priv; + if ((output_reg == DP_C) && cdv_intel_dpc_is_edp(dev)) + type = DRM_MODE_CONNECTOR_eDP; + connector = &psb_intel_connector->base; encoder = &psb_intel_encoder->base; - drm_connector_init(dev, connector, &cdv_intel_dp_connector_funcs, DRM_MODE_CONNECTOR_DisplayPort); + drm_connector_init(dev, connector, &cdv_intel_dp_connector_funcs, type); drm_encoder_init(dev, encoder, &cdv_intel_dp_enc_funcs, DRM_MODE_ENCODER_TMDS); psb_intel_connector_attach_encoder(psb_intel_connector, psb_intel_encoder); - psb_intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; + + if (type == DRM_MODE_CONNECTOR_DisplayPort) + psb_intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT; + else + psb_intel_encoder->type = INTEL_OUTPUT_EDP; + psb_intel_encoder->dev_priv=intel_dp; intel_dp->encoder = psb_intel_encoder; @@ -1493,6 +1844,83 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev cdv_intel_dp_i2c_init(psb_intel_connector, psb_intel_encoder, name); /* FIXME:fail check */ cdv_intel_dp_add_properties(connector); + + if (is_edp(psb_intel_encoder)) { + int ret; + struct edp_power_seq cur; + u32 pp_on, pp_off, pp_div; + u32 pwm_ctrl; + + pp_on = REG_READ(PP_CONTROL); + pp_on &= ~PANEL_UNLOCK_MASK; + pp_on |= PANEL_UNLOCK_REGS; + + REG_WRITE(PP_CONTROL, pp_on); + + pwm_ctrl = REG_READ(BLC_PWM_CTL2); + pwm_ctrl |= PWM_PIPE_B; + REG_WRITE(BLC_PWM_CTL2, pwm_ctrl); + + pp_on = REG_READ(PP_ON_DELAYS); + pp_off = REG_READ(PP_OFF_DELAYS); + pp_div = REG_READ(PP_DIVISOR); + + /* Pull timing values out of registers */ + cur.t1_t3 = (pp_on & PANEL_POWER_UP_DELAY_MASK) >> + PANEL_POWER_UP_DELAY_SHIFT; + + cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >> + PANEL_LIGHT_ON_DELAY_SHIFT; + + cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >> + PANEL_LIGHT_OFF_DELAY_SHIFT; + + cur.t10 = (pp_off & PANEL_POWER_DOWN_DELAY_MASK) >> + PANEL_POWER_DOWN_DELAY_SHIFT; + + cur.t11_t12 = ((pp_div & PANEL_POWER_CYCLE_DELAY_MASK) >> + PANEL_POWER_CYCLE_DELAY_SHIFT); + + DRM_DEBUG_KMS("cur t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n", + cur.t1_t3, cur.t8, cur.t9, cur.t10, cur.t11_t12); + + + intel_dp->panel_power_up_delay = cur.t1_t3 / 10; + intel_dp->backlight_on_delay = cur.t8 / 10; + intel_dp->backlight_off_delay = cur.t9 / 10; + intel_dp->panel_power_down_delay = cur.t10 / 10; + intel_dp->panel_power_cycle_delay = (cur.t11_t12 - 1) * 100; + + DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n", + intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay, + intel_dp->panel_power_cycle_delay); + + DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", + intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); + + + cdv_intel_edp_panel_vdd_on(psb_intel_encoder); + ret = cdv_intel_dp_aux_native_read(psb_intel_encoder, DP_DPCD_REV, + intel_dp->dpcd, + sizeof(intel_dp->dpcd)); + cdv_intel_edp_panel_vdd_off(psb_intel_encoder); + if (ret == 0) { + /* if this fails, presume the device is a ghost */ + DRM_INFO("failed to retrieve link info, disabling eDP\n"); + cdv_intel_dp_encoder_destroy(encoder); + cdv_intel_dp_destroy(connector); + goto err_priv; + } else { + DRM_DEBUG_KMS("DPCD: Rev=%x LN_Rate=%x LN_CNT=%x LN_DOWNSP=%x\n", + intel_dp->dpcd[0], intel_dp->dpcd[1], + intel_dp->dpcd[2], intel_dp->dpcd[3]); + + } + /* The CDV reference driver moves pnale backlight setup into the displays that + have a backlight: this is a good idea and one we should probably adopt, however + we need to migrate all the drivers before we can do that */ + /*cdv_intel_panel_setup_backlight(dev); */ + } return; err_priv: diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index c7f9468b74b..b362dd39bf5 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c @@ -506,16 +506,8 @@ static int cdv_intel_lvds_set_property(struct drm_connector *connector, property, value)) return -1; - else { -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - struct drm_psb_private *dev_priv = - encoder->dev->dev_private; - struct backlight_device *bd = - dev_priv->backlight_device; - bd->props.brightness = value; - backlight_update_status(bd); -#endif - } + else + gma_backlight_set(encoder->dev, value); } else if (!strcmp(property->name, "DPMS") && encoder) { struct drm_encoder_helper_funcs *helpers = encoder->helper_private; diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 2de6b1fcc13..884ba73ac6c 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -768,6 +768,9 @@ static void psb_setup_outputs(struct drm_device *dev) crtc_mask = (1 << 0) | (1 << 1); clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT); break; + case INTEL_OUTPUT_EDP: + crtc_mask = (1 << 1); + clone_mask = (1 << INTEL_OUTPUT_EDP); } encoder->possible_crtcs = crtc_mask; encoder->possible_clones = diff --git a/drivers/gpu/drm/gma500/intel_bios.c b/drivers/gpu/drm/gma500/intel_bios.c index 8d7caf0f363..4fb79cf00ed 100644 --- a/drivers/gpu/drm/gma500/intel_bios.c +++ b/drivers/gpu/drm/gma500/intel_bios.c @@ -54,6 +54,98 @@ static void *find_section(struct bdb_header *bdb, int section_id) return NULL; } +static void +parse_edp(struct drm_psb_private *dev_priv, struct bdb_header *bdb) +{ + struct bdb_edp *edp; + struct edp_power_seq *edp_pps; + struct edp_link_params *edp_link_params; + uint8_t panel_type; + + edp = find_section(bdb, BDB_EDP); + + dev_priv->edp.bpp = 18; + if (!edp) { + if (dev_priv->edp.support) { + DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported, assume %dbpp panel color depth.\n", + dev_priv->edp.bpp); + } + return; + } + + panel_type = dev_priv->panel_type; + switch ((edp->color_depth >> (panel_type * 2)) & 3) { + case EDP_18BPP: + dev_priv->edp.bpp = 18; + break; + case EDP_24BPP: + dev_priv->edp.bpp = 24; + break; + case EDP_30BPP: + dev_priv->edp.bpp = 30; + break; + } + + /* Get the eDP sequencing and link info */ + edp_pps = &edp->power_seqs[panel_type]; + edp_link_params = &edp->link_params[panel_type]; + + dev_priv->edp.pps = *edp_pps; + + DRM_DEBUG_KMS("EDP timing in vbt t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n", + dev_priv->edp.pps.t1_t3, dev_priv->edp.pps.t8, + dev_priv->edp.pps.t9, dev_priv->edp.pps.t10, + dev_priv->edp.pps.t11_t12); + + dev_priv->edp.rate = edp_link_params->rate ? DP_LINK_BW_2_7 : + DP_LINK_BW_1_62; + switch (edp_link_params->lanes) { + case 0: + dev_priv->edp.lanes = 1; + break; + case 1: + dev_priv->edp.lanes = 2; + break; + case 3: + default: + dev_priv->edp.lanes = 4; + break; + } + DRM_DEBUG_KMS("VBT reports EDP: Lane_count %d, Lane_rate %d, Bpp %d\n", + dev_priv->edp.lanes, dev_priv->edp.rate, dev_priv->edp.bpp); + + switch (edp_link_params->preemphasis) { + case 0: + dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_0; + break; + case 1: + dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_3_5; + break; + case 2: + dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_6; + break; + case 3: + dev_priv->edp.preemphasis = DP_TRAIN_PRE_EMPHASIS_9_5; + break; + } + switch (edp_link_params->vswing) { + case 0: + dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_400; + break; + case 1: + dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_600; + break; + case 2: + dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_800; + break; + case 3: + dev_priv->edp.vswing = DP_TRAIN_VOLTAGE_SWING_1200; + break; + } + DRM_DEBUG_KMS("VBT reports EDP: VSwing %d, Preemph %d\n", + dev_priv->edp.vswing, dev_priv->edp.preemphasis); +} + static u16 get_blocksize(void *p) { @@ -154,6 +246,8 @@ static void parse_lfp_panel_data(struct drm_psb_private *dev_priv, return; dev_priv->lvds_dither = lvds_options->pixel_dither; + dev_priv->panel_type = lvds_options->panel_type; + if (lvds_options->panel_type == 0xff) return; @@ -340,6 +434,9 @@ parse_driver_features(struct drm_psb_private *dev_priv, if (!driver) return; + if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP) + dev_priv->edp.support = 1; + /* This bit means to use 96Mhz for DPLL_A or not */ if (driver->primary_lfp_id) dev_priv->dplla_96mhz = true; @@ -437,6 +534,9 @@ int psb_intel_init_bios(struct drm_device *dev) size_t size; int i; + + dev_priv->panel_type = 0xff; + /* XXX Should this validation be moved to intel_opregion.c? */ if (dev_priv->opregion.vbt) { struct vbt_header *vbt = dev_priv->opregion.vbt; @@ -477,6 +577,7 @@ int psb_intel_init_bios(struct drm_device *dev) parse_sdvo_device_mapping(dev_priv, bdb); parse_device_mapping(dev_priv, bdb); parse_backlight_data(dev_priv, bdb); + parse_edp(dev_priv, bdb); if (bios) pci_unmap_rom(pdev, bios); diff --git a/drivers/gpu/drm/gma500/intel_bios.h b/drivers/gpu/drm/gma500/intel_bios.h index 2e95523b84b..c6267c98c9e 100644 --- a/drivers/gpu/drm/gma500/intel_bios.h +++ b/drivers/gpu/drm/gma500/intel_bios.h @@ -23,6 +23,7 @@ #define _I830_BIOS_H_ #include +#include struct vbt_header { u8 signature[20]; /**< Always starts with 'VBT$' */ @@ -93,6 +94,7 @@ struct vbios_data { #define BDB_SDVO_LVDS_PNP_IDS 24 #define BDB_SDVO_LVDS_POWER_SEQ 25 #define BDB_TV_OPTIONS 26 +#define BDB_EDP 27 #define BDB_LVDS_OPTIONS 40 #define BDB_LVDS_LFP_DATA_PTRS 41 #define BDB_LVDS_LFP_DATA 42 @@ -391,6 +393,11 @@ struct bdb_sdvo_lvds_options { u8 panel_misc_bits_4; } __attribute__((packed)); +#define BDB_DRIVER_FEATURE_NO_LVDS 0 +#define BDB_DRIVER_FEATURE_INT_LVDS 1 +#define BDB_DRIVER_FEATURE_SDVO_LVDS 2 +#define BDB_DRIVER_FEATURE_EDP 3 + struct bdb_driver_features { u8 boot_dev_algorithm:1; u8 block_display_switch:1; @@ -431,6 +438,45 @@ struct bdb_driver_features { u8 custom_vbt_version; } __attribute__((packed)); +#define EDP_18BPP 0 +#define EDP_24BPP 1 +#define EDP_30BPP 2 +#define EDP_RATE_1_62 0 +#define EDP_RATE_2_7 1 +#define EDP_LANE_1 0 +#define EDP_LANE_2 1 +#define EDP_LANE_4 3 +#define EDP_PREEMPHASIS_NONE 0 +#define EDP_PREEMPHASIS_3_5dB 1 +#define EDP_PREEMPHASIS_6dB 2 +#define EDP_PREEMPHASIS_9_5dB 3 +#define EDP_VSWING_0_4V 0 +#define EDP_VSWING_0_6V 1 +#define EDP_VSWING_0_8V 2 +#define EDP_VSWING_1_2V 3 + +struct edp_power_seq { + u16 t1_t3; + u16 t8; + u16 t9; + u16 t10; + u16 t11_t12; +} __attribute__ ((packed)); + +struct edp_link_params { + u8 rate:4; + u8 lanes:4; + u8 preemphasis:4; + u8 vswing:4; +} __attribute__ ((packed)); + +struct bdb_edp { + struct edp_power_seq power_seqs[16]; + u32 color_depth; + u32 sdrrs_msa_timing_delay; + struct edp_link_params link_params[16]; +} __attribute__ ((packed)); + extern int psb_intel_init_bios(struct drm_device *dev); extern void psb_intel_destroy_bios(struct drm_device *dev); diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c index 5675d93b420..32dba2ab53e 100644 --- a/drivers/gpu/drm/gma500/mdfld_dsi_output.c +++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c @@ -299,17 +299,8 @@ static int mdfld_dsi_connector_set_property(struct drm_connector *connector, if (drm_connector_property_set_value(connector, property, value)) goto set_prop_error; - else { -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - struct backlight_device *psb_bd; - - psb_bd = mdfld_get_backlight_device(); - if (psb_bd) { - psb_bd->props.brightness = value; - mdfld_set_brightness(psb_bd); - } -#endif - } + else + gma_backlight_set(encoder->dev, value); } set_prop_done: return 0; diff --git a/drivers/gpu/drm/gma500/mid_bios.c b/drivers/gpu/drm/gma500/mid_bios.c index b2a790bd989..850cd3fbb96 100644 --- a/drivers/gpu/drm/gma500/mid_bios.c +++ b/drivers/gpu/drm/gma500/mid_bios.c @@ -118,20 +118,20 @@ static void mid_get_pci_revID(struct drm_psb_private *dev_priv) dev_priv->platform_rev_id); } -struct vbt_header { +struct mid_vbt_header { u32 signature; u8 revision; } __packed; /* The same for r0 and r1 */ struct vbt_r0 { - struct vbt_header vbt_header; + struct mid_vbt_header vbt_header; u8 size; u8 checksum; } __packed; struct vbt_r10 { - struct vbt_header vbt_header; + struct mid_vbt_header vbt_header; u8 checksum; u16 size; u8 panel_count; @@ -281,7 +281,7 @@ static void mid_get_vbt_data(struct drm_psb_private *dev_priv) struct drm_device *dev = dev_priv->dev; u32 addr; u8 __iomem *vbt_virtual; - struct vbt_header vbt_header; + struct mid_vbt_header vbt_header; struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); int ret = -1; diff --git a/drivers/gpu/drm/gma500/opregion.c b/drivers/gpu/drm/gma500/opregion.c index c430bd42468..ad0d6de938f 100644 --- a/drivers/gpu/drm/gma500/opregion.c +++ b/drivers/gpu/drm/gma500/opregion.c @@ -166,8 +166,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp) if (config_enabled(CONFIG_BACKLIGHT_CLASS_DEVICE)) { int max = bd->props.max_brightness; - bd->props.brightness = bclp * max / 255; - backlight_update_status(bd); + gma_backlight_set(dev, bclp * max / 255); } asle->cblv = (bclp * 0x64) / 0xff | ASLE_CBLV_VALID; diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 1bd115ecefe..4ab6ae7e92b 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -28,6 +28,7 @@ #include "gma_drm.h" #include "psb_reg.h" #include "psb_intel_drv.h" +#include "intel_bios.h" #include "gtt.h" #include "power.h" #include "opregion.h" @@ -613,6 +614,8 @@ struct drm_psb_private { */ struct backlight_device *backlight_device; struct drm_property *backlight_property; + bool backlight_enabled; + int backlight_level; uint32_t blc_adj1; uint32_t blc_adj2; @@ -640,6 +643,19 @@ struct drm_psb_private { int mdfld_panel_id; bool dplla_96mhz; /* DPLL data from the VBT */ + + struct { + int rate; + int lanes; + int preemphasis; + int vswing; + + bool initialized; + bool support; + int bpp; + struct edp_power_seq pps; + } edp; + uint8_t panel_type; }; @@ -796,6 +812,9 @@ extern int psb_fbdev_init(struct drm_device *dev); /* backlight.c */ int gma_backlight_init(struct drm_device *dev); void gma_backlight_exit(struct drm_device *dev); +void gma_backlight_disable(struct drm_device *dev); +void gma_backlight_enable(struct drm_device *dev); +void gma_backlight_set(struct drm_device *dev, int v); /* oaktrail_crtc.c */ extern const struct drm_crtc_helper_funcs oaktrail_helper_funcs; diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c index 37adc9edf97..2a4c3a9e33e 100644 --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c @@ -630,17 +630,8 @@ int psb_intel_lvds_set_property(struct drm_connector *connector, property, value)) goto set_prop_error; - else { -#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE - struct drm_psb_private *devp = - encoder->dev->dev_private; - struct backlight_device *bd = devp->backlight_device; - if (bd) { - bd->props.brightness = value; - backlight_update_status(bd); - } -#endif - } + else + gma_backlight_set(encoder->dev, value); } else if (!strcmp(property->name, "DPMS")) { struct drm_encoder_helper_funcs *hfuncs = encoder->helper_private; diff --git a/drivers/gpu/drm/gma500/psb_intel_reg.h b/drivers/gpu/drm/gma500/psb_intel_reg.h index d3091fc72b9..389e969e898 100644 --- a/drivers/gpu/drm/gma500/psb_intel_reg.h +++ b/drivers/gpu/drm/gma500/psb_intel_reg.h @@ -173,15 +173,46 @@ #define PP_SEQUENCE_ON (1 << 28) #define PP_SEQUENCE_OFF (2 << 28) #define PP_SEQUENCE_MASK 0x30000000 +#define PP_CYCLE_DELAY_ACTIVE (1 << 27) +#define PP_SEQUENCE_STATE_ON_IDLE (1 << 3) +#define PP_SEQUENCE_STATE_MASK 0x0000000f + #define PP_CONTROL 0x61204 #define POWER_TARGET_ON (1 << 0) - +#define PANEL_UNLOCK_REGS (0xabcd << 16) +#define PANEL_UNLOCK_MASK (0xffff << 16) +#define EDP_FORCE_VDD (1 << 3) +#define EDP_BLC_ENABLE (1 << 2) +#define PANEL_POWER_RESET (1 << 1) +#define PANEL_POWER_OFF (0 << 0) +#define PANEL_POWER_ON (1 << 0) + +/* Poulsbo/Oaktrail */ #define LVDSPP_ON 0x61208 #define LVDSPP_OFF 0x6120c #define PP_CYCLE 0x61210 +/* Cedartrail */ #define PP_ON_DELAYS 0x61208 /* Cedartrail */ +#define PANEL_PORT_SELECT_MASK (3 << 30) +#define PANEL_PORT_SELECT_LVDS (0 << 30) +#define PANEL_PORT_SELECT_EDP (1 << 30) +#define PANEL_POWER_UP_DELAY_MASK (0x1fff0000) +#define PANEL_POWER_UP_DELAY_SHIFT 16 +#define PANEL_LIGHT_ON_DELAY_MASK (0x1fff) +#define PANEL_LIGHT_ON_DELAY_SHIFT 0 + #define PP_OFF_DELAYS 0x6120c /* Cedartrail */ +#define PANEL_POWER_DOWN_DELAY_MASK (0x1fff0000) +#define PANEL_POWER_DOWN_DELAY_SHIFT 16 +#define PANEL_LIGHT_OFF_DELAY_MASK (0x1fff) +#define PANEL_LIGHT_OFF_DELAY_SHIFT 0 + +#define PP_DIVISOR 0x61210 /* Cedartrail */ +#define PP_REFERENCE_DIVIDER_MASK (0xffffff00) +#define PP_REFERENCE_DIVIDER_SHIFT 8 +#define PANEL_POWER_CYCLE_DELAY_MASK (0x1f) +#define PANEL_POWER_CYCLE_DELAY_SHIFT 0 #define PFIT_CONTROL 0x61230 #define PFIT_ENABLE (1 << 31) @@ -1503,4 +1534,9 @@ No status bits are changed. #define PIPE_DP_LINK_M(pipe) _PIPE(pipe, _PIPEA_DP_LINK_M, _PIPEB_DP_LINK_M) #define PIPE_DP_LINK_N(pipe) _PIPE(pipe, _PIPEA_DP_LINK_N, _PIPEB_DP_LINK_N) +#define PIPE_BPC_MASK (7 << 5) +#define PIPE_8BPC (0 << 5) +#define PIPE_10BPC (1 << 5) +#define PIPE_6BPC (2 << 5) + #endif -- cgit v1.2.3-70-g09d2 From 9a9f5786fcccda3cc61eaa8f537690327eff6853 Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Wed, 8 Aug 2012 13:57:01 +0000 Subject: gma500: Disable the clock gating of display controller to make DP/eDP work well I don't know why the DP/eDP is affected by the clock gating. But the test shows that it really fixes the DP/eDP clock issue during enabling DP/eDP. Signed-off-by: Zhao Yakui [Updated to only apply the workaround if the device has DP. We don't want to do this on netbooks] Signed-off-by: Alan Cox Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/cdv_intel_dp.c | 24 ++++++++++++++++++++++++ drivers/gpu/drm/gma500/psb_intel_reg.h | 4 ++++ 2 files changed, 28 insertions(+) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index 0571ef9b889..9bacce3ce53 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -1778,6 +1778,28 @@ static bool cdv_intel_dpc_is_edp(struct drm_device *dev) return false; } +/* Cedarview display clock gating + + We need this disable dot get correct behaviour while enabling + DP/eDP. TODO - investigate if we can turn it back to normality + after enabling */ +static void cdv_disable_intel_clock_gating(struct drm_device *dev) +{ + u32 reg_value; + reg_value = REG_READ(DSPCLK_GATE_D); + + reg_value |= (DPUNIT_PIPEB_GATE_DISABLE | + DPUNIT_PIPEA_GATE_DISABLE | + DPCUNIT_CLOCK_GATE_DISABLE | + DPLSUNIT_CLOCK_GATE_DISABLE | + DPOUNIT_CLOCK_GATE_DISABLE | + DPIOUNIT_CLOCK_GATE_DISABLE); + + REG_WRITE(DSPCLK_GATE_D, reg_value); + + udelay(500); +} + void cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, int output_reg) { @@ -1841,6 +1863,8 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev break; } + cdv_disable_intel_clock_gating(dev); + cdv_intel_dp_i2c_init(psb_intel_connector, psb_intel_encoder, name); /* FIXME:fail check */ cdv_intel_dp_add_properties(connector); diff --git a/drivers/gpu/drm/gma500/psb_intel_reg.h b/drivers/gpu/drm/gma500/psb_intel_reg.h index 389e969e898..d914719c4b6 100644 --- a/drivers/gpu/drm/gma500/psb_intel_reg.h +++ b/drivers/gpu/drm/gma500/psb_intel_reg.h @@ -1313,6 +1313,10 @@ No status bits are changed. # define VRHUNIT_CLOCK_GATE_DISABLE (1 << 28) /* Fixed value on CDV */ # define DPOUNIT_CLOCK_GATE_DISABLE (1 << 11) # define DPIOUNIT_CLOCK_GATE_DISABLE (1 << 6) +# define DPUNIT_PIPEB_GATE_DISABLE (1 << 30) +# define DPUNIT_PIPEA_GATE_DISABLE (1 << 25) +# define DPCUNIT_CLOCK_GATE_DISABLE (1 << 24) +# define DPLSUNIT_CLOCK_GATE_DISABLE (1 << 13) #define RAMCLK_GATE_D 0x6210 -- cgit v1.2.3-70-g09d2 From 4d46259f00c6dd04d53e74cdfa8f8b6ec35c0140 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Tue, 24 Jul 2012 16:47:34 +0100 Subject: drm: gma500: Kill the GEM glue layer The private gem_create_mmap_offset() function is now implemented in the DRM core as drm_gem_create_mmap_offset(). Use it and kill the private copy. Signed-off-by: Laurent Pinchart Signed-off-by: Alan Cox Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/Makefile | 2 +- drivers/gpu/drm/gma500/gem.c | 9 +++- drivers/gpu/drm/gma500/gem_glue.c | 90 --------------------------------------- drivers/gpu/drm/gma500/gem_glue.h | 2 - drivers/gpu/drm/gma500/psb_drv.h | 1 - 5 files changed, 8 insertions(+), 96 deletions(-) delete mode 100644 drivers/gpu/drm/gma500/gem_glue.c delete mode 100644 drivers/gpu/drm/gma500/gem_glue.h (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/Makefile b/drivers/gpu/drm/gma500/Makefile index 56a0f2ac82c..7a2d40a5c1e 100644 --- a/drivers/gpu/drm/gma500/Makefile +++ b/drivers/gpu/drm/gma500/Makefile @@ -3,7 +3,7 @@ # ccflags-y += -I$(srctree)/include/drm -gma500_gfx-y += gem_glue.o \ +gma500_gfx-y += \ accel_2d.o \ backlight.o \ framebuffer.o \ diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c index fc7d144bc2d..df20546a2a3 100644 --- a/drivers/gpu/drm/gma500/gem.c +++ b/drivers/gpu/drm/gma500/gem.c @@ -36,7 +36,12 @@ int psb_gem_init_object(struct drm_gem_object *obj) void psb_gem_free_object(struct drm_gem_object *obj) { struct gtt_range *gtt = container_of(obj, struct gtt_range, gem); - drm_gem_object_release_wrap(obj); + + /* Remove the list map if one is present */ + if (obj->map_list.map) + drm_gem_free_mmap_offset(obj); + drm_gem_object_release(obj); + /* This must occur last as it frees up the memory of the GEM object */ psb_gtt_free_range(obj->dev, gtt); } @@ -77,7 +82,7 @@ int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev, /* Make it mmapable */ if (!obj->map_list.map) { - ret = gem_create_mmap_offset(obj); + ret = drm_gem_create_mmap_offset(obj); if (ret) goto out; } diff --git a/drivers/gpu/drm/gma500/gem_glue.c b/drivers/gpu/drm/gma500/gem_glue.c deleted file mode 100644 index 3c17634f606..00000000000 --- a/drivers/gpu/drm/gma500/gem_glue.c +++ /dev/null @@ -1,90 +0,0 @@ -/************************************************************************** - * Copyright (c) 2011, Intel Corporation. - * All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - **************************************************************************/ - -#include -#include -#include "gem_glue.h" - -void drm_gem_object_release_wrap(struct drm_gem_object *obj) -{ - /* Remove the list map if one is present */ - if (obj->map_list.map) { - struct drm_gem_mm *mm = obj->dev->mm_private; - struct drm_map_list *list = &obj->map_list; - drm_ht_remove_item(&mm->offset_hash, &list->hash); - drm_mm_put_block(list->file_offset_node); - kfree(list->map); - list->map = NULL; - } - drm_gem_object_release(obj); -} - -/** - * gem_create_mmap_offset - invent an mmap offset - * @obj: our object - * - * Standard implementation of offset generation for mmap as is - * duplicated in several drivers. This belongs in GEM. - */ -int gem_create_mmap_offset(struct drm_gem_object *obj) -{ - struct drm_device *dev = obj->dev; - struct drm_gem_mm *mm = dev->mm_private; - struct drm_map_list *list; - struct drm_local_map *map; - int ret; - - list = &obj->map_list; - list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL); - if (list->map == NULL) - return -ENOMEM; - map = list->map; - map->type = _DRM_GEM; - map->size = obj->size; - map->handle = obj; - - list->file_offset_node = drm_mm_search_free(&mm->offset_manager, - obj->size / PAGE_SIZE, 0, 0); - if (!list->file_offset_node) { - dev_err(dev->dev, "failed to allocate offset for bo %d\n", - obj->name); - ret = -ENOSPC; - goto free_it; - } - list->file_offset_node = drm_mm_get_block(list->file_offset_node, - obj->size / PAGE_SIZE, 0); - if (!list->file_offset_node) { - ret = -ENOMEM; - goto free_it; - } - list->hash.key = list->file_offset_node->start; - ret = drm_ht_insert_item(&mm->offset_hash, &list->hash); - if (ret) { - dev_err(dev->dev, "failed to add to map hash\n"); - goto free_mm; - } - return 0; - -free_mm: - drm_mm_put_block(list->file_offset_node); -free_it: - kfree(list->map); - list->map = NULL; - return ret; -} diff --git a/drivers/gpu/drm/gma500/gem_glue.h b/drivers/gpu/drm/gma500/gem_glue.h deleted file mode 100644 index ce5ce30f74d..00000000000 --- a/drivers/gpu/drm/gma500/gem_glue.h +++ /dev/null @@ -1,2 +0,0 @@ -extern void drm_gem_object_release_wrap(struct drm_gem_object *obj); -extern int gem_create_mmap_offset(struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 4ab6ae7e92b..223ff5b1b5c 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -24,7 +24,6 @@ #include #include "drm_global.h" -#include "gem_glue.h" #include "gma_drm.h" #include "psb_reg.h" #include "psb_intel_drv.h" -- cgit v1.2.3-70-g09d2 From f76c0dde78fbe021801fe904fb5999f3154d4e5d Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 22 Aug 2012 12:00:28 +0000 Subject: gma500/cdv: Fix call to cdv_intel_dp_set_m_n We should be making this call not praying that the values are right. In addition as noted by Josiah Standing we should be calling this for eDP as well. Signed-off-by: Alan Cox Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/cdv_intel_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index bfb05656177..55db356d102 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -1127,8 +1127,8 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, } /* dpll |= PLL_REF_INPUT_DREFCLK; */ - if (is_dp) { -/*FIXME cdv_intel_dp_set_m_n(crtc, mode, adjusted_mode); */ + if (is_dp || is_edp) { + cdv_intel_dp_set_m_n(crtc, mode, adjusted_mode); } else { REG_WRITE(PIPE_GMCH_DATA_M(pipe), 0); REG_WRITE(PIPE_GMCH_DATA_N(pipe), 0); -- cgit v1.2.3-70-g09d2 From 451023dc32d4542c21b52ad1692e6e01cb75b099 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 15 Aug 2012 09:32:39 +0000 Subject: drm: remove the raw_edid field from struct drm_display_info Neither the drm core nor any of the drivers really need the raw_edid field of struct drm_display_info for anything. Instead of being useful, it creates confusion about who is responsible for freeing the memory it points to and setting the field to NULL afterwards, leading to memory leaks and dangling pointers. Remove the raw_edid field, and fix drivers as necessary. Reported-by: Russell King Signed-off-by: Jani Nikula Acked-by: Inki Dae Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid.c | 3 --- drivers/gpu/drm/drm_edid_load.c | 23 +++++++++++++---------- drivers/gpu/drm/exynos/exynos_drm_connector.c | 4 +--- drivers/gpu/drm/exynos/exynos_drm_vidi.c | 13 ------------- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 2 -- drivers/gpu/drm/gma500/oaktrail_hdmi.c | 1 - drivers/gpu/drm/gma500/psb_intel_sdvo.c | 3 --- drivers/gpu/drm/i915/intel_dp.c | 4 ---- drivers/gpu/drm/i915/intel_hdmi.c | 3 --- drivers/gpu/drm/i915/intel_modes.c | 1 - drivers/gpu/drm/i915/intel_sdvo.c | 3 --- drivers/gpu/drm/mgag200/mgag200_mode.c | 1 - drivers/gpu/drm/udl/udl_connector.c | 3 --- drivers/staging/omapdrm/omap_connector.c | 5 +---- include/drm/drm_crtc.h | 2 -- 15 files changed, 15 insertions(+), 56 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index a8743c399e8..bcc472572cd 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -399,10 +399,7 @@ struct edid *drm_get_edid(struct drm_connector *connector, if (drm_probe_ddc(adapter)) edid = (struct edid *)drm_do_get_edid(connector, adapter); - connector->display_info.raw_edid = (char *)edid; - return edid; - } EXPORT_SYMBOL(drm_get_edid); diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c index 0303935d10e..186832e1874 100644 --- a/drivers/gpu/drm/drm_edid_load.c +++ b/drivers/gpu/drm/drm_edid_load.c @@ -114,8 +114,8 @@ static u8 generic_edid[GENERIC_EDIDS][128] = { }, }; -static int edid_load(struct drm_connector *connector, char *name, - char *connector_name) +static u8 *edid_load(struct drm_connector *connector, char *name, + char *connector_name) { const struct firmware *fw; struct platform_device *pdev; @@ -205,7 +205,6 @@ static int edid_load(struct drm_connector *connector, char *name, edid = new_edid; } - connector->display_info.raw_edid = edid; DRM_INFO("Got %s EDID base block and %d extension%s from " "\"%s\" for connector \"%s\"\n", builtin ? "built-in" : "external", valid_extensions, valid_extensions == 1 ? "" : "s", @@ -215,7 +214,10 @@ relfw_out: release_firmware(fw); out: - return err; + if (err) + return ERR_PTR(err); + + return edid; } int drm_load_edid_firmware(struct drm_connector *connector) @@ -223,6 +225,7 @@ int drm_load_edid_firmware(struct drm_connector *connector) char *connector_name = drm_get_connector_name(connector); char *edidname = edid_firmware, *last, *colon; int ret; + struct edid *edid; if (*edidname == '\0') return 0; @@ -240,13 +243,13 @@ int drm_load_edid_firmware(struct drm_connector *connector) if (*last == '\n') *last = '\0'; - ret = edid_load(connector, edidname, connector_name); - if (ret) + edid = (struct edid *) edid_load(connector, edidname, connector_name); + if (IS_ERR_OR_NULL(edid)) return 0; - drm_mode_connector_update_edid_property(connector, - (struct edid *) connector->display_info.raw_edid); + drm_mode_connector_update_edid_property(connector, edid); + ret = drm_add_edid_modes(connector, edid); + kfree(edid); - return drm_add_edid_modes(connector, (struct edid *) - connector->display_info.raw_edid); + return ret; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index d9568198c30..9dce3b9c389 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c @@ -147,9 +147,7 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) drm_mode_connector_update_edid_property(connector, edid); count = drm_add_edid_modes(connector, edid); - - kfree(connector->display_info.raw_edid); - connector->display_info.raw_edid = edid; + kfree(edid); } else { struct drm_display_mode *mode = drm_mode_create(connector->dev); struct exynos_drm_panel_info *panel; diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index bb1550c4dd5..92395258d64 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c @@ -102,7 +102,6 @@ static int vidi_get_edid(struct device *dev, struct drm_connector *connector, u8 *edid, int len) { struct vidi_context *ctx = get_vidi_context(dev); - struct edid *raw_edid; DRM_DEBUG_KMS("%s\n", __FILE__); @@ -115,18 +114,6 @@ static int vidi_get_edid(struct device *dev, struct drm_connector *connector, return -EFAULT; } - raw_edid = kzalloc(len, GFP_KERNEL); - if (!raw_edid) { - DRM_DEBUG_KMS("failed to allocate raw_edid.\n"); - return -ENOMEM; - } - - memcpy(raw_edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions) - * EDID_LENGTH, len)); - - /* attach the edid data to connector. */ - connector->display_info.raw_edid = (char *)raw_edid; - memcpy(edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions) * EDID_LENGTH, len)); diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c index 0c90f0316db..b1b77bb92a8 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c @@ -157,8 +157,6 @@ static enum drm_connector_status cdv_hdmi_detect( hdmi_priv->has_hdmi_audio = drm_detect_monitor_audio(edid); } - - psb_intel_connector->base.display_info.raw_edid = NULL; kfree(edid); } return status; diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c index 2eb3dc4e9c9..69e51e903f3 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c @@ -252,7 +252,6 @@ static int oaktrail_hdmi_get_modes(struct drm_connector *connector) if (edid) { drm_mode_connector_update_edid_property(connector, edid); ret = drm_add_edid_modes(connector, edid); - connector->display_info.raw_edid = NULL; } /* diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index 0466c7b985f..a453d94f115 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c @@ -1343,7 +1343,6 @@ psb_intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) } } else status = connector_status_disconnected; - connector->display_info.raw_edid = NULL; kfree(edid); } @@ -1404,7 +1403,6 @@ psb_intel_sdvo_detect(struct drm_connector *connector, bool force) ret = connector_status_disconnected; else ret = connector_status_connected; - connector->display_info.raw_edid = NULL; kfree(edid); } else ret = connector_status_connected; @@ -1453,7 +1451,6 @@ static void psb_intel_sdvo_get_ddc_modes(struct drm_connector *connector) drm_add_edid_modes(connector, edid); } - connector->display_info.raw_edid = NULL; kfree(edid); } } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 977d9d216c7..d14b1e39244 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -2145,7 +2145,6 @@ intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter *ada ret = drm_add_edid_modes(connector, intel_dp->edid); drm_edid_to_eld(connector, intel_dp->edid); - connector->display_info.raw_edid = NULL; return intel_dp->edid_mode_count; } @@ -2191,7 +2190,6 @@ intel_dp_detect(struct drm_connector *connector, bool force) edid = intel_dp_get_edid(connector, &intel_dp->adapter); if (edid) { intel_dp->has_audio = drm_detect_monitor_audio(edid); - connector->display_info.raw_edid = NULL; kfree(edid); } } @@ -2256,8 +2254,6 @@ intel_dp_detect_audio(struct drm_connector *connector) edid = intel_dp_get_edid(connector, &intel_dp->adapter); if (edid) { has_audio = drm_detect_monitor_audio(edid); - - connector->display_info.raw_edid = NULL; kfree(edid); } diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index e4c37bb572e..35a6ee7a8cc 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -737,7 +737,6 @@ intel_hdmi_detect(struct drm_connector *connector, bool force) drm_detect_hdmi_monitor(edid); intel_hdmi->has_audio = drm_detect_monitor_audio(edid); } - connector->display_info.raw_edid = NULL; kfree(edid); } @@ -778,8 +777,6 @@ intel_hdmi_detect_audio(struct drm_connector *connector) if (edid) { if (edid->input & DRM_EDID_INPUT_DIGITAL) has_audio = drm_detect_monitor_audio(edid); - - connector->display_info.raw_edid = NULL; kfree(edid); } diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index 45848b9b670..7a5238fc1a0 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c @@ -50,7 +50,6 @@ int intel_ddc_get_modes(struct drm_connector *connector, drm_mode_connector_update_edid_property(connector, edid); ret = drm_add_edid_modes(connector, edid); drm_edid_to_eld(connector, edid); - connector->display_info.raw_edid = NULL; kfree(edid); } diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 5fb425bf4d0..434b1d1d3c8 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1345,7 +1345,6 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector) } } else status = connector_status_disconnected; - connector->display_info.raw_edid = NULL; kfree(edid); } @@ -1419,7 +1418,6 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) else ret = connector_status_disconnected; - connector->display_info.raw_edid = NULL; kfree(edid); } else ret = connector_status_connected; @@ -1465,7 +1463,6 @@ static void intel_sdvo_get_ddc_modes(struct drm_connector *connector) drm_add_edid_modes(connector, edid); } - connector->display_info.raw_edid = NULL; kfree(edid); } } diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index b69642d5d85..c7420e83c0b 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1399,7 +1399,6 @@ static int mga_vga_get_modes(struct drm_connector *connector) if (edid) { drm_mode_connector_update_edid_property(connector, edid); ret = drm_add_edid_modes(connector, edid); - connector->display_info.raw_edid = NULL; kfree(edid); } return ret; diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index ba055e9ca00..2d98ff92f3b 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c @@ -57,11 +57,8 @@ static int udl_get_modes(struct drm_connector *connector) edid = (struct edid *)udl_get_edid(udl); - connector->display_info.raw_edid = (char *)edid; - drm_mode_connector_update_edid_property(connector, edid); ret = drm_add_edid_modes(connector, edid); - connector->display_info.raw_edid = NULL; kfree(edid); return ret; } diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c index 5e2856c0e0b..9c2287b71d2 100644 --- a/drivers/staging/omapdrm/omap_connector.c +++ b/drivers/staging/omapdrm/omap_connector.c @@ -177,14 +177,11 @@ static int omap_connector_get_modes(struct drm_connector *connector) drm_mode_connector_update_edid_property( connector, edid); n = drm_add_edid_modes(connector, edid); - kfree(connector->display_info.raw_edid); - connector->display_info.raw_edid = edid; } else { drm_mode_connector_update_edid_property( connector, NULL); - connector->display_info.raw_edid = NULL; - kfree(edid); } + kfree(edid); } else { struct drm_display_mode *mode = drm_mode_create(dev); struct omap_video_timings timings; diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index a1a0386e016..0522044b749 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -216,8 +216,6 @@ struct drm_display_info { u32 color_formats; u8 cea_rev; - - char *raw_edid; /* if any */ }; struct drm_framebuffer_funcs { -- cgit v1.2.3-70-g09d2 From 28bbda39b69af06e77801333c0c28ef9df2f256f Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Mon, 13 Aug 2012 16:27:09 +0000 Subject: gma500: Fix comment mispelling in cdv_intel_limits definition. Signed-off-by: Forest Bond Signed-off-by: Alan Cox Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/cdv_intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index 55db356d102..65cb248fa1f 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -76,7 +76,7 @@ static bool cdv_intel_find_dp_pll(const struct cdv_intel_limit_t *limit, struct #define CDV_LIMIT_DP_100 5 static const struct cdv_intel_limit_t cdv_intel_limits[] = { - { /* CDV_SIGNLE_LVDS_96MHz */ + { /* CDV_SINGLE_LVDS_96MHz */ .dot = {.min = 20000, .max = 115500}, .vco = {.min = 1800000, .max = 3600000}, .n = {.min = 2, .max = 6}, -- cgit v1.2.3-70-g09d2 From f835bc0fcacc7f4e29890938b1c2faecd07eda9e Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Mon, 13 Aug 2012 16:29:04 +0000 Subject: gma500: psb_intel_crtc: Drop crtc_enable flag. This is set when setting DPMS on and off, but it isn't checked anywhere, so just remove it. Signed-off-by: Forest Bond Signed-off-by: Alan Cox Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/cdv_intel_display.c | 2 -- drivers/gpu/drm/gma500/psb_intel_drv.h | 1 - 2 files changed, 3 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index 65cb248fa1f..3cfd0931fbf 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -930,7 +930,6 @@ static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode) /* Give the overlay scaler a chance to enable * if it's on this pipe */ /* psb_intel_crtc_dpms_video(crtc, true); TODO */ - psb_intel_crtc->crtc_enable = true; break; case DRM_MODE_DPMS_OFF: if (!psb_intel_crtc->active) @@ -981,7 +980,6 @@ static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode) /* Wait for the clocks to turn off. */ udelay(150); - psb_intel_crtc->crtc_enable = false; break; } cdv_intel_update_watermark(dev, crtc); diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h index c53e592604c..c9710ffa484 100644 --- a/drivers/gpu/drm/gma500/psb_intel_drv.h +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h @@ -193,7 +193,6 @@ struct psb_intel_crtc { u32 mode_flags; bool active; - bool crtc_enable; /* Saved Crtc HW states */ struct psb_intel_crtc_state *crtc_state; -- cgit v1.2.3-70-g09d2 From 32285038f533f5bb4ba4c75de7ade710a836b639 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 15 Aug 2012 09:34:43 +0000 Subject: gma500: remove an unreachable return statement Signed-off-by: Jani Nikula Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index a453d94f115..d35f93ba3a8 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c @@ -1292,7 +1292,6 @@ psb_intel_sdvo_get_analog_edid(struct drm_connector *connector) return drm_get_edid(connector, &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); - return NULL; } static enum drm_connector_status -- cgit v1.2.3-70-g09d2 From ce5fdd63752390b89804b1e246de267b398d1515 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 24 Aug 2012 13:53:49 +1000 Subject: gma500: fix incorrect declaration. this header was incorrect, caused a build failure. Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/psb_intel_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h index c9710ffa484..90f2d11e686 100644 --- a/drivers/gpu/drm/gma500/psb_intel_drv.h +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h @@ -289,7 +289,7 @@ extern void gma_intel_teardown_gmbus(struct drm_device *dev); /* DP support */ extern void cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, int output_reg); -extern void psb_intel_dp_set_m_n(struct drm_crtc *crtc, +extern void cdv_intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); -- cgit v1.2.3-70-g09d2 From f64c48f1d39cbe9e14dd25104633b486b1226606 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 24 Aug 2012 09:42:44 +0300 Subject: gma500: remove references to drm_display_info raw_edid field Another reference to raw_edid field of struct drm_display_info was added in gma500 while the whole field was being removed, causing build failure. Remove the hopefully last references to raw_edid. Reported-by: Fengguang Wu Signed-off-by: Jani Nikula Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/cdv_intel_dp.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index 9bacce3ce53..c9abc06ef68 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -1554,7 +1554,6 @@ cdv_intel_dp_detect(struct drm_connector *connector, bool force) edid = drm_get_edid(connector, &intel_dp->adapter); if (edid) { intel_dp->has_audio = drm_detect_monitor_audio(edid); - connector->display_info.raw_edid = NULL; kfree(edid); } } @@ -1634,8 +1633,6 @@ cdv_intel_dp_detect_audio(struct drm_connector *connector) edid = drm_get_edid(connector, &intel_dp->adapter); if (edid) { has_audio = drm_detect_monitor_audio(edid); - - connector->display_info.raw_edid = NULL; kfree(edid); } if (edp) -- cgit v1.2.3-70-g09d2 From 6f314ebbaa2667d67a7206ba78f28e46cf47eda5 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 13 Jul 2012 15:27:29 +0100 Subject: gma500: Fix frequency detection If we have a 266MHz part we set core_freq to 0 in several spots Signed-off-by: Alan Cox Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/cdv_device.c | 1 + drivers/gpu/drm/gma500/psb_device.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index 4882e642eec..bfc2f397019 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -457,6 +457,7 @@ static void cdv_get_core_freq(struct drm_device *dev) case 6: case 7: dev_priv->core_freq = 266; + break; default: dev_priv->core_freq = 0; } diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c index 5971bc82b76..f1432f096e5 100644 --- a/drivers/gpu/drm/gma500/psb_device.c +++ b/drivers/gpu/drm/gma500/psb_device.c @@ -290,6 +290,7 @@ static void psb_get_core_freq(struct drm_device *dev) case 6: case 7: dev_priv->core_freq = 266; + break; default: dev_priv->core_freq = 0; } -- cgit v1.2.3-70-g09d2 From 4a68a74ba04e7ccf798d45988f4f2d2131fb5063 Mon Sep 17 00:00:00 2001 From: Forest Bond Date: Mon, 13 Aug 2012 16:31:24 +0000 Subject: gma500: Consider CRTC initially active. [this one ideally should make 3.6 - it fixes the very annoying mode setting bug] This causes the pipe to be forced off prior to initial mode set, which roughly mirrors the behavior of the i915 driver. It fixes initial mode setting on my Intel DN2800MT (Cedarview) board. Without it, mode setting triggers an out-of-range error from the monitor for most modes, but only on initial configuration (i.e. they can be configured successfully from userspace after that). Signed-off-by: Forest Bond Signed-off-by: Alan Cox Cc: stable Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/psb_intel_display.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index 30dc22a7156..8033526bb53 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c @@ -1362,6 +1362,9 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe, (struct drm_connector **) (psb_intel_crtc + 1); psb_intel_crtc->mode_set.num_connectors = 0; psb_intel_cursor_init(dev, psb_intel_crtc); + + /* Set to true so that the pipe is forced off on initial config. */ + psb_intel_crtc->active = true; } int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, -- cgit v1.2.3-70-g09d2 From 26df641eac05abe1a3276eea441359b4d1120816 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 12 Sep 2012 10:05:04 +0000 Subject: gma500: Fix regression on Oaktrail devices The register map patches didn't set one value for the GMA600 which means the Fujitsu Q550 dies on boot with the GMA500 driver enabled. Add the map entry so we don't read from the device MMIO + 0 by mistake. Signed-off-by: Alan Cox Cc: Horses Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/oaktrail_device.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c index 0f9b7db80f6..cf49ba5a54b 100644 --- a/drivers/gpu/drm/gma500/oaktrail_device.c +++ b/drivers/gpu/drm/gma500/oaktrail_device.c @@ -476,6 +476,7 @@ static const struct psb_offset oaktrail_regmap[2] = { .pos = DSPAPOS, .surf = DSPASURF, .addr = MRST_DSPABASE, + .base = MRST_DSPABASE, .status = PIPEASTAT, .linoff = DSPALINOFF, .tileoff = DSPATILEOFF, @@ -499,6 +500,7 @@ static const struct psb_offset oaktrail_regmap[2] = { .pos = DSPBPOS, .surf = DSPBSURF, .addr = DSPBBASE, + .base = DSPBBASE, .status = PIPEBSTAT, .linoff = DSPBLINOFF, .tileoff = DSPBTILEOFF, -- cgit v1.2.3-70-g09d2 From 09e7dcf081b1100d1cdff57fa9eb25c3a834c9d6 Mon Sep 17 00:00:00 2001 From: Emil Goode Date: Wed, 5 Sep 2012 23:51:47 +0200 Subject: gma500: Remove unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch removes a unused struct psb_intel_connector Sparse gives a warning: drivers/gpu/drm/gma500/cdv_intel_hdmi.c:142:30: warning: unused variable ‘psb_intel_connector’ [-Wunused-variable] Signed-off-by: Emil Goode Signed-off-by: Dave Airlie --- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c index b1b77bb92a8..7272a461edf 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c @@ -139,8 +139,6 @@ static enum drm_connector_status cdv_hdmi_detect( { struct psb_intel_encoder *psb_intel_encoder = psb_intel_attached_encoder(connector); - struct psb_intel_connector *psb_intel_connector = - to_psb_intel_connector(connector); struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_encoder->dev_priv; struct edid *edid = NULL; enum drm_connector_status status = connector_status_disconnected; -- cgit v1.2.3-70-g09d2 From 4126d5d61f8466be3f76c1bc4e16d46eb2c9641b Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 2 Oct 2012 18:01:05 +0100 Subject: UAPI: (Scripted) Remove redundant DRM UAPI header #inclusions from drivers/gpu/. Remove redundant DRM UAPI header #inclusions from drivers/gpu/. Remove redundant #inclusions of core DRM UAPI headers (drm.h, drm_mode.h and drm_sarea.h). They are now #included via drmP.h and drm_crtc.h via a preceding patch. Without this patch and the patch to make include the UAPI headers from the core headers, after the UAPI split, the DRM C sources cannot find these UAPI headers because the DRM code relies on specific -I flags to make #include "..." work on headers in include/drm/ - but that does not work after the UAPI split without adding more -I flags. Signed-off-by: David Howells Acked-by: Dave Airlie Acked-by: Arnd Bergmann Acked-by: Thomas Gleixner Acked-by: Paul E. McKenney Acked-by: Dave Jones --- drivers/gpu/drm/ast/ast_drv.c | 1 - drivers/gpu/drm/ast/ast_fb.c | 1 - drivers/gpu/drm/cirrus/cirrus_drv.c | 1 - drivers/gpu/drm/cirrus/cirrus_fbdev.c | 1 - drivers/gpu/drm/cirrus/cirrus_main.c | 1 - drivers/gpu/drm/cirrus/cirrus_mode.c | 1 - drivers/gpu/drm/drm_crtc.c | 1 - drivers/gpu/drm/drm_modes.c | 1 - drivers/gpu/drm/exynos/exynos_drm_buf.c | 1 - drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 1 - drivers/gpu/drm/exynos/exynos_drm_drv.c | 1 - drivers/gpu/drm/exynos/exynos_drm_drv.h | 1 - drivers/gpu/drm/exynos/exynos_drm_gem.c | 1 - drivers/gpu/drm/gma500/intel_gmbus.c | 1 - drivers/gpu/drm/gma500/psb_intel_sdvo.c | 1 - drivers/gpu/drm/i810/i810_dma.c | 1 - drivers/gpu/drm/i810/i810_drv.c | 1 - drivers/gpu/drm/i915/dvo.h | 1 - drivers/gpu/drm/i915/i915_debugfs.c | 1 - drivers/gpu/drm/i915/i915_dma.c | 1 - drivers/gpu/drm/i915/i915_drv.c | 1 - drivers/gpu/drm/i915/i915_gem.c | 1 - drivers/gpu/drm/i915/i915_gem_debug.c | 1 - drivers/gpu/drm/i915/i915_gem_evict.c | 1 - drivers/gpu/drm/i915/i915_gem_execbuffer.c | 1 - drivers/gpu/drm/i915/i915_gem_gtt.c | 1 - drivers/gpu/drm/i915/i915_gem_stolen.c | 1 - drivers/gpu/drm/i915/i915_gem_tiling.c | 1 - drivers/gpu/drm/i915/i915_ioc32.c | 1 - drivers/gpu/drm/i915/i915_irq.c | 1 - drivers/gpu/drm/i915/i915_suspend.c | 1 - drivers/gpu/drm/i915/intel_bios.c | 1 - drivers/gpu/drm/i915/intel_crt.c | 1 - drivers/gpu/drm/i915/intel_dp.c | 1 - drivers/gpu/drm/i915/intel_dvo.c | 1 - drivers/gpu/drm/i915/intel_fb.c | 1 - drivers/gpu/drm/i915/intel_hdmi.c | 1 - drivers/gpu/drm/i915/intel_i2c.c | 1 - drivers/gpu/drm/i915/intel_lvds.c | 1 - drivers/gpu/drm/i915/intel_overlay.c | 1 - drivers/gpu/drm/i915/intel_ringbuffer.c | 1 - drivers/gpu/drm/i915/intel_sdvo.c | 1 - drivers/gpu/drm/i915/intel_tv.c | 1 - drivers/gpu/drm/mga/mga_dma.c | 2 -- drivers/gpu/drm/mga/mga_drv.c | 1 - drivers/gpu/drm/mga/mga_ioc32.c | 1 - drivers/gpu/drm/mga/mga_irq.c | 1 - drivers/gpu/drm/mga/mga_state.c | 1 - drivers/gpu/drm/mga/mga_warp.c | 1 - drivers/gpu/drm/mgag200/mgag200_drv.c | 1 - drivers/gpu/drm/mgag200/mgag200_fb.c | 1 - drivers/gpu/drm/mgag200/mgag200_i2c.c | 1 - drivers/gpu/drm/mgag200/mgag200_main.c | 1 - drivers/gpu/drm/mgag200/mgag200_mode.c | 1 - drivers/gpu/drm/nouveau/nouveau_acpi.c | 2 -- drivers/gpu/drm/nouveau/nouveau_channel.c | 1 - drivers/gpu/drm/nouveau/nouveau_dma.c | 1 - drivers/gpu/drm/nouveau/nouveau_drv.c | 1 - drivers/gpu/drm/nouveau/nouveau_fbcon.c | 1 - drivers/gpu/drm/nouveau/nouveau_fence.c | 1 - drivers/gpu/drm/nouveau/nouveau_gem.c | 1 - drivers/gpu/drm/nouveau/nouveau_gpuobj.c | 1 - drivers/gpu/drm/nouveau/nouveau_ioc32.c | 1 - drivers/gpu/drm/nouveau/nouveau_irq.c | 1 - drivers/gpu/drm/nouveau/nouveau_mem.c | 2 -- drivers/gpu/drm/nouveau/nouveau_notifier.c | 1 - drivers/gpu/drm/nouveau/nouveau_prime.c | 1 - drivers/gpu/drm/nouveau/nouveau_state.c | 2 -- drivers/gpu/drm/nouveau/nv04_cursor.c | 1 - drivers/gpu/drm/nouveau/nv04_display.c | 1 - drivers/gpu/drm/nouveau/nv04_fb.c | 1 - drivers/gpu/drm/nouveau/nv04_fifo.c | 1 - drivers/gpu/drm/nouveau/nv04_graph.c | 1 - drivers/gpu/drm/nouveau/nv04_instmem.c | 1 - drivers/gpu/drm/nouveau/nv04_mc.c | 1 - drivers/gpu/drm/nouveau/nv04_timer.c | 1 - drivers/gpu/drm/nouveau/nv10_fb.c | 1 - drivers/gpu/drm/nouveau/nv10_fifo.c | 1 - drivers/gpu/drm/nouveau/nv10_graph.c | 1 - drivers/gpu/drm/nouveau/nv17_fifo.c | 1 - drivers/gpu/drm/nouveau/nv20_fb.c | 1 - drivers/gpu/drm/nouveau/nv20_graph.c | 1 - drivers/gpu/drm/nouveau/nv30_fb.c | 1 - drivers/gpu/drm/nouveau/nv40_fb.c | 1 - drivers/gpu/drm/nouveau/nv40_fifo.c | 1 - drivers/gpu/drm/nouveau/nv40_graph.c | 1 - drivers/gpu/drm/nouveau/nv40_mc.c | 1 - drivers/gpu/drm/nouveau/nv50_crtc.c | 1 - drivers/gpu/drm/nouveau/nv50_cursor.c | 1 - drivers/gpu/drm/nouveau/nv50_display.h | 1 - drivers/gpu/drm/nouveau/nv50_fb.c | 1 - drivers/gpu/drm/nouveau/nv50_fifo.c | 1 - drivers/gpu/drm/nouveau/nv50_graph.c | 1 - drivers/gpu/drm/nouveau/nv50_instmem.c | 1 - drivers/gpu/drm/nouveau/nv50_mc.c | 1 - drivers/gpu/drm/nouveau/nv84_fifo.c | 1 - drivers/gpu/drm/nouveau/nvc0_fb.c | 1 - drivers/gpu/drm/r128/r128_cce.c | 1 - drivers/gpu/drm/r128/r128_drv.c | 1 - drivers/gpu/drm/r128/r128_ioc32.c | 1 - drivers/gpu/drm/r128/r128_irq.c | 1 - drivers/gpu/drm/r128/r128_state.c | 1 - drivers/gpu/drm/radeon/evergreen_blit_kms.c | 1 - drivers/gpu/drm/radeon/r100.c | 1 - drivers/gpu/drm/radeon/r200.c | 1 - drivers/gpu/drm/radeon/r300_cmdbuf.c | 1 - drivers/gpu/drm/radeon/r600_blit.c | 1 - drivers/gpu/drm/radeon/r600_blit_kms.c | 1 - drivers/gpu/drm/radeon/r600_cp.c | 1 - drivers/gpu/drm/radeon/radeon_acpi.c | 2 -- drivers/gpu/drm/radeon/radeon_agp.c | 1 - drivers/gpu/drm/radeon/radeon_cp.c | 2 -- drivers/gpu/drm/radeon/radeon_drv.c | 1 - drivers/gpu/drm/radeon/radeon_fb.c | 1 - drivers/gpu/drm/radeon/radeon_fence.c | 1 - drivers/gpu/drm/radeon/radeon_gem.c | 1 - drivers/gpu/drm/radeon/radeon_ioc32.c | 1 - drivers/gpu/drm/radeon/radeon_irq.c | 1 - drivers/gpu/drm/radeon/radeon_kms.c | 1 - drivers/gpu/drm/radeon/radeon_mem.c | 1 - drivers/gpu/drm/radeon/radeon_mode.h | 1 - drivers/gpu/drm/radeon/radeon_prime.c | 1 - drivers/gpu/drm/radeon/radeon_sa.c | 1 - drivers/gpu/drm/radeon/radeon_semaphore.c | 1 - drivers/gpu/drm/radeon/radeon_state.c | 2 -- drivers/gpu/drm/udl/udl_fb.c | 1 - drivers/gpu/drm/via/via_dma.c | 1 - drivers/gpu/drm/via/via_irq.c | 1 - drivers/gpu/drm/via/via_verifier.c | 1 - 129 files changed, 136 deletions(-) (limited to 'drivers/gpu/drm/gma500') diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index 36164806b9d..d5749b86cae 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -29,7 +29,6 @@ #include #include "drmP.h" -#include "drm.h" #include "drm_crtc_helper.h" #include "ast_drv.h" diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c index 2fc8e9e860b..d0d27923310 100644 --- a/drivers/gpu/drm/ast/ast_fb.c +++ b/drivers/gpu/drm/ast/ast_fb.c @@ -38,7 +38,6 @@ #include "drmP.h" -#include "drm.h" #include "drm_crtc.h" #include "drm_fb_helper.h" #include "ast_drv.h" diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index b83a2d7ddd1..781b90c5a3c 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -11,7 +11,6 @@ #include #include #include "drmP.h" -#include "drm.h" #include "cirrus_drv.h" diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c index 9a276a53699..6aaada5d2b6 100644 --- a/drivers/gpu/drm/cirrus/cirrus_fbdev.c +++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c @@ -10,7 +10,6 @@ */ #include #include "drmP.h" -#include "drm.h" #include "drm_fb_helper.h" #include diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c index e3c12257841..5690d241260 100644 --- a/drivers/gpu/drm/cirrus/cirrus_main.c +++ b/drivers/gpu/drm/cirrus/cirrus_main.c @@ -9,7 +9,6 @@ * Dave Airlie */ #include "drmP.h" -#include "drm.h" #include "drm_crtc_helper.h" #include "cirrus_drv.h" diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index a44d31aa4e3..e70f782a4f2 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -15,7 +15,6 @@ * Copyright 1999-2001 Jeff Garzik */ #include "drmP.h" -#include "drm.h" #include "drm_crtc_helper.h" #include