mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-03-23 19:57:01 +08:00
Merge branch 'drm-gma500-alanc' into drm-core-next
* drm-gma500-alanc: (47 commits) gma500: psb_irq: mark mid_{enable, disable}_pipe_event() as static gma500: mark psb_intel_sdvo_hdmi_sink_detect() as static gma500: psb_intel_display: drop unused variables gma500: mark psb_intel_pipe_set_base() as static gma500: drop unused psb_intel_modeset_cleanup() gma500: oaktrail_lvds_init() drop unused variable gma500: oaktrail_hdmi_i2c_access() drop unused variable gma500: mark oaktrail_backlight_init() as static gma500: oaktrail_hdmi: fix -Wmissing-field-initializers warning gma500: oaktrail_hdmi: drop dead code gma500: oaktrail_crtc: drop unused variables gma500: oaktrail_crtc: mark few functions as static gma500: mdfld_intel_display: drop unused variables gma500: mdfld_dsi_pkg_sender: fix -Wtype-limits warning gma500: mdfld_dsi_dpi: drop unused variables gma500: mdfld_device: mark few functions as static gma500: cdv_intel_lvds: #if 0 currently unused functions gma500: cdv_intel_lvds: mark few functions as static gma500: cdv_intel_hdmi: add missing include gma500: cdv_intel_crt: mark few functions as static ...
This commit is contained in:
commit
83465324cb
@ -28,6 +28,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/mfd/intel_msic.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c/tc35876x.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/mpspec_def.h>
|
||||
@ -686,6 +688,19 @@ static void *msic_ocd_platform_data(void *info)
|
||||
return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD);
|
||||
}
|
||||
|
||||
/* tc35876x DSI-LVDS bridge chip and panel platform data */
|
||||
static void *tc35876x_platform_data(void *data)
|
||||
{
|
||||
static struct tc35876x_platform_data pdata;
|
||||
|
||||
/* gpio pins set to -1 will not be used by the driver */
|
||||
pdata.gpio_bridge_reset = get_gpio_by_name("LCMB_RXEN");
|
||||
pdata.gpio_panel_bl_en = get_gpio_by_name("6S6P_BL_EN");
|
||||
pdata.gpio_panel_vadd = get_gpio_by_name("EN_VREG_LCD_V3P3");
|
||||
|
||||
return &pdata;
|
||||
}
|
||||
|
||||
static const struct devs_id __initconst device_ids[] = {
|
||||
{"bma023", SFI_DEV_TYPE_I2C, 1, &no_platform_data},
|
||||
{"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data},
|
||||
@ -698,6 +713,7 @@ static const struct devs_id __initconst device_ids[] = {
|
||||
{"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data},
|
||||
{"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data},
|
||||
{"mpu3050", SFI_DEV_TYPE_I2C, 1, &mpu3050_platform_data},
|
||||
{"i2c_disp_brig", SFI_DEV_TYPE_I2C, 0, &tc35876x_platform_data},
|
||||
|
||||
/* MSIC subdevices */
|
||||
{"msic_battery", SFI_DEV_TYPE_IPC, 1, &msic_battery_platform_data},
|
||||
|
@ -16,8 +16,7 @@ config DRM_GMA600
|
||||
depends on DRM_GMA500
|
||||
help
|
||||
Say yes to include support for GMA600 (Intel Moorestown/Oaktrail)
|
||||
platforms with LVDS ports. HDMI and MIPI are not currently
|
||||
supported.
|
||||
platforms with LVDS ports. MIPI is not currently supported.
|
||||
|
||||
config DRM_GMA3600
|
||||
bool "Intel GMA3600/3650 support (Experimental)"
|
||||
@ -25,3 +24,10 @@ config DRM_GMA3600
|
||||
help
|
||||
Say yes to include basic support for Intel GMA3600/3650 (Intel
|
||||
Cedar Trail) platforms.
|
||||
|
||||
config DRM_MEDFIELD
|
||||
bool "Intel Medfield support (Experimental)"
|
||||
depends on DRM_GMA500 && X86_INTEL_MID
|
||||
help
|
||||
Say yes to include support for the Intel Medfield platform.
|
||||
|
||||
|
@ -37,4 +37,14 @@ gma500_gfx-$(CONFIG_DRM_GMA600) += oaktrail_device.o \
|
||||
oaktrail_hdmi.o \
|
||||
oaktrail_hdmi_i2c.o
|
||||
|
||||
gma500_gfx-$(CONFIG_DRM_MEDFIELD) += mdfld_device.o \
|
||||
mdfld_output.o \
|
||||
mdfld_intel_display.o \
|
||||
mdfld_dsi_output.o \
|
||||
mdfld_dsi_dpi.o \
|
||||
mdfld_dsi_pkg_sender.o \
|
||||
mdfld_tpo_vid.o \
|
||||
mdfld_tmd_vid.o \
|
||||
tc35876x-dsi-lvds.o
|
||||
|
||||
obj-$(CONFIG_DRM_GMA500) += gma500_gfx.o
|
||||
|
@ -26,7 +26,7 @@ extern void cdv_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *
|
||||
extern struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
|
||||
struct drm_crtc *crtc);
|
||||
|
||||
extern inline void cdv_intel_wait_for_vblank(struct drm_device *dev)
|
||||
static inline void cdv_intel_wait_for_vblank(struct drm_device *dev)
|
||||
{
|
||||
/* Wait for 20ms, i.e. one cycle at 50hz. */
|
||||
/* FIXME: msleep ?? */
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "psb_intel_drv.h"
|
||||
#include "psb_intel_reg.h"
|
||||
#include "power.h"
|
||||
#include "cdv_device.h"
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
|
||||
|
@ -344,7 +344,7 @@ cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
|
||||
/*
|
||||
* Returns whether any encoder on the specified pipe is of the specified type
|
||||
*/
|
||||
bool cdv_intel_pipe_has_type(struct drm_crtc *crtc, int type)
|
||||
static bool cdv_intel_pipe_has_type(struct drm_crtc *crtc, int type)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
@ -476,7 +476,7 @@ static bool cdv_intel_find_best_PLL(struct drm_crtc *crtc, int target,
|
||||
return err != target;
|
||||
}
|
||||
|
||||
int cdv_intel_pipe_set_base(struct drm_crtc *crtc,
|
||||
static int cdv_intel_pipe_set_base(struct drm_crtc *crtc,
|
||||
int x, int y, struct drm_framebuffer *old_fb)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
@ -569,7 +569,6 @@ static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
|
||||
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
|
||||
u32 temp;
|
||||
bool enabled;
|
||||
|
||||
/* XXX: When our outputs are all unaware of DPMS modes other than off
|
||||
* and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
|
||||
@ -663,7 +662,6 @@ static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
udelay(150);
|
||||
break;
|
||||
}
|
||||
enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
|
||||
/*Set FIFO Watermarks*/
|
||||
REG_WRITE(DSPARB, 0x3F3E);
|
||||
}
|
||||
@ -680,22 +678,6 @@ static void cdv_intel_crtc_commit(struct drm_crtc *crtc)
|
||||
crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
|
||||
}
|
||||
|
||||
void cdv_intel_encoder_prepare(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_encoder_helper_funcs *encoder_funcs =
|
||||
encoder->helper_private;
|
||||
/* lvds has its own version of prepare see cdv_intel_lvds_prepare */
|
||||
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
|
||||
}
|
||||
|
||||
void cdv_intel_encoder_commit(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_encoder_helper_funcs *encoder_funcs =
|
||||
encoder->helper_private;
|
||||
/* lvds has its own version of commit see cdv_intel_lvds_commit */
|
||||
encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
|
||||
}
|
||||
|
||||
static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
@ -745,7 +727,7 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
int refclk;
|
||||
struct cdv_intel_clock_t clock;
|
||||
u32 dpll = 0, dspcntr, pipeconf;
|
||||
bool ok, is_sdvo = false, is_dvo = false;
|
||||
bool ok;
|
||||
bool is_crt = false, is_lvds = false, is_tv = false;
|
||||
bool is_hdmi = false;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
@ -763,12 +745,6 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
case INTEL_OUTPUT_LVDS:
|
||||
is_lvds = true;
|
||||
break;
|
||||
case INTEL_OUTPUT_SDVO:
|
||||
is_sdvo = true;
|
||||
break;
|
||||
case INTEL_OUTPUT_DVO:
|
||||
is_dvo = true;
|
||||
break;
|
||||
case INTEL_OUTPUT_TVOUT:
|
||||
is_tv = true;
|
||||
break;
|
||||
@ -928,7 +904,7 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
}
|
||||
|
||||
/** Loads the palette/gamma unit for the CRTC with the prepared values */
|
||||
void cdv_intel_crtc_load_lut(struct drm_crtc *crtc)
|
||||
static void cdv_intel_crtc_load_lut(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_psb_private *dev_priv =
|
||||
@ -968,7 +944,7 @@ void cdv_intel_crtc_load_lut(struct drm_crtc *crtc)
|
||||
gma_power_end(dev);
|
||||
} else {
|
||||
for (i = 0; i < 256; i++) {
|
||||
dev_priv->save_palette_a[i] =
|
||||
dev_priv->regs.psb.save_palette_a[i] =
|
||||
((psb_intel_crtc->lut_r[i] +
|
||||
psb_intel_crtc->lut_adj[i]) << 16) |
|
||||
((psb_intel_crtc->lut_g[i] +
|
||||
@ -1338,18 +1314,20 @@ static int cdv_intel_crtc_clock_get(struct drm_device *dev,
|
||||
gma_power_end(dev);
|
||||
} else {
|
||||
dpll = (pipe == 0) ?
|
||||
dev_priv->saveDPLL_A : dev_priv->saveDPLL_B;
|
||||
dev_priv->regs.psb.saveDPLL_A :
|
||||
dev_priv->regs.psb.saveDPLL_B;
|
||||
|
||||
if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
|
||||
fp = (pipe == 0) ?
|
||||
dev_priv->saveFPA0 :
|
||||
dev_priv->saveFPB0;
|
||||
dev_priv->regs.psb.saveFPA0 :
|
||||
dev_priv->regs.psb.saveFPB0;
|
||||
else
|
||||
fp = (pipe == 0) ?
|
||||
dev_priv->saveFPA1 :
|
||||
dev_priv->saveFPB1;
|
||||
dev_priv->regs.psb.saveFPA1 :
|
||||
dev_priv->regs.psb.saveFPB1;
|
||||
|
||||
is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN);
|
||||
is_lvds = (pipe == 1) &&
|
||||
(dev_priv->regs.psb.saveLVDS & LVDS_PORT_EN);
|
||||
}
|
||||
|
||||
clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
|
||||
@ -1419,13 +1397,17 @@ struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
|
||||
gma_power_end(dev);
|
||||
} else {
|
||||
htot = (pipe == 0) ?
|
||||
dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B;
|
||||
dev_priv->regs.psb.saveHTOTAL_A :
|
||||
dev_priv->regs.psb.saveHTOTAL_B;
|
||||
hsync = (pipe == 0) ?
|
||||
dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B;
|
||||
dev_priv->regs.psb.saveHSYNC_A :
|
||||
dev_priv->regs.psb.saveHSYNC_B;
|
||||
vtot = (pipe == 0) ?
|
||||
dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B;
|
||||
dev_priv->regs.psb.saveVTOTAL_A :
|
||||
dev_priv->regs.psb.saveVTOTAL_B;
|
||||
vsync = (pipe == 0) ?
|
||||
dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B;
|
||||
dev_priv->regs.psb.saveVSYNC_A :
|
||||
dev_priv->regs.psb.saveVSYNC_B;
|
||||
}
|
||||
|
||||
mode = kzalloc(sizeof(*mode), GFP_KERNEL);
|
||||
@ -1475,34 +1457,3 @@ const struct drm_crtc_funcs cdv_intel_crtc_funcs = {
|
||||
.set_config = cdv_crtc_set_config,
|
||||
.destroy = cdv_intel_crtc_destroy,
|
||||
};
|
||||
|
||||
/*
|
||||
* Set the default value of cursor control and base register
|
||||
* to zero. This is a workaround for h/w defect on oaktrail
|
||||
*/
|
||||
void cdv_intel_cursor_init(struct drm_device *dev, int pipe)
|
||||
{
|
||||
uint32_t control;
|
||||
uint32_t base;
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
control = CURACNTR;
|
||||
base = CURABASE;
|
||||
break;
|
||||
case 1:
|
||||
control = CURBCNTR;
|
||||
base = CURBBASE;
|
||||
break;
|
||||
case 2:
|
||||
control = CURCCNTR;
|
||||
base = CURCBASE;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
REG_WRITE(control, 0);
|
||||
REG_WRITE(base, 0);
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "psb_intel_drv.h"
|
||||
#include "psb_drv.h"
|
||||
#include "psb_intel_reg.h"
|
||||
#include "cdv_device.h"
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
/* hdmi control bits */
|
||||
|
@ -78,13 +78,14 @@ static u32 cdv_intel_lvds_get_max_backlight(struct drm_device *dev)
|
||||
|
||||
gma_power_end(dev);
|
||||
} else
|
||||
retval = ((dev_priv->saveBLC_PWM_CTL &
|
||||
retval = ((dev_priv->regs.saveBLC_PWM_CTL &
|
||||
BACKLIGHT_MODULATION_FREQ_MASK) >>
|
||||
BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Set LVDS backlight level by I2C command
|
||||
*/
|
||||
@ -165,6 +166,7 @@ void cdv_intel_lvds_set_brightness(struct drm_device *dev, int level)
|
||||
else
|
||||
cdv_lvds_pwm_set_brightness(dev, level);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Sets the backlight level.
|
||||
@ -184,9 +186,9 @@ static void cdv_intel_lvds_set_backlight(struct drm_device *dev, int level)
|
||||
(level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
|
||||
gma_power_end(dev);
|
||||
} else {
|
||||
blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL &
|
||||
blc_pwm_ctl = dev_priv->regs.saveBLC_PWM_CTL &
|
||||
~BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
|
||||
dev_priv->regs.saveBLC_PWM_CTL = (blc_pwm_ctl |
|
||||
(level << BACKLIGHT_DUTY_CYCLE_SHIFT));
|
||||
}
|
||||
}
|
||||
@ -242,7 +244,7 @@ static void cdv_intel_lvds_restore(struct drm_connector *connector)
|
||||
{
|
||||
}
|
||||
|
||||
int cdv_intel_lvds_mode_valid(struct drm_connector *connector,
|
||||
static int cdv_intel_lvds_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
@ -267,7 +269,7 @@ int cdv_intel_lvds_mode_valid(struct drm_connector *connector,
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
||||
static bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
@ -436,7 +438,7 @@ static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
|
||||
* Unregister the DDC bus for this connector then free the driver private
|
||||
* structure.
|
||||
*/
|
||||
void cdv_intel_lvds_destroy(struct drm_connector *connector)
|
||||
static void cdv_intel_lvds_destroy(struct drm_connector *connector)
|
||||
{
|
||||
struct psb_intel_encoder *psb_intel_encoder =
|
||||
psb_intel_attached_encoder(connector);
|
||||
@ -448,7 +450,7 @@ void cdv_intel_lvds_destroy(struct drm_connector *connector)
|
||||
kfree(connector);
|
||||
}
|
||||
|
||||
int cdv_intel_lvds_set_property(struct drm_connector *connector,
|
||||
static int cdv_intel_lvds_set_property(struct drm_connector *connector,
|
||||
struct drm_property *property,
|
||||
uint64_t value)
|
||||
{
|
||||
|
@ -111,39 +111,6 @@ static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void psbfb_suspend(struct drm_device *dev)
|
||||
{
|
||||
struct drm_framebuffer *fb;
|
||||
|
||||
console_lock();
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
|
||||
struct psb_framebuffer *psbfb = to_psb_fb(fb);
|
||||
struct fb_info *info = psbfb->fbdev;
|
||||
fb_set_suspend(info, 1);
|
||||
drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
|
||||
}
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
console_unlock();
|
||||
}
|
||||
|
||||
void psbfb_resume(struct drm_device *dev)
|
||||
{
|
||||
struct drm_framebuffer *fb;
|
||||
|
||||
console_lock();
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
|
||||
struct psb_framebuffer *psbfb = to_psb_fb(fb);
|
||||
struct fb_info *info = psbfb->fbdev;
|
||||
fb_set_suspend(info, 0);
|
||||
drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
|
||||
}
|
||||
mutex_unlock(&dev->mode_config.mutex);
|
||||
console_unlock();
|
||||
drm_helper_disable_unused_functions(dev);
|
||||
}
|
||||
|
||||
static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
|
||||
{
|
||||
struct psb_framebuffer *psbfb = vma->vm_private_data;
|
||||
@ -391,6 +358,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
|
||||
mode_cmd.width = sizes->surface_width;
|
||||
mode_cmd.height = sizes->surface_height;
|
||||
bpp = sizes->surface_bpp;
|
||||
depth = sizes->surface_depth;
|
||||
|
||||
/* No 24bit packed */
|
||||
if (bpp == 24)
|
||||
@ -403,7 +371,6 @@ static int psbfb_create(struct psb_fbdev *fbdev,
|
||||
* is ok with some fonts
|
||||
*/
|
||||
mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 4096 >> pitch_lines);
|
||||
depth = sizes->surface_depth;
|
||||
|
||||
size = mode_cmd.pitches[0] * mode_cmd.height;
|
||||
size = ALIGN(size, PAGE_SIZE);
|
||||
@ -463,6 +430,7 @@ static int psbfb_create(struct psb_fbdev *fbdev,
|
||||
fbdev->psb_fb_helper.fb = fb;
|
||||
fbdev->psb_fb_helper.fbdev = info;
|
||||
|
||||
drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
|
||||
strcpy(info->fix.id, "psbfb");
|
||||
|
||||
info->flags = FBINFO_DEFAULT;
|
||||
@ -500,7 +468,6 @@ static int psbfb_create(struct psb_fbdev *fbdev,
|
||||
info->apertures->ranges[0].size = dev_priv->gtt.stolen_size;
|
||||
}
|
||||
|
||||
drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
|
||||
drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
|
||||
sizes->fb_width, sizes->fb_height);
|
||||
|
||||
@ -556,11 +523,21 @@ static struct drm_framebuffer *psb_user_framebuffer_create
|
||||
static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
|
||||
u16 blue, int regno)
|
||||
{
|
||||
struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc);
|
||||
|
||||
intel_crtc->lut_r[regno] = red >> 8;
|
||||
intel_crtc->lut_g[regno] = green >> 8;
|
||||
intel_crtc->lut_b[regno] = blue >> 8;
|
||||
}
|
||||
|
||||
static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red,
|
||||
u16 *green, u16 *blue, int regno)
|
||||
{
|
||||
struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc);
|
||||
|
||||
*red = intel_crtc->lut_r[regno] << 8;
|
||||
*green = intel_crtc->lut_g[regno] << 8;
|
||||
*blue = intel_crtc->lut_b[regno] << 8;
|
||||
}
|
||||
|
||||
static int psbfb_probe(struct drm_fb_helper *helper,
|
||||
@ -585,7 +562,7 @@ struct drm_fb_helper_funcs psb_fb_helper_funcs = {
|
||||
.fb_probe = psbfb_probe,
|
||||
};
|
||||
|
||||
int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
|
||||
static int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
|
||||
{
|
||||
struct fb_info *info;
|
||||
struct psb_framebuffer *psbfb = &fbdev->pfb;
|
||||
@ -627,7 +604,7 @@ int psb_fbdev_init(struct drm_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void psb_fbdev_fini(struct drm_device *dev)
|
||||
static void psb_fbdev_fini(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm.h>
|
||||
#include "gem_glue.h"
|
||||
|
||||
void drm_gem_object_release_wrap(struct drm_gem_object *obj)
|
||||
{
|
||||
|
@ -57,7 +57,7 @@ static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type)
|
||||
* Given a gtt_range object return the GTT offset of the page table
|
||||
* entries for this gtt_range
|
||||
*/
|
||||
u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
|
||||
static u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
unsigned long offset;
|
||||
@ -378,7 +378,7 @@ void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt)
|
||||
kfree(gt);
|
||||
}
|
||||
|
||||
void psb_gtt_alloc(struct drm_device *dev)
|
||||
static void psb_gtt_alloc(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
init_rwsem(&dev_priv->gtt.sem);
|
||||
|
691
drivers/gpu/drm/gma500/mdfld_device.c
Normal file
691
drivers/gpu/drm/gma500/mdfld_device.c
Normal file
@ -0,0 +1,691 @@
|
||||
/**************************************************************************
|
||||
* 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 "psb_drv.h"
|
||||
#include "mid_bios.h"
|
||||
#include "mdfld_output.h"
|
||||
#include "mdfld_dsi_output.h"
|
||||
#include "tc35876x-dsi-lvds.h"
|
||||
|
||||
#include <asm/intel_scu_ipc.h>
|
||||
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
|
||||
#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
|
||||
#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
|
||||
#define BLC_PWM_FREQ_CALC_CONSTANT 32
|
||||
#define MHz 1000000
|
||||
#define BRIGHTNESS_MIN_LEVEL 1
|
||||
#define BRIGHTNESS_MAX_LEVEL 100
|
||||
#define BRIGHTNESS_MASK 0xFF
|
||||
#define BLC_POLARITY_NORMAL 0
|
||||
#define BLC_POLARITY_INVERSE 1
|
||||
#define BLC_ADJUSTMENT_MAX 100
|
||||
|
||||
#define MDFLD_BLC_PWM_PRECISION_FACTOR 10
|
||||
#define MDFLD_BLC_MAX_PWM_REG_FREQ 0xFFFE
|
||||
#define MDFLD_BLC_MIN_PWM_REG_FREQ 0x2
|
||||
|
||||
#define MDFLD_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
|
||||
#define MDFLD_BACKLIGHT_PWM_CTL_SHIFT (16)
|
||||
|
||||
static struct backlight_device *mdfld_backlight_device;
|
||||
|
||||
int mdfld_set_brightness(struct backlight_device *bd)
|
||||
{
|
||||
struct drm_device *dev =
|
||||
(struct drm_device *)bl_get_data(mdfld_backlight_device);
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
int level = bd->props.brightness;
|
||||
|
||||
DRM_DEBUG_DRIVER("backlight level set to %d\n", level);
|
||||
|
||||
/* Perform value bounds checking */
|
||||
if (level < BRIGHTNESS_MIN_LEVEL)
|
||||
level = BRIGHTNESS_MIN_LEVEL;
|
||||
|
||||
if (gma_power_begin(dev, false)) {
|
||||
u32 adjusted_level = 0;
|
||||
|
||||
/*
|
||||
* Adjust the backlight level with the percent in
|
||||
* dev_priv->blc_adj2
|
||||
*/
|
||||
adjusted_level = level * dev_priv->blc_adj2;
|
||||
adjusted_level = adjusted_level / BLC_ADJUSTMENT_MAX;
|
||||
dev_priv->brightness_adjusted = adjusted_level;
|
||||
|
||||
if (mdfld_get_panel_type(dev, 0) == TC35876X) {
|
||||
if (dev_priv->dpi_panel_on[0] ||
|
||||
dev_priv->dpi_panel_on[2])
|
||||
tc35876x_brightness_control(dev,
|
||||
dev_priv->brightness_adjusted);
|
||||
} else {
|
||||
if (dev_priv->dpi_panel_on[0])
|
||||
mdfld_dsi_brightness_control(dev, 0,
|
||||
dev_priv->brightness_adjusted);
|
||||
}
|
||||
|
||||
if (dev_priv->dpi_panel_on[2])
|
||||
mdfld_dsi_brightness_control(dev, 2,
|
||||
dev_priv->brightness_adjusted);
|
||||
gma_power_end(dev);
|
||||
}
|
||||
|
||||
/* cache the brightness for later use */
|
||||
dev_priv->brightness = level;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mdfld_get_brightness(struct backlight_device *bd)
|
||||
{
|
||||
struct drm_device *dev =
|
||||
(struct drm_device *)bl_get_data(mdfld_backlight_device);
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
|
||||
DRM_DEBUG_DRIVER("brightness = 0x%x \n", dev_priv->brightness);
|
||||
|
||||
/* return locally cached var instead of HW read (due to DPST etc.) */
|
||||
return dev_priv->brightness;
|
||||
}
|
||||
|
||||
static const struct backlight_ops mdfld_ops = {
|
||||
.get_brightness = mdfld_get_brightness,
|
||||
.update_status = mdfld_set_brightness,
|
||||
};
|
||||
|
||||
static int device_backlight_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = (struct drm_psb_private *)
|
||||
dev->dev_private;
|
||||
|
||||
dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
|
||||
dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mdfld_backlight_init(struct drm_device *dev)
|
||||
{
|
||||
struct backlight_properties props;
|
||||
int ret = 0;
|
||||
|
||||
memset(&props, 0, sizeof(struct backlight_properties));
|
||||
props.max_brightness = BRIGHTNESS_MAX_LEVEL;
|
||||
props.type = BACKLIGHT_PLATFORM;
|
||||
mdfld_backlight_device = backlight_device_register("mdfld-bl",
|
||||
NULL, (void *)dev, &mdfld_ops, &props);
|
||||
|
||||
if (IS_ERR(mdfld_backlight_device))
|
||||
return PTR_ERR(mdfld_backlight_device);
|
||||
|
||||
ret = device_backlight_init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mdfld_backlight_device->props.brightness = BRIGHTNESS_MAX_LEVEL;
|
||||
mdfld_backlight_device->props.max_brightness = BRIGHTNESS_MAX_LEVEL;
|
||||
backlight_update_status(mdfld_backlight_device);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct backlight_device *mdfld_get_backlight_device(void)
|
||||
{
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
return mdfld_backlight_device;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* mdfld_save_display_registers
|
||||
*
|
||||
* Description: We are going to suspend so save current display
|
||||
* register state.
|
||||
*
|
||||
* Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
|
||||
*/
|
||||
static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct medfield_state *regs = &dev_priv->regs.mdfld;
|
||||
int i;
|
||||
|
||||
/* register */
|
||||
u32 dpll_reg = MRST_DPLL_A;
|
||||
u32 fp_reg = MRST_FPA0;
|
||||
u32 pipeconf_reg = PIPEACONF;
|
||||
u32 htot_reg = HTOTAL_A;
|
||||
u32 hblank_reg = HBLANK_A;
|
||||
u32 hsync_reg = HSYNC_A;
|
||||
u32 vtot_reg = VTOTAL_A;
|
||||
u32 vblank_reg = VBLANK_A;
|
||||
u32 vsync_reg = VSYNC_A;
|
||||
u32 pipesrc_reg = PIPEASRC;
|
||||
u32 dspstride_reg = DSPASTRIDE;
|
||||
u32 dsplinoff_reg = DSPALINOFF;
|
||||
u32 dsptileoff_reg = DSPATILEOFF;
|
||||
u32 dspsize_reg = DSPASIZE;
|
||||
u32 dsppos_reg = DSPAPOS;
|
||||
u32 dspsurf_reg = DSPASURF;
|
||||
u32 mipi_reg = MIPI;
|
||||
u32 dspcntr_reg = DSPACNTR;
|
||||
u32 dspstatus_reg = PIPEASTAT;
|
||||
u32 palette_reg = PALETTE_A;
|
||||
|
||||
/* pointer to values */
|
||||
u32 *dpll_val = ®s->saveDPLL_A;
|
||||
u32 *fp_val = ®s->saveFPA0;
|
||||
u32 *pipeconf_val = ®s->savePIPEACONF;
|
||||
u32 *htot_val = ®s->saveHTOTAL_A;
|
||||
u32 *hblank_val = ®s->saveHBLANK_A;
|
||||
u32 *hsync_val = ®s->saveHSYNC_A;
|
||||
u32 *vtot_val = ®s->saveVTOTAL_A;
|
||||
u32 *vblank_val = ®s->saveVBLANK_A;
|
||||
u32 *vsync_val = ®s->saveVSYNC_A;
|
||||
u32 *pipesrc_val = ®s->savePIPEASRC;
|
||||
u32 *dspstride_val = ®s->saveDSPASTRIDE;
|
||||
u32 *dsplinoff_val = ®s->saveDSPALINOFF;
|
||||
u32 *dsptileoff_val = ®s->saveDSPATILEOFF;
|
||||
u32 *dspsize_val = ®s->saveDSPASIZE;
|
||||
u32 *dsppos_val = ®s->saveDSPAPOS;
|
||||
u32 *dspsurf_val = ®s->saveDSPASURF;
|
||||
u32 *mipi_val = ®s->saveMIPI;
|
||||
u32 *dspcntr_val = ®s->saveDSPACNTR;
|
||||
u32 *dspstatus_val = ®s->saveDSPASTATUS;
|
||||
u32 *palette_val = regs->save_palette_a;
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
/* regester */
|
||||
dpll_reg = MDFLD_DPLL_B;
|
||||
fp_reg = MDFLD_DPLL_DIV0;
|
||||
pipeconf_reg = PIPEBCONF;
|
||||
htot_reg = HTOTAL_B;
|
||||
hblank_reg = HBLANK_B;
|
||||
hsync_reg = HSYNC_B;
|
||||
vtot_reg = VTOTAL_B;
|
||||
vblank_reg = VBLANK_B;
|
||||
vsync_reg = VSYNC_B;
|
||||
pipesrc_reg = PIPEBSRC;
|
||||
dspstride_reg = DSPBSTRIDE;
|
||||
dsplinoff_reg = DSPBLINOFF;
|
||||
dsptileoff_reg = DSPBTILEOFF;
|
||||
dspsize_reg = DSPBSIZE;
|
||||
dsppos_reg = DSPBPOS;
|
||||
dspsurf_reg = DSPBSURF;
|
||||
dspcntr_reg = DSPBCNTR;
|
||||
dspstatus_reg = PIPEBSTAT;
|
||||
palette_reg = PALETTE_B;
|
||||
|
||||
/* values */
|
||||
dpll_val = ®s->saveDPLL_B;
|
||||
fp_val = ®s->saveFPB0;
|
||||
pipeconf_val = ®s->savePIPEBCONF;
|
||||
htot_val = ®s->saveHTOTAL_B;
|
||||
hblank_val = ®s->saveHBLANK_B;
|
||||
hsync_val = ®s->saveHSYNC_B;
|
||||
vtot_val = ®s->saveVTOTAL_B;
|
||||
vblank_val = ®s->saveVBLANK_B;
|
||||
vsync_val = ®s->saveVSYNC_B;
|
||||
pipesrc_val = ®s->savePIPEBSRC;
|
||||
dspstride_val = ®s->saveDSPBSTRIDE;
|
||||
dsplinoff_val = ®s->saveDSPBLINOFF;
|
||||
dsptileoff_val = ®s->saveDSPBTILEOFF;
|
||||
dspsize_val = ®s->saveDSPBSIZE;
|
||||
dsppos_val = ®s->saveDSPBPOS;
|
||||
dspsurf_val = ®s->saveDSPBSURF;
|
||||
dspcntr_val = ®s->saveDSPBCNTR;
|
||||
dspstatus_val = ®s->saveDSPBSTATUS;
|
||||
palette_val = regs->save_palette_b;
|
||||
break;
|
||||
case 2:
|
||||
/* register */
|
||||
pipeconf_reg = PIPECCONF;
|
||||
htot_reg = HTOTAL_C;
|
||||
hblank_reg = HBLANK_C;
|
||||
hsync_reg = HSYNC_C;
|
||||
vtot_reg = VTOTAL_C;
|
||||
vblank_reg = VBLANK_C;
|
||||
vsync_reg = VSYNC_C;
|
||||
pipesrc_reg = PIPECSRC;
|
||||
dspstride_reg = DSPCSTRIDE;
|
||||
dsplinoff_reg = DSPCLINOFF;
|
||||
dsptileoff_reg = DSPCTILEOFF;
|
||||
dspsize_reg = DSPCSIZE;
|
||||
dsppos_reg = DSPCPOS;
|
||||
dspsurf_reg = DSPCSURF;
|
||||
mipi_reg = MIPI_C;
|
||||
dspcntr_reg = DSPCCNTR;
|
||||
dspstatus_reg = PIPECSTAT;
|
||||
palette_reg = PALETTE_C;
|
||||
|
||||
/* pointer to values */
|
||||
pipeconf_val = ®s->savePIPECCONF;
|
||||
htot_val = ®s->saveHTOTAL_C;
|
||||
hblank_val = ®s->saveHBLANK_C;
|
||||
hsync_val = ®s->saveHSYNC_C;
|
||||
vtot_val = ®s->saveVTOTAL_C;
|
||||
vblank_val = ®s->saveVBLANK_C;
|
||||
vsync_val = ®s->saveVSYNC_C;
|
||||
pipesrc_val = ®s->savePIPECSRC;
|
||||
dspstride_val = ®s->saveDSPCSTRIDE;
|
||||
dsplinoff_val = ®s->saveDSPCLINOFF;
|
||||
dsptileoff_val = ®s->saveDSPCTILEOFF;
|
||||
dspsize_val = ®s->saveDSPCSIZE;
|
||||
dsppos_val = ®s->saveDSPCPOS;
|
||||
dspsurf_val = ®s->saveDSPCSURF;
|
||||
mipi_val = ®s->saveMIPI_C;
|
||||
dspcntr_val = ®s->saveDSPCCNTR;
|
||||
dspstatus_val = ®s->saveDSPCSTATUS;
|
||||
palette_val = regs->save_palette_c;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("%s, invalid pipe number.\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Pipe & plane A info */
|
||||
*dpll_val = PSB_RVDC32(dpll_reg);
|
||||
*fp_val = PSB_RVDC32(fp_reg);
|
||||
*pipeconf_val = PSB_RVDC32(pipeconf_reg);
|
||||
*htot_val = PSB_RVDC32(htot_reg);
|
||||
*hblank_val = PSB_RVDC32(hblank_reg);
|
||||
*hsync_val = PSB_RVDC32(hsync_reg);
|
||||
*vtot_val = PSB_RVDC32(vtot_reg);
|
||||
*vblank_val = PSB_RVDC32(vblank_reg);
|
||||
*vsync_val = PSB_RVDC32(vsync_reg);
|
||||
*pipesrc_val = PSB_RVDC32(pipesrc_reg);
|
||||
*dspstride_val = PSB_RVDC32(dspstride_reg);
|
||||
*dsplinoff_val = PSB_RVDC32(dsplinoff_reg);
|
||||
*dsptileoff_val = PSB_RVDC32(dsptileoff_reg);
|
||||
*dspsize_val = PSB_RVDC32(dspsize_reg);
|
||||
*dsppos_val = PSB_RVDC32(dsppos_reg);
|
||||
*dspsurf_val = PSB_RVDC32(dspsurf_reg);
|
||||
*dspcntr_val = PSB_RVDC32(dspcntr_reg);
|
||||
*dspstatus_val = PSB_RVDC32(dspstatus_reg);
|
||||
|
||||
/*save palette (gamma) */
|
||||
for (i = 0; i < 256; i++)
|
||||
palette_val[i] = PSB_RVDC32(palette_reg + (i << 2));
|
||||
|
||||
if (pipe == 1) {
|
||||
regs->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
|
||||
regs->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
|
||||
|
||||
regs->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
|
||||
regs->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*mipi_val = PSB_RVDC32(mipi_reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* mdfld_restore_display_registers
|
||||
*
|
||||
* Description: We are going to resume so restore display register state.
|
||||
*
|
||||
* Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
|
||||
*/
|
||||
static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
|
||||
{
|
||||
/* To get panel out of ULPS mode. */
|
||||
u32 temp = 0;
|
||||
u32 device_ready_reg = DEVICE_READY_REG;
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct mdfld_dsi_config *dsi_config = NULL;
|
||||
struct medfield_state *regs = &dev_priv->regs.mdfld;
|
||||
u32 i = 0;
|
||||
u32 dpll = 0;
|
||||
u32 timeout = 0;
|
||||
|
||||
/* regester */
|
||||
u32 dpll_reg = MRST_DPLL_A;
|
||||
u32 fp_reg = MRST_FPA0;
|
||||
u32 pipeconf_reg = PIPEACONF;
|
||||
u32 htot_reg = HTOTAL_A;
|
||||
u32 hblank_reg = HBLANK_A;
|
||||
u32 hsync_reg = HSYNC_A;
|
||||
u32 vtot_reg = VTOTAL_A;
|
||||
u32 vblank_reg = VBLANK_A;
|
||||
u32 vsync_reg = VSYNC_A;
|
||||
u32 pipesrc_reg = PIPEASRC;
|
||||
u32 dspstride_reg = DSPASTRIDE;
|
||||
u32 dsplinoff_reg = DSPALINOFF;
|
||||
u32 dsptileoff_reg = DSPATILEOFF;
|
||||
u32 dspsize_reg = DSPASIZE;
|
||||
u32 dsppos_reg = DSPAPOS;
|
||||
u32 dspsurf_reg = DSPASURF;
|
||||
u32 dspstatus_reg = PIPEASTAT;
|
||||
u32 mipi_reg = MIPI;
|
||||
u32 dspcntr_reg = DSPACNTR;
|
||||
u32 palette_reg = PALETTE_A;
|
||||
|
||||
/* values */
|
||||
u32 dpll_val = regs->saveDPLL_A & ~DPLL_VCO_ENABLE;
|
||||
u32 fp_val = regs->saveFPA0;
|
||||
u32 pipeconf_val = regs->savePIPEACONF;
|
||||
u32 htot_val = regs->saveHTOTAL_A;
|
||||
u32 hblank_val = regs->saveHBLANK_A;
|
||||
u32 hsync_val = regs->saveHSYNC_A;
|
||||
u32 vtot_val = regs->saveVTOTAL_A;
|
||||
u32 vblank_val = regs->saveVBLANK_A;
|
||||
u32 vsync_val = regs->saveVSYNC_A;
|
||||
u32 pipesrc_val = regs->savePIPEASRC;
|
||||
u32 dspstride_val = regs->saveDSPASTRIDE;
|
||||
u32 dsplinoff_val = regs->saveDSPALINOFF;
|
||||
u32 dsptileoff_val = regs->saveDSPATILEOFF;
|
||||
u32 dspsize_val = regs->saveDSPASIZE;
|
||||
u32 dsppos_val = regs->saveDSPAPOS;
|
||||
u32 dspsurf_val = regs->saveDSPASURF;
|
||||
u32 dspstatus_val = regs->saveDSPASTATUS;
|
||||
u32 mipi_val = regs->saveMIPI;
|
||||
u32 dspcntr_val = regs->saveDSPACNTR;
|
||||
u32 *palette_val = regs->save_palette_a;
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
dsi_config = dev_priv->dsi_configs[0];
|
||||
break;
|
||||
case 1:
|
||||
/* regester */
|
||||
dpll_reg = MDFLD_DPLL_B;
|
||||
fp_reg = MDFLD_DPLL_DIV0;
|
||||
pipeconf_reg = PIPEBCONF;
|
||||
htot_reg = HTOTAL_B;
|
||||
hblank_reg = HBLANK_B;
|
||||
hsync_reg = HSYNC_B;
|
||||
vtot_reg = VTOTAL_B;
|
||||
vblank_reg = VBLANK_B;
|
||||
vsync_reg = VSYNC_B;
|
||||
pipesrc_reg = PIPEBSRC;
|
||||
dspstride_reg = DSPBSTRIDE;
|
||||
dsplinoff_reg = DSPBLINOFF;
|
||||
dsptileoff_reg = DSPBTILEOFF;
|
||||
dspsize_reg = DSPBSIZE;
|
||||
dsppos_reg = DSPBPOS;
|
||||
dspsurf_reg = DSPBSURF;
|
||||
dspcntr_reg = DSPBCNTR;
|
||||
dspstatus_reg = PIPEBSTAT;
|
||||
palette_reg = PALETTE_B;
|
||||
|
||||
/* values */
|
||||
dpll_val = regs->saveDPLL_B & ~DPLL_VCO_ENABLE;
|
||||
fp_val = regs->saveFPB0;
|
||||
pipeconf_val = regs->savePIPEBCONF;
|
||||
htot_val = regs->saveHTOTAL_B;
|
||||
hblank_val = regs->saveHBLANK_B;
|
||||
hsync_val = regs->saveHSYNC_B;
|
||||
vtot_val = regs->saveVTOTAL_B;
|
||||
vblank_val = regs->saveVBLANK_B;
|
||||
vsync_val = regs->saveVSYNC_B;
|
||||
pipesrc_val = regs->savePIPEBSRC;
|
||||
dspstride_val = regs->saveDSPBSTRIDE;
|
||||
dsplinoff_val = regs->saveDSPBLINOFF;
|
||||
dsptileoff_val = regs->saveDSPBTILEOFF;
|
||||
dspsize_val = regs->saveDSPBSIZE;
|
||||
dsppos_val = regs->saveDSPBPOS;
|
||||
dspsurf_val = regs->saveDSPBSURF;
|
||||
dspcntr_val = regs->saveDSPBCNTR;
|
||||
dspstatus_val = regs->saveDSPBSTATUS;
|
||||
palette_val = regs->save_palette_b;
|
||||
break;
|
||||
case 2:
|
||||
/* regester */
|
||||
pipeconf_reg = PIPECCONF;
|
||||
htot_reg = HTOTAL_C;
|
||||
hblank_reg = HBLANK_C;
|
||||
hsync_reg = HSYNC_C;
|
||||
vtot_reg = VTOTAL_C;
|
||||
vblank_reg = VBLANK_C;
|
||||
vsync_reg = VSYNC_C;
|
||||
pipesrc_reg = PIPECSRC;
|
||||
dspstride_reg = DSPCSTRIDE;
|
||||
dsplinoff_reg = DSPCLINOFF;
|
||||
dsptileoff_reg = DSPCTILEOFF;
|
||||
dspsize_reg = DSPCSIZE;
|
||||
dsppos_reg = DSPCPOS;
|
||||
dspsurf_reg = DSPCSURF;
|
||||
mipi_reg = MIPI_C;
|
||||
dspcntr_reg = DSPCCNTR;
|
||||
dspstatus_reg = PIPECSTAT;
|
||||
palette_reg = PALETTE_C;
|
||||
|
||||
/* values */
|
||||
pipeconf_val = regs->savePIPECCONF;
|
||||
htot_val = regs->saveHTOTAL_C;
|
||||
hblank_val = regs->saveHBLANK_C;
|
||||
hsync_val = regs->saveHSYNC_C;
|
||||
vtot_val = regs->saveVTOTAL_C;
|
||||
vblank_val = regs->saveVBLANK_C;
|
||||
vsync_val = regs->saveVSYNC_C;
|
||||
pipesrc_val = regs->savePIPECSRC;
|
||||
dspstride_val = regs->saveDSPCSTRIDE;
|
||||
dsplinoff_val = regs->saveDSPCLINOFF;
|
||||
dsptileoff_val = regs->saveDSPCTILEOFF;
|
||||
dspsize_val = regs->saveDSPCSIZE;
|
||||
dsppos_val = regs->saveDSPCPOS;
|
||||
dspsurf_val = regs->saveDSPCSURF;
|
||||
mipi_val = regs->saveMIPI_C;
|
||||
dspcntr_val = regs->saveDSPCCNTR;
|
||||
dspstatus_val = regs->saveDSPCSTATUS;
|
||||
palette_val = regs->save_palette_c;
|
||||
|
||||
dsi_config = dev_priv->dsi_configs[1];
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("%s, invalid pipe number.\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*make sure VGA plane is off. it initializes to on after reset!*/
|
||||
PSB_WVDC32(0x80000000, VGACNTRL);
|
||||
|
||||
if (pipe == 1) {
|
||||
PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
|
||||
PSB_RVDC32(dpll_reg);
|
||||
|
||||
PSB_WVDC32(fp_val, fp_reg);
|
||||
} else {
|
||||
|
||||
dpll = PSB_RVDC32(dpll_reg);
|
||||
|
||||
if (!(dpll & DPLL_VCO_ENABLE)) {
|
||||
|
||||
/* When ungating power of DPLL, needs to wait 0.5us
|
||||
before enable the VCO */
|
||||
if (dpll & MDFLD_PWR_GATE_EN) {
|
||||
dpll &= ~MDFLD_PWR_GATE_EN;
|
||||
PSB_WVDC32(dpll, dpll_reg);
|
||||
/* FIXME_MDFLD PO - change 500 to 1 after PO */
|
||||
udelay(500);
|
||||
}
|
||||
|
||||
PSB_WVDC32(fp_val, fp_reg);
|
||||
PSB_WVDC32(dpll_val, dpll_reg);
|
||||
/* FIXME_MDFLD PO - change 500 to 1 after PO */
|
||||
udelay(500);
|
||||
|
||||
dpll_val |= DPLL_VCO_ENABLE;
|
||||
PSB_WVDC32(dpll_val, dpll_reg);
|
||||
PSB_RVDC32(dpll_reg);
|
||||
|
||||
/* wait for DSI PLL to lock */
|
||||
while (timeout < 20000 &&
|
||||
!(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
|
||||
udelay(150);
|
||||
timeout++;
|
||||
}
|
||||
|
||||
if (timeout == 20000) {
|
||||
DRM_ERROR("%s, can't lock DSIPLL.\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Restore mode */
|
||||
PSB_WVDC32(htot_val, htot_reg);
|
||||
PSB_WVDC32(hblank_val, hblank_reg);
|
||||
PSB_WVDC32(hsync_val, hsync_reg);
|
||||
PSB_WVDC32(vtot_val, vtot_reg);
|
||||
PSB_WVDC32(vblank_val, vblank_reg);
|
||||
PSB_WVDC32(vsync_val, vsync_reg);
|
||||
PSB_WVDC32(pipesrc_val, pipesrc_reg);
|
||||
PSB_WVDC32(dspstatus_val, dspstatus_reg);
|
||||
|
||||
/*set up the plane*/
|
||||
PSB_WVDC32(dspstride_val, dspstride_reg);
|
||||
PSB_WVDC32(dsplinoff_val, dsplinoff_reg);
|
||||
PSB_WVDC32(dsptileoff_val, dsptileoff_reg);
|
||||
PSB_WVDC32(dspsize_val, dspsize_reg);
|
||||
PSB_WVDC32(dsppos_val, dsppos_reg);
|
||||
PSB_WVDC32(dspsurf_val, dspsurf_reg);
|
||||
|
||||
if (pipe == 1) {
|
||||
/* restore palette (gamma) */
|
||||
/*DRM_UDELAY(50000); */
|
||||
for (i = 0; i < 256; i++)
|
||||
PSB_WVDC32(palette_val[i], palette_reg + (i << 2));
|
||||
|
||||
PSB_WVDC32(regs->savePFIT_CONTROL, PFIT_CONTROL);
|
||||
PSB_WVDC32(regs->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
|
||||
|
||||
/*TODO: resume HDMI port */
|
||||
|
||||
/*TODO: resume pipe*/
|
||||
|
||||
/*enable the plane*/
|
||||
PSB_WVDC32(dspcntr_val & ~DISPLAY_PLANE_ENABLE, dspcntr_reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*set up pipe related registers*/
|
||||
PSB_WVDC32(mipi_val, mipi_reg);
|
||||
|
||||
/*setup MIPI adapter + MIPI IP registers*/
|
||||
if (dsi_config)
|
||||
mdfld_dsi_controller_init(dsi_config, pipe);
|
||||
|
||||
if (in_atomic() || in_interrupt())
|
||||
mdelay(20);
|
||||
else
|
||||
msleep(20);
|
||||
|
||||
/*enable the plane*/
|
||||
PSB_WVDC32(dspcntr_val, dspcntr_reg);
|
||||
|
||||
if (in_atomic() || in_interrupt())
|
||||
mdelay(20);
|
||||
else
|
||||
msleep(20);
|
||||
|
||||
/* LP Hold Release */
|
||||
temp = REG_READ(mipi_reg);
|
||||
temp |= LP_OUTPUT_HOLD_RELEASE;
|
||||
REG_WRITE(mipi_reg, temp);
|
||||
mdelay(1);
|
||||
|
||||
|
||||
/* Set DSI host to exit from Utra Low Power State */
|
||||
temp = REG_READ(device_ready_reg);
|
||||
temp &= ~ULPS_MASK;
|
||||
temp |= 0x3;
|
||||
temp |= EXIT_ULPS_DEV_READY;
|
||||
REG_WRITE(device_ready_reg, temp);
|
||||
mdelay(1);
|
||||
|
||||
temp = REG_READ(device_ready_reg);
|
||||
temp &= ~ULPS_MASK;
|
||||
temp |= EXITING_ULPS;
|
||||
REG_WRITE(device_ready_reg, temp);
|
||||
mdelay(1);
|
||||
|
||||
/*enable the pipe*/
|
||||
PSB_WVDC32(pipeconf_val, pipeconf_reg);
|
||||
|
||||
/* restore palette (gamma) */
|
||||
/*DRM_UDELAY(50000); */
|
||||
for (i = 0; i < 256; i++)
|
||||
PSB_WVDC32(palette_val[i], palette_reg + (i << 2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mdfld_save_registers(struct drm_device *dev)
|
||||
{
|
||||
/* mdfld_save_cursor_overlay_registers(dev); */
|
||||
mdfld_save_display_registers(dev, 0);
|
||||
mdfld_save_display_registers(dev, 2);
|
||||
mdfld_disable_crtc(dev, 0);
|
||||
mdfld_disable_crtc(dev, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mdfld_restore_registers(struct drm_device *dev)
|
||||
{
|
||||
mdfld_restore_display_registers(dev, 2);
|
||||
mdfld_restore_display_registers(dev, 0);
|
||||
/* mdfld_restore_cursor_overlay_registers(dev); */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mdfld_power_down(struct drm_device *dev)
|
||||
{
|
||||
/* FIXME */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mdfld_power_up(struct drm_device *dev)
|
||||
{
|
||||
/* FIXME */
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct psb_ops mdfld_chip_ops = {
|
||||
.name = "mdfld",
|
||||
.accel_2d = 0,
|
||||
.pipes = 3,
|
||||
.crtcs = 3,
|
||||
.sgx_offset = MRST_SGX_OFFSET,
|
||||
|
||||
.chip_setup = mid_chip_setup,
|
||||
.crtc_helper = &mdfld_helper_funcs,
|
||||
.crtc_funcs = &psb_intel_crtc_funcs,
|
||||
|
||||
.output_init = mdfld_output_init,
|
||||
|
||||
#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
|
||||
.backlight_init = mdfld_backlight_init,
|
||||
#endif
|
||||
|
||||
.save_regs = mdfld_save_registers,
|
||||
.restore_regs = mdfld_restore_registers,
|
||||
.power_down = mdfld_power_down,
|
||||
.power_up = mdfld_power_up,
|
||||
};
|
1017
drivers/gpu/drm/gma500/mdfld_dsi_dpi.c
Normal file
1017
drivers/gpu/drm/gma500/mdfld_dsi_dpi.c
Normal file
File diff suppressed because it is too large
Load Diff
79
drivers/gpu/drm/gma500/mdfld_dsi_dpi.h
Normal file
79
drivers/gpu/drm/gma500/mdfld_dsi_dpi.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright © 2010 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:
|
||||
* jim liu <jim.liu@intel.com>
|
||||
* Jackie Li<yaodong.li@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef __MDFLD_DSI_DPI_H__
|
||||
#define __MDFLD_DSI_DPI_H__
|
||||
|
||||
#include "mdfld_dsi_output.h"
|
||||
#include "mdfld_output.h"
|
||||
|
||||
struct mdfld_dsi_dpi_timing {
|
||||
u16 hsync_count;
|
||||
u16 hbp_count;
|
||||
u16 hfp_count;
|
||||
u16 hactive_count;
|
||||
u16 vsync_count;
|
||||
u16 vbp_count;
|
||||
u16 vfp_count;
|
||||
};
|
||||
|
||||
struct mdfld_dsi_dpi_output {
|
||||
struct mdfld_dsi_encoder base;
|
||||
struct drm_device *dev;
|
||||
|
||||
int panel_on;
|
||||
int first_boot;
|
||||
|
||||
const struct panel_funcs *p_funcs;
|
||||
};
|
||||
|
||||
#define MDFLD_DSI_DPI_OUTPUT(dsi_encoder)\
|
||||
container_of(dsi_encoder, struct mdfld_dsi_dpi_output, base)
|
||||
|
||||
/* Export functions */
|
||||
extern int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode,
|
||||
struct mdfld_dsi_dpi_timing *dpi_timing,
|
||||
int num_lane, int bpp);
|
||||
extern struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
|
||||
struct mdfld_dsi_connector *dsi_connector,
|
||||
const struct panel_funcs *p_funcs);
|
||||
|
||||
/* MDFLD DPI helper functions */
|
||||
extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode);
|
||||
extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder);
|
||||
extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder);
|
||||
extern void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
extern void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output,
|
||||
int pipe);
|
||||
extern void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config,
|
||||
int pipe);
|
||||
#endif /*__MDFLD_DSI_DPI_H__*/
|
618
drivers/gpu/drm/gma500/mdfld_dsi_output.c
Normal file
618
drivers/gpu/drm/gma500/mdfld_dsi_output.c
Normal file
@ -0,0 +1,618 @@
|
||||
/*
|
||||
* Copyright © 2010 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:
|
||||
* jim liu <jim.liu@intel.com>
|
||||
* Jackie Li<yaodong.li@intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "mdfld_dsi_output.h"
|
||||
#include "mdfld_dsi_dpi.h"
|
||||
#include "mdfld_output.h"
|
||||
#include "mdfld_dsi_pkg_sender.h"
|
||||
#include "tc35876x-dsi-lvds.h"
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <asm/intel_scu_ipc.h>
|
||||
|
||||
/* get the LABC from command line. */
|
||||
static int LABC_control = 1;
|
||||
|
||||
#ifdef MODULE
|
||||
module_param(LABC_control, int, 0644);
|
||||
#else
|
||||
|
||||
static int __init parse_LABC_control(char *arg)
|
||||
{
|
||||
/* LABC control can be passed in as a cmdline parameter */
|
||||
/* to enable this feature add LABC=1 to cmdline */
|
||||
/* to disable this feature add LABC=0 to cmdline */
|
||||
if (!arg)
|
||||
return -EINVAL;
|
||||
|
||||
if (!strcasecmp(arg, "0"))
|
||||
LABC_control = 0;
|
||||
else if (!strcasecmp(arg, "1"))
|
||||
LABC_control = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
early_param("LABC", parse_LABC_control);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check and see if the generic control or data buffer is empty and ready.
|
||||
*/
|
||||
void mdfld_dsi_gen_fifo_ready(struct drm_device *dev, u32 gen_fifo_stat_reg,
|
||||
u32 fifo_stat)
|
||||
{
|
||||
u32 GEN_BF_time_out_count;
|
||||
|
||||
/* Check MIPI Adatper command registers */
|
||||
for (GEN_BF_time_out_count = 0;
|
||||
GEN_BF_time_out_count < GEN_FB_TIME_OUT;
|
||||
GEN_BF_time_out_count++) {
|
||||
if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat)
|
||||
break;
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
if (GEN_BF_time_out_count == GEN_FB_TIME_OUT)
|
||||
DRM_ERROR("mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x.\n",
|
||||
gen_fifo_stat_reg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the DSI MIPI keyboard and display brightness.
|
||||
* FIXME: this is exported to OSPM code. should work out an specific
|
||||
* display interface to OSPM.
|
||||
*/
|
||||
|
||||
void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe)
|
||||
{
|
||||
struct mdfld_dsi_pkg_sender *sender =
|
||||
mdfld_dsi_get_pkg_sender(dsi_config);
|
||||
struct drm_device *dev = sender->dev;
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
u32 gen_ctrl_val;
|
||||
|
||||
if (!sender) {
|
||||
DRM_ERROR("No sender found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set default display backlight value to 85% (0xd8)*/
|
||||
mdfld_dsi_send_mcs_short(sender, write_display_brightness, 0xd8, 1,
|
||||
true);
|
||||
|
||||
/* Set minimum brightness setting of CABC function to 20% (0x33)*/
|
||||
mdfld_dsi_send_mcs_short(sender, write_cabc_min_bright, 0x33, 1, true);
|
||||
|
||||
/* Enable backlight or/and LABC */
|
||||
gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON |
|
||||
BACKLIGHT_ON;
|
||||
if (LABC_control == 1)
|
||||
gen_ctrl_val |= DISPLAY_DIMMING_ON | DISPLAY_BRIGHTNESS_AUTO
|
||||
| GAMMA_AUTO;
|
||||
|
||||
if (LABC_control == 1)
|
||||
gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON;
|
||||
|
||||
dev_priv->mipi_ctrl_display = gen_ctrl_val;
|
||||
|
||||
mdfld_dsi_send_mcs_short(sender, write_ctrl_display, (u8)gen_ctrl_val,
|
||||
1, true);
|
||||
|
||||
mdfld_dsi_send_mcs_short(sender, write_ctrl_cabc, UI_IMAGE, 1, true);
|
||||
}
|
||||
|
||||
void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level)
|
||||
{
|
||||
struct mdfld_dsi_pkg_sender *sender;
|
||||
struct drm_psb_private *dev_priv;
|
||||
struct mdfld_dsi_config *dsi_config;
|
||||
u32 gen_ctrl_val = 0;
|
||||
int p_type = TMD_VID;
|
||||
|
||||
if (!dev || (pipe != 0 && pipe != 2)) {
|
||||
DRM_ERROR("Invalid parameter\n");
|
||||
return;
|
||||
}
|
||||
|
||||
p_type = mdfld_get_panel_type(dev, 0);
|
||||
|
||||
dev_priv = dev->dev_private;
|
||||
|
||||
if (pipe)
|
||||
dsi_config = dev_priv->dsi_configs[1];
|
||||
else
|
||||
dsi_config = dev_priv->dsi_configs[0];
|
||||
|
||||
sender = mdfld_dsi_get_pkg_sender(dsi_config);
|
||||
|
||||
if (!sender) {
|
||||
DRM_ERROR("No sender found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gen_ctrl_val = (level * 0xff / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff;
|
||||
|
||||
dev_dbg(sender->dev->dev, "pipe = %d, gen_ctrl_val = %d.\n",
|
||||
pipe, gen_ctrl_val);
|
||||
|
||||
if (p_type == TMD_VID) {
|
||||
/* Set display backlight value */
|
||||
mdfld_dsi_send_mcs_short(sender, tmd_write_display_brightness,
|
||||
(u8)gen_ctrl_val, 1, true);
|
||||
} else {
|
||||
/* Set display backlight value */
|
||||
mdfld_dsi_send_mcs_short(sender, write_display_brightness,
|
||||
(u8)gen_ctrl_val, 1, true);
|
||||
|
||||
/* Enable backlight control */
|
||||
if (level == 0)
|
||||
gen_ctrl_val = 0;
|
||||
else
|
||||
gen_ctrl_val = dev_priv->mipi_ctrl_display;
|
||||
|
||||
mdfld_dsi_send_mcs_short(sender, write_ctrl_display,
|
||||
(u8)gen_ctrl_val, 1, true);
|
||||
}
|
||||
}
|
||||
|
||||
static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config,
|
||||
u8 dcs, u32 *data, bool hs)
|
||||
{
|
||||
struct mdfld_dsi_pkg_sender *sender
|
||||
= mdfld_dsi_get_pkg_sender(dsi_config);
|
||||
|
||||
if (!sender || !data) {
|
||||
DRM_ERROR("Invalid parameter\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return mdfld_dsi_read_mcs(sender, dcs, data, 1, hs);
|
||||
}
|
||||
|
||||
int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, u32 *mode,
|
||||
bool hs)
|
||||
{
|
||||
if (!dsi_config || !mode) {
|
||||
DRM_ERROR("Invalid parameter\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, hs);
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: this function was used by OSPM.
|
||||
* TODO: will be removed later, should work out display interfaces for OSPM
|
||||
*/
|
||||
void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config, int pipe)
|
||||
{
|
||||
if (!dsi_config || ((pipe != 0) && (pipe != 2))) {
|
||||
DRM_ERROR("Invalid parameters\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mdfld_dsi_dpi_controller_init(dsi_config, pipe);
|
||||
}
|
||||
|
||||
static void mdfld_dsi_connector_save(struct drm_connector *connector)
|
||||
{
|
||||
}
|
||||
|
||||
static void mdfld_dsi_connector_restore(struct drm_connector *connector)
|
||||
{
|
||||
}
|
||||
|
||||
/* FIXME: start using the force parameter */
|
||||
static enum drm_connector_status
|
||||
mdfld_dsi_connector_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
struct mdfld_dsi_connector *dsi_connector
|
||||
= mdfld_dsi_connector(connector);
|
||||
|
||||
dsi_connector->status = connector_status_connected;
|
||||
|
||||
return dsi_connector->status;
|
||||
}
|
||||
|
||||
static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
|
||||
struct drm_property *property,
|
||||
uint64_t value)
|
||||
{
|
||||
struct drm_encoder *encoder = connector->encoder;
|
||||
struct backlight_device *psb_bd;
|
||||
|
||||
if (!strcmp(property->name, "scaling mode") && encoder) {
|
||||
struct psb_intel_crtc *psb_crtc =
|
||||
to_psb_intel_crtc(encoder->crtc);
|
||||
bool centerechange;
|
||||
uint64_t val;
|
||||
|
||||
if (!psb_crtc)
|
||||
goto set_prop_error;
|
||||
|
||||
switch (value) {
|
||||
case DRM_MODE_SCALE_FULLSCREEN:
|
||||
break;
|
||||
case DRM_MODE_SCALE_NO_SCALE:
|
||||
break;
|
||||
case DRM_MODE_SCALE_ASPECT:
|
||||
break;
|
||||
default:
|
||||
goto set_prop_error;
|
||||
}
|
||||
|
||||
if (drm_connector_property_get_value(connector, property, &val))
|
||||
goto set_prop_error;
|
||||
|
||||
if (val == value)
|
||||
goto set_prop_done;
|
||||
|
||||
if (drm_connector_property_set_value(connector,
|
||||
property, value))
|
||||
goto set_prop_error;
|
||||
|
||||
centerechange = (val == DRM_MODE_SCALE_NO_SCALE) ||
|
||||
(value == DRM_MODE_SCALE_NO_SCALE);
|
||||
|
||||
if (psb_crtc->saved_mode.hdisplay != 0 &&
|
||||
psb_crtc->saved_mode.vdisplay != 0) {
|
||||
if (centerechange) {
|
||||
if (!drm_crtc_helper_set_mode(encoder->crtc,
|
||||
&psb_crtc->saved_mode,
|
||||
encoder->crtc->x,
|
||||
encoder->crtc->y,
|
||||
encoder->crtc->fb))
|
||||
goto set_prop_error;
|
||||
} else {
|
||||
struct drm_encoder_helper_funcs *funcs =
|
||||
encoder->helper_private;
|
||||
funcs->mode_set(encoder,
|
||||
&psb_crtc->saved_mode,
|
||||
&psb_crtc->saved_adjusted_mode);
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(property->name, "backlight") && encoder) {
|
||||
if (drm_connector_property_set_value(connector, property,
|
||||
value))
|
||||
goto set_prop_error;
|
||||
else {
|
||||
psb_bd = mdfld_get_backlight_device();
|
||||
if (psb_bd) {
|
||||
psb_bd->props.brightness = value;
|
||||
mdfld_set_brightness(psb_bd);
|
||||
}
|
||||
}
|
||||
}
|
||||
set_prop_done:
|
||||
return 0;
|
||||
set_prop_error:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void mdfld_dsi_connector_destroy(struct drm_connector *connector)
|
||||
{
|
||||
struct mdfld_dsi_connector *dsi_connector =
|
||||
mdfld_dsi_connector(connector);
|
||||
struct mdfld_dsi_pkg_sender *sender;
|
||||
|
||||
if (!dsi_connector)
|
||||
return;
|
||||
drm_sysfs_connector_remove(connector);
|
||||
drm_connector_cleanup(connector);
|
||||
sender = dsi_connector->pkg_sender;
|
||||
mdfld_dsi_pkg_sender_destroy(sender);
|
||||
kfree(dsi_connector);
|
||||
}
|
||||
|
||||
static int mdfld_dsi_connector_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct mdfld_dsi_connector *dsi_connector =
|
||||
mdfld_dsi_connector(connector);
|
||||
struct mdfld_dsi_config *dsi_config =
|
||||
mdfld_dsi_get_config(dsi_connector);
|
||||
struct drm_display_mode *fixed_mode = dsi_config->fixed_mode;
|
||||
struct drm_display_mode *dup_mode = NULL;
|
||||
struct drm_device *dev = connector->dev;
|
||||
|
||||
connector->display_info.min_vfreq = 0;
|
||||
connector->display_info.max_vfreq = 200;
|
||||
connector->display_info.min_hfreq = 0;
|
||||
connector->display_info.max_hfreq = 200;
|
||||
|
||||
if (fixed_mode) {
|
||||
dev_dbg(dev->dev, "fixed_mode %dx%d\n",
|
||||
fixed_mode->hdisplay, fixed_mode->vdisplay);
|
||||
dup_mode = drm_mode_duplicate(dev, fixed_mode);
|
||||
drm_mode_probed_add(connector, dup_mode);
|
||||
return 1;
|
||||
}
|
||||
DRM_ERROR("Didn't get any modes!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mdfld_dsi_connector_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
struct mdfld_dsi_connector *dsi_connector =
|
||||
mdfld_dsi_connector(connector);
|
||||
struct mdfld_dsi_config *dsi_config =
|
||||
mdfld_dsi_get_config(dsi_connector);
|
||||
struct drm_display_mode *fixed_mode = dsi_config->fixed_mode;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
|
||||
return MODE_NO_DBLESCAN;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
return MODE_NO_INTERLACE;
|
||||
|
||||
/**
|
||||
* FIXME: current DC has no fitting unit, reject any mode setting
|
||||
* request
|
||||
* Will figure out a way to do up-scaling(pannel fitting) later.
|
||||
**/
|
||||
if (fixed_mode) {
|
||||
if (mode->hdisplay != fixed_mode->hdisplay)
|
||||
return MODE_PANEL;
|
||||
|
||||
if (mode->vdisplay != fixed_mode->vdisplay)
|
||||
return MODE_PANEL;
|
||||
}
|
||||
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode)
|
||||
{
|
||||
if (mode == connector->dpms)
|
||||
return;
|
||||
|
||||
/*first, execute dpms*/
|
||||
|
||||
drm_helper_connector_dpms(connector, mode);
|
||||
}
|
||||
|
||||
static struct drm_encoder *mdfld_dsi_connector_best_encoder(
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct mdfld_dsi_connector *dsi_connector =
|
||||
mdfld_dsi_connector(connector);
|
||||
struct mdfld_dsi_config *dsi_config =
|
||||
mdfld_dsi_get_config(dsi_connector);
|
||||
return &dsi_config->encoder->base.base;
|
||||
}
|
||||
|
||||
/*DSI connector funcs*/
|
||||
static const struct drm_connector_funcs mdfld_dsi_connector_funcs = {
|
||||
.dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms,
|
||||
.save = mdfld_dsi_connector_save,
|
||||
.restore = mdfld_dsi_connector_restore,
|
||||
.detect = mdfld_dsi_connector_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.set_property = mdfld_dsi_connector_set_property,
|
||||
.destroy = mdfld_dsi_connector_destroy,
|
||||
};
|
||||
|
||||
/*DSI connector helper funcs*/
|
||||
static const struct drm_connector_helper_funcs
|
||||
mdfld_dsi_connector_helper_funcs = {
|
||||
.get_modes = mdfld_dsi_connector_get_modes,
|
||||
.mode_valid = mdfld_dsi_connector_mode_valid,
|
||||
.best_encoder = mdfld_dsi_connector_best_encoder,
|
||||
};
|
||||
|
||||
static int mdfld_dsi_get_default_config(struct drm_device *dev,
|
||||
struct mdfld_dsi_config *config, int pipe)
|
||||
{
|
||||
if (!dev || !config) {
|
||||
DRM_ERROR("Invalid parameters");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
config->bpp = 24;
|
||||
if (mdfld_get_panel_type(dev, pipe) == TC35876X)
|
||||
config->lane_count = 4;
|
||||
else
|
||||
config->lane_count = 2;
|
||||
config->channel_num = 0;
|
||||
|
||||
if (mdfld_get_panel_type(dev, pipe) == TMD_VID)
|
||||
config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE;
|
||||
else if (mdfld_get_panel_type(dev, pipe) == TC35876X)
|
||||
config->video_mode =
|
||||
MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS;
|
||||
else
|
||||
config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdfld_dsi_panel_reset(int pipe)
|
||||
{
|
||||
unsigned gpio;
|
||||
int ret = 0;
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
gpio = 128;
|
||||
break;
|
||||
case 2:
|
||||
gpio = 34;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("Invalid output\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = gpio_request(gpio, "gfx");
|
||||
if (ret) {
|
||||
DRM_ERROR("gpio_rqueset failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = gpio_direction_output(gpio, 1);
|
||||
if (ret) {
|
||||
DRM_ERROR("gpio_direction_output failed\n");
|
||||
goto gpio_error;
|
||||
}
|
||||
|
||||
gpio_get_value(128);
|
||||
|
||||
gpio_error:
|
||||
if (gpio_is_valid(gpio))
|
||||
gpio_free(gpio);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* MIPI output init
|
||||
* @dev drm device
|
||||
* @pipe pipe number. 0 or 2
|
||||
* @config
|
||||
*
|
||||
* Do the initialization of a MIPI output, including create DRM mode objects
|
||||
* initialization of DSI output on @pipe
|
||||
*/
|
||||
void mdfld_dsi_output_init(struct drm_device *dev,
|
||||
int pipe,
|
||||
const struct panel_funcs *p_vid_funcs)
|
||||
{
|
||||
struct mdfld_dsi_config *dsi_config;
|
||||
struct mdfld_dsi_connector *dsi_connector;
|
||||
struct drm_connector *connector;
|
||||
struct mdfld_dsi_encoder *encoder;
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct panel_info dsi_panel_info;
|
||||
u32 width_mm, height_mm;
|
||||
|
||||
dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe);
|
||||
|
||||
if (!dev || ((pipe != 0) && (pipe != 2))) {
|
||||
DRM_ERROR("Invalid parameter\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*create a new connetor*/
|
||||
dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL);
|
||||
if (!dsi_connector) {
|
||||
DRM_ERROR("No memory");
|
||||
return;
|
||||
}
|
||||
|
||||
dsi_connector->pipe = pipe;
|
||||
|
||||
dsi_config = kzalloc(sizeof(struct mdfld_dsi_config),
|
||||
GFP_KERNEL);
|
||||
if (!dsi_config) {
|
||||
DRM_ERROR("cannot allocate memory for DSI config\n");
|
||||
goto dsi_init_err0;
|
||||
}
|
||||
mdfld_dsi_get_default_config(dev, dsi_config, pipe);
|
||||
|
||||
dsi_connector->private = dsi_config;
|
||||
|
||||
dsi_config->changed = 1;
|
||||
dsi_config->dev = dev;
|
||||
|
||||
dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev);
|
||||
if (p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
|
||||
goto dsi_init_err0;
|
||||
|
||||
width_mm = dsi_panel_info.width_mm;
|
||||
height_mm = dsi_panel_info.height_mm;
|
||||
|
||||
dsi_config->mode = dsi_config->fixed_mode;
|
||||
dsi_config->connector = dsi_connector;
|
||||
|
||||
if (!dsi_config->fixed_mode) {
|
||||
DRM_ERROR("No pannel fixed mode was found\n");
|
||||
goto dsi_init_err0;
|
||||
}
|
||||
|
||||
if (pipe && dev_priv->dsi_configs[0]) {
|
||||
dsi_config->dvr_ic_inited = 0;
|
||||
dev_priv->dsi_configs[1] = dsi_config;
|
||||
} else if (pipe == 0) {
|
||||
dsi_config->dvr_ic_inited = 1;
|
||||
dev_priv->dsi_configs[0] = dsi_config;
|
||||
} else {
|
||||
DRM_ERROR("Trying to init MIPI1 before MIPI0\n");
|
||||
goto dsi_init_err0;
|
||||
}
|
||||
|
||||
|
||||
connector = &dsi_connector->base.base;
|
||||
drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_LVDS);
|
||||
drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs);
|
||||
|
||||
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
|
||||
connector->display_info.width_mm = width_mm;
|
||||
connector->display_info.height_mm = height_mm;
|
||||
connector->interlace_allowed = false;
|
||||
connector->doublescan_allowed = false;
|
||||
|
||||
/*attach properties*/
|
||||
drm_connector_attach_property(connector,
|
||||
dev->mode_config.scaling_mode_property,
|
||||
DRM_MODE_SCALE_FULLSCREEN);
|
||||
drm_connector_attach_property(connector,
|
||||
dev_priv->backlight_property,
|
||||
MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
|
||||
|
||||
/*init DSI package sender on this output*/
|
||||
if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) {
|
||||
DRM_ERROR("Package Sender initialization failed on pipe %d\n",
|
||||
pipe);
|
||||
goto dsi_init_err0;
|
||||
}
|
||||
|
||||
encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs);
|
||||
if (!encoder) {
|
||||
DRM_ERROR("Create DPI encoder failed\n");
|
||||
goto dsi_init_err1;
|
||||
}
|
||||
encoder->private = dsi_config;
|
||||
dsi_config->encoder = encoder;
|
||||
encoder->base.type = (pipe == 0) ? INTEL_OUTPUT_MIPI :
|
||||
INTEL_OUTPUT_MIPI2;
|
||||
drm_sysfs_connector_add(connector);
|
||||
return;
|
||||
|
||||
/*TODO: add code to destroy outputs on error*/
|
||||
dsi_init_err1:
|
||||
/*destroy sender*/
|
||||
mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender);
|
||||
|
||||
drm_connector_cleanup(connector);
|
||||
|
||||
kfree(dsi_config->fixed_mode);
|
||||
kfree(dsi_config);
|
||||
dsi_init_err0:
|
||||
kfree(dsi_connector);
|
||||
}
|
378
drivers/gpu/drm/gma500/mdfld_dsi_output.h
Normal file
378
drivers/gpu/drm/gma500/mdfld_dsi_output.h
Normal file
@ -0,0 +1,378 @@
|
||||
/*
|
||||
* Copyright © 2010 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:
|
||||
* jim liu <jim.liu@intel.com>
|
||||
* Jackie Li<yaodong.li@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef __MDFLD_DSI_OUTPUT_H__
|
||||
#define __MDFLD_DSI_OUTPUT_H__
|
||||
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/version.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
|
||||
#include "psb_drv.h"
|
||||
#include "psb_intel_drv.h"
|
||||
#include "psb_intel_reg.h"
|
||||
#include "mdfld_output.h"
|
||||
|
||||
#include <asm/mrst.h>
|
||||
|
||||
#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
|
||||
#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
|
||||
#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
|
||||
#define FLD_MOD(orig, val, start, end) \
|
||||
(((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
|
||||
|
||||
#define REG_FLD_MOD(reg, val, start, end) \
|
||||
REG_WRITE(reg, FLD_MOD(REG_READ(reg), val, start, end))
|
||||
|
||||
static inline int REGISTER_FLD_WAIT(struct drm_device *dev, u32 reg,
|
||||
u32 val, int start, int end)
|
||||
{
|
||||
int t = 100000;
|
||||
|
||||
while (FLD_GET(REG_READ(reg), start, end) != val) {
|
||||
if (--t == 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define REG_FLD_WAIT(reg, val, start, end) \
|
||||
REGISTER_FLD_WAIT(dev, reg, val, start, end)
|
||||
|
||||
#define REG_BIT_WAIT(reg, val, bitnum) \
|
||||
REGISTER_FLD_WAIT(dev, reg, val, bitnum, bitnum)
|
||||
|
||||
#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100
|
||||
|
||||
#ifdef DEBUG
|
||||
#define CHECK_PIPE(pipe) ({ \
|
||||
const typeof(pipe) __pipe = (pipe); \
|
||||
BUG_ON(__pipe != 0 && __pipe != 2); \
|
||||
__pipe; })
|
||||
#else
|
||||
#define CHECK_PIPE(pipe) (pipe)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Actual MIPIA->MIPIC reg offset is 0x800, value 0x400 is valid for 0 and 2
|
||||
*/
|
||||
#define REG_OFFSET(pipe) (CHECK_PIPE(pipe) * 0x400)
|
||||
|
||||
/* mdfld DSI controller registers */
|
||||
#define MIPI_DEVICE_READY_REG(pipe) (0xb000 + REG_OFFSET(pipe))
|
||||
#define MIPI_INTR_STAT_REG(pipe) (0xb004 + REG_OFFSET(pipe))
|
||||
#define MIPI_INTR_EN_REG(pipe) (0xb008 + REG_OFFSET(pipe))
|
||||
#define MIPI_DSI_FUNC_PRG_REG(pipe) (0xb00c + REG_OFFSET(pipe))
|
||||
#define MIPI_HS_TX_TIMEOUT_REG(pipe) (0xb010 + REG_OFFSET(pipe))
|
||||
#define MIPI_LP_RX_TIMEOUT_REG(pipe) (0xb014 + REG_OFFSET(pipe))
|
||||
#define MIPI_TURN_AROUND_TIMEOUT_REG(pipe) (0xb018 + REG_OFFSET(pipe))
|
||||
#define MIPI_DEVICE_RESET_TIMER_REG(pipe) (0xb01c + REG_OFFSET(pipe))
|
||||
#define MIPI_DPI_RESOLUTION_REG(pipe) (0xb020 + REG_OFFSET(pipe))
|
||||
#define MIPI_DBI_FIFO_THROTTLE_REG(pipe) (0xb024 + REG_OFFSET(pipe))
|
||||
#define MIPI_HSYNC_COUNT_REG(pipe) (0xb028 + REG_OFFSET(pipe))
|
||||
#define MIPI_HBP_COUNT_REG(pipe) (0xb02c + REG_OFFSET(pipe))
|
||||
#define MIPI_HFP_COUNT_REG(pipe) (0xb030 + REG_OFFSET(pipe))
|
||||
#define MIPI_HACTIVE_COUNT_REG(pipe) (0xb034 + REG_OFFSET(pipe))
|
||||
#define MIPI_VSYNC_COUNT_REG(pipe) (0xb038 + REG_OFFSET(pipe))
|
||||
#define MIPI_VBP_COUNT_REG(pipe) (0xb03c + REG_OFFSET(pipe))
|
||||
#define MIPI_VFP_COUNT_REG(pipe) (0xb040 + REG_OFFSET(pipe))
|
||||
#define MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe) (0xb044 + REG_OFFSET(pipe))
|
||||
#define MIPI_DPI_CONTROL_REG(pipe) (0xb048 + REG_OFFSET(pipe))
|
||||
#define MIPI_DPI_DATA_REG(pipe) (0xb04c + REG_OFFSET(pipe))
|
||||
#define MIPI_INIT_COUNT_REG(pipe) (0xb050 + REG_OFFSET(pipe))
|
||||
#define MIPI_MAX_RETURN_PACK_SIZE_REG(pipe) (0xb054 + REG_OFFSET(pipe))
|
||||
#define MIPI_VIDEO_MODE_FORMAT_REG(pipe) (0xb058 + REG_OFFSET(pipe))
|
||||
#define MIPI_EOT_DISABLE_REG(pipe) (0xb05c + REG_OFFSET(pipe))
|
||||
#define MIPI_LP_BYTECLK_REG(pipe) (0xb060 + REG_OFFSET(pipe))
|
||||
#define MIPI_LP_GEN_DATA_REG(pipe) (0xb064 + REG_OFFSET(pipe))
|
||||
#define MIPI_HS_GEN_DATA_REG(pipe) (0xb068 + REG_OFFSET(pipe))
|
||||
#define MIPI_LP_GEN_CTRL_REG(pipe) (0xb06c + REG_OFFSET(pipe))
|
||||
#define MIPI_HS_GEN_CTRL_REG(pipe) (0xb070 + REG_OFFSET(pipe))
|
||||
#define MIPI_GEN_FIFO_STAT_REG(pipe) (0xb074 + REG_OFFSET(pipe))
|
||||
#define MIPI_HS_LS_DBI_ENABLE_REG(pipe) (0xb078 + REG_OFFSET(pipe))
|
||||
#define MIPI_DPHY_PARAM_REG(pipe) (0xb080 + REG_OFFSET(pipe))
|
||||
#define MIPI_DBI_BW_CTRL_REG(pipe) (0xb084 + REG_OFFSET(pipe))
|
||||
#define MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe) (0xb088 + REG_OFFSET(pipe))
|
||||
|
||||
#define MIPI_CTRL_REG(pipe) (0xb104 + REG_OFFSET(pipe))
|
||||
#define MIPI_DATA_ADD_REG(pipe) (0xb108 + REG_OFFSET(pipe))
|
||||
#define MIPI_DATA_LEN_REG(pipe) (0xb10c + REG_OFFSET(pipe))
|
||||
#define MIPI_CMD_ADD_REG(pipe) (0xb110 + REG_OFFSET(pipe))
|
||||
#define MIPI_CMD_LEN_REG(pipe) (0xb114 + REG_OFFSET(pipe))
|
||||
|
||||
/* non-uniform reg offset */
|
||||
#define MIPI_PORT_CONTROL(pipe) (CHECK_PIPE(pipe) ? MIPI_C : MIPI)
|
||||
|
||||
#define DSI_DEVICE_READY (0x1)
|
||||
#define DSI_POWER_STATE_ULPS_ENTER (0x2 << 1)
|
||||
#define DSI_POWER_STATE_ULPS_EXIT (0x1 << 1)
|
||||
#define DSI_POWER_STATE_ULPS_OFFSET (0x1)
|
||||
|
||||
|
||||
#define DSI_ONE_DATA_LANE (0x1)
|
||||
#define DSI_TWO_DATA_LANE (0x2)
|
||||
#define DSI_THREE_DATA_LANE (0X3)
|
||||
#define DSI_FOUR_DATA_LANE (0x4)
|
||||
#define DSI_DPI_VIRT_CHANNEL_OFFSET (0x3)
|
||||
#define DSI_DBI_VIRT_CHANNEL_OFFSET (0x5)
|
||||
#define DSI_DPI_COLOR_FORMAT_RGB565 (0x01 << 7)
|
||||
#define DSI_DPI_COLOR_FORMAT_RGB666 (0x02 << 7)
|
||||
#define DSI_DPI_COLOR_FORMAT_RGB666_UNPACK (0x03 << 7)
|
||||
#define DSI_DPI_COLOR_FORMAT_RGB888 (0x04 << 7)
|
||||
#define DSI_DBI_COLOR_FORMAT_OPTION2 (0x05 << 13)
|
||||
|
||||
#define DSI_INTR_STATE_RXSOTERROR BIT(0)
|
||||
|
||||
#define DSI_INTR_STATE_SPL_PKG_SENT BIT(30)
|
||||
#define DSI_INTR_STATE_TE BIT(31)
|
||||
|
||||
#define DSI_HS_TX_TIMEOUT_MASK (0xffffff)
|
||||
|
||||
#define DSI_LP_RX_TIMEOUT_MASK (0xffffff)
|
||||
|
||||
#define DSI_TURN_AROUND_TIMEOUT_MASK (0x3f)
|
||||
|
||||
#define DSI_RESET_TIMER_MASK (0xffff)
|
||||
|
||||
#define DSI_DBI_FIFO_WM_HALF (0x0)
|
||||
#define DSI_DBI_FIFO_WM_QUARTER (0x1)
|
||||
#define DSI_DBI_FIFO_WM_LOW (0x2)
|
||||
|
||||
#define DSI_DPI_TIMING_MASK (0xffff)
|
||||
|
||||
#define DSI_INIT_TIMER_MASK (0xffff)
|
||||
|
||||
#define DSI_DBI_RETURN_PACK_SIZE_MASK (0x3ff)
|
||||
|
||||
#define DSI_LP_BYTECLK_MASK (0x0ffff)
|
||||
|
||||
#define DSI_HS_CTRL_GEN_SHORT_W0 (0x03)
|
||||
#define DSI_HS_CTRL_GEN_SHORT_W1 (0x13)
|
||||
#define DSI_HS_CTRL_GEN_SHORT_W2 (0x23)
|
||||
#define DSI_HS_CTRL_GEN_R0 (0x04)
|
||||
#define DSI_HS_CTRL_GEN_R1 (0x14)
|
||||
#define DSI_HS_CTRL_GEN_R2 (0x24)
|
||||
#define DSI_HS_CTRL_GEN_LONG_W (0x29)
|
||||
#define DSI_HS_CTRL_MCS_SHORT_W0 (0x05)
|
||||
#define DSI_HS_CTRL_MCS_SHORT_W1 (0x15)
|
||||
#define DSI_HS_CTRL_MCS_R0 (0x06)
|
||||
#define DSI_HS_CTRL_MCS_LONG_W (0x39)
|
||||
#define DSI_HS_CTRL_VC_OFFSET (0x06)
|
||||
#define DSI_HS_CTRL_WC_OFFSET (0x08)
|
||||
|
||||
#define DSI_FIFO_GEN_HS_DATA_FULL BIT(0)
|
||||
#define DSI_FIFO_GEN_HS_DATA_HALF_EMPTY BIT(1)
|
||||
#define DSI_FIFO_GEN_HS_DATA_EMPTY BIT(2)
|
||||
#define DSI_FIFO_GEN_LP_DATA_FULL BIT(8)
|
||||
#define DSI_FIFO_GEN_LP_DATA_HALF_EMPTY BIT(9)
|
||||
#define DSI_FIFO_GEN_LP_DATA_EMPTY BIT(10)
|
||||
#define DSI_FIFO_GEN_HS_CTRL_FULL BIT(16)
|
||||
#define DSI_FIFO_GEN_HS_CTRL_HALF_EMPTY BIT(17)
|
||||
#define DSI_FIFO_GEN_HS_CTRL_EMPTY BIT(18)
|
||||
#define DSI_FIFO_GEN_LP_CTRL_FULL BIT(24)
|
||||
#define DSI_FIFO_GEN_LP_CTRL_HALF_EMPTY BIT(25)
|
||||
#define DSI_FIFO_GEN_LP_CTRL_EMPTY BIT(26)
|
||||
#define DSI_FIFO_DBI_EMPTY BIT(27)
|
||||
#define DSI_FIFO_DPI_EMPTY BIT(28)
|
||||
|
||||
#define DSI_DBI_HS_LP_SWITCH_MASK (0x1)
|
||||
|
||||
#define DSI_HS_LP_SWITCH_COUNTER_OFFSET (0x0)
|
||||
#define DSI_LP_HS_SWITCH_COUNTER_OFFSET (0x16)
|
||||
|
||||
#define DSI_DPI_CTRL_HS_SHUTDOWN (0x00000001)
|
||||
#define DSI_DPI_CTRL_HS_TURN_ON (0x00000002)
|
||||
|
||||
/*dsi power modes*/
|
||||
#define DSI_POWER_MODE_DISPLAY_ON BIT(2)
|
||||
#define DSI_POWER_MODE_NORMAL_ON BIT(3)
|
||||
#define DSI_POWER_MODE_SLEEP_OUT BIT(4)
|
||||
#define DSI_POWER_MODE_PARTIAL_ON BIT(5)
|
||||
#define DSI_POWER_MODE_IDLE_ON BIT(6)
|
||||
|
||||
enum {
|
||||
MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE = 1,
|
||||
MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS = 2,
|
||||
MDFLD_DSI_VIDEO_BURST_MODE = 3,
|
||||
};
|
||||
|
||||
#define DSI_DPI_COMPLETE_LAST_LINE BIT(2)
|
||||
#define DSI_DPI_DISABLE_BTA BIT(3)
|
||||
|
||||
struct mdfld_dsi_connector {
|
||||
struct psb_intel_connector base;
|
||||
|
||||
int pipe;
|
||||
void *private;
|
||||
void *pkg_sender;
|
||||
|
||||
/* Connection status */
|
||||
enum drm_connector_status status;
|
||||
};
|
||||
|
||||
struct mdfld_dsi_encoder {
|
||||
struct psb_intel_encoder base;
|
||||
void *private;
|
||||
};
|
||||
|
||||
/*
|
||||
* DSI config, consists of one DSI connector, two DSI encoders.
|
||||
* DRM will pick up on DSI encoder basing on differents configs.
|
||||
*/
|
||||
struct mdfld_dsi_config {
|
||||
struct drm_device *dev;
|
||||
struct drm_display_mode *fixed_mode;
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
struct mdfld_dsi_connector *connector;
|
||||
struct mdfld_dsi_encoder *encoder;
|
||||
|
||||
int changed;
|
||||
|
||||
int bpp;
|
||||
int lane_count;
|
||||
/*Virtual channel number for this encoder*/
|
||||
int channel_num;
|
||||
/*video mode configure*/
|
||||
int video_mode;
|
||||
|
||||
int dvr_ic_inited;
|
||||
};
|
||||
|
||||
static inline struct mdfld_dsi_connector *mdfld_dsi_connector(
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct psb_intel_connector *psb_connector;
|
||||
|
||||
psb_connector = to_psb_intel_connector(connector);
|
||||
|
||||
return container_of(psb_connector, struct mdfld_dsi_connector, base);
|
||||
}
|
||||
|
||||
static inline struct mdfld_dsi_encoder *mdfld_dsi_encoder(
|
||||
struct drm_encoder *encoder)
|
||||
{
|
||||
struct psb_intel_encoder *psb_encoder;
|
||||
|
||||
psb_encoder = to_psb_intel_encoder(encoder);
|
||||
|
||||
return container_of(psb_encoder, struct mdfld_dsi_encoder, base);
|
||||
}
|
||||
|
||||
static inline struct mdfld_dsi_config *
|
||||
mdfld_dsi_get_config(struct mdfld_dsi_connector *connector)
|
||||
{
|
||||
if (!connector)
|
||||
return NULL;
|
||||
return (struct mdfld_dsi_config *)connector->private;
|
||||
}
|
||||
|
||||
static inline void *mdfld_dsi_get_pkg_sender(struct mdfld_dsi_config *config)
|
||||
{
|
||||
struct mdfld_dsi_connector *dsi_connector;
|
||||
|
||||
if (!config)
|
||||
return NULL;
|
||||
|
||||
dsi_connector = config->connector;
|
||||
|
||||
if (!dsi_connector)
|
||||
return NULL;
|
||||
|
||||
return dsi_connector->pkg_sender;
|
||||
}
|
||||
|
||||
static inline struct mdfld_dsi_config *
|
||||
mdfld_dsi_encoder_get_config(struct mdfld_dsi_encoder *encoder)
|
||||
{
|
||||
if (!encoder)
|
||||
return NULL;
|
||||
return (struct mdfld_dsi_config *)encoder->private;
|
||||
}
|
||||
|
||||
static inline struct mdfld_dsi_connector *
|
||||
mdfld_dsi_encoder_get_connector(struct mdfld_dsi_encoder *encoder)
|
||||
{
|
||||
struct mdfld_dsi_config *config;
|
||||
|
||||
if (!encoder)
|
||||
return NULL;
|
||||
|
||||
config = mdfld_dsi_encoder_get_config(encoder);
|
||||
if (!config)
|
||||
return NULL;
|
||||
|
||||
return config->connector;
|
||||
}
|
||||
|
||||
static inline void *mdfld_dsi_encoder_get_pkg_sender(
|
||||
struct mdfld_dsi_encoder *encoder)
|
||||
{
|
||||
struct mdfld_dsi_config *dsi_config;
|
||||
|
||||
dsi_config = mdfld_dsi_encoder_get_config(encoder);
|
||||
if (!dsi_config)
|
||||
return NULL;
|
||||
|
||||
return mdfld_dsi_get_pkg_sender(dsi_config);
|
||||
}
|
||||
|
||||
static inline int mdfld_dsi_encoder_get_pipe(struct mdfld_dsi_encoder *encoder)
|
||||
{
|
||||
struct mdfld_dsi_connector *connector;
|
||||
|
||||
if (!encoder)
|
||||
return -1;
|
||||
|
||||
connector = mdfld_dsi_encoder_get_connector(encoder);
|
||||
if (!connector)
|
||||
return -1;
|
||||
return connector->pipe;
|
||||
}
|
||||
|
||||
/* Export functions */
|
||||
extern void mdfld_dsi_gen_fifo_ready(struct drm_device *dev,
|
||||
u32 gen_fifo_stat_reg, u32 fifo_stat);
|
||||
extern void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config,
|
||||
int pipe);
|
||||
extern void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe,
|
||||
int level);
|
||||
extern void mdfld_dsi_output_init(struct drm_device *dev,
|
||||
int pipe,
|
||||
const struct panel_funcs *p_vid_funcs);
|
||||
extern void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config,
|
||||
int pipe);
|
||||
|
||||
extern int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config,
|
||||
u32 *mode, bool hs);
|
||||
extern int mdfld_dsi_panel_reset(int pipe);
|
||||
|
||||
#endif /*__MDFLD_DSI_OUTPUT_H__*/
|
694
drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c
Normal file
694
drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c
Normal file
@ -0,0 +1,694 @@
|
||||
/*
|
||||
* Copyright © 2010 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:
|
||||
* Jackie Li<yaodong.li@intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/freezer.h>
|
||||
|
||||
#include "mdfld_dsi_output.h"
|
||||
#include "mdfld_dsi_pkg_sender.h"
|
||||
#include "mdfld_dsi_dpi.h"
|
||||
|
||||
#define MDFLD_DSI_READ_MAX_COUNT 5000
|
||||
|
||||
enum data_type {
|
||||
DSI_DT_GENERIC_SHORT_WRITE_0 = 0x03,
|
||||
DSI_DT_GENERIC_SHORT_WRITE_1 = 0x13,
|
||||
DSI_DT_GENERIC_SHORT_WRITE_2 = 0x23,
|
||||
DSI_DT_GENERIC_READ_0 = 0x04,
|
||||
DSI_DT_GENERIC_READ_1 = 0x14,
|
||||
DSI_DT_GENERIC_READ_2 = 0x24,
|
||||
DSI_DT_GENERIC_LONG_WRITE = 0x29,
|
||||
DSI_DT_DCS_SHORT_WRITE_0 = 0x05,
|
||||
DSI_DT_DCS_SHORT_WRITE_1 = 0x15,
|
||||
DSI_DT_DCS_READ = 0x06,
|
||||
DSI_DT_DCS_LONG_WRITE = 0x39,
|
||||
};
|
||||
|
||||
enum {
|
||||
MDFLD_DSI_PANEL_MODE_SLEEP = 0x1,
|
||||
};
|
||||
|
||||
enum {
|
||||
MDFLD_DSI_PKG_SENDER_FREE = 0x0,
|
||||
MDFLD_DSI_PKG_SENDER_BUSY = 0x1,
|
||||
};
|
||||
|
||||
static const char *const dsi_errors[] = {
|
||||
"RX SOT Error",
|
||||
"RX SOT Sync Error",
|
||||
"RX EOT Sync Error",
|
||||
"RX Escape Mode Entry Error",
|
||||
"RX LP TX Sync Error",
|
||||
"RX HS Receive Timeout Error",
|
||||
"RX False Control Error",
|
||||
"RX ECC Single Bit Error",
|
||||
"RX ECC Multibit Error",
|
||||
"RX Checksum Error",
|
||||
"RX DSI Data Type Not Recognised",
|
||||
"RX DSI VC ID Invalid",
|
||||
"TX False Control Error",
|
||||
"TX ECC Single Bit Error",
|
||||
"TX ECC Multibit Error",
|
||||
"TX Checksum Error",
|
||||
"TX DSI Data Type Not Recognised",
|
||||
"TX DSI VC ID invalid",
|
||||
"High Contention",
|
||||
"Low contention",
|
||||
"DPI FIFO Under run",
|
||||
"HS TX Timeout",
|
||||
"LP RX Timeout",
|
||||
"Turn Around ACK Timeout",
|
||||
"ACK With No Error",
|
||||
"RX Invalid TX Length",
|
||||
"RX Prot Violation",
|
||||
"HS Generic Write FIFO Full",
|
||||
"LP Generic Write FIFO Full",
|
||||
"Generic Read Data Avail"
|
||||
"Special Packet Sent",
|
||||
"Tearing Effect",
|
||||
};
|
||||
|
||||
static inline int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender *sender,
|
||||
u32 mask)
|
||||
{
|
||||
struct drm_device *dev = sender->dev;
|
||||
u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg;
|
||||
int retry = 0xffff;
|
||||
|
||||
while (retry--) {
|
||||
if ((mask & REG_READ(gen_fifo_stat_reg)) == mask)
|
||||
return 0;
|
||||
udelay(100);
|
||||
}
|
||||
DRM_ERROR("fifo is NOT empty 0x%08x\n", REG_READ(gen_fifo_stat_reg));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
|
||||
{
|
||||
return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(10) | BIT(18) |
|
||||
BIT(26) | BIT(27) | BIT(28)));
|
||||
}
|
||||
|
||||
static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
|
||||
{
|
||||
return wait_for_gen_fifo_empty(sender, (BIT(10) | BIT(26)));
|
||||
}
|
||||
|
||||
static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
|
||||
{
|
||||
return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(18)));
|
||||
}
|
||||
|
||||
static int handle_dsi_error(struct mdfld_dsi_pkg_sender *sender, u32 mask)
|
||||
{
|
||||
u32 intr_stat_reg = sender->mipi_intr_stat_reg;
|
||||
struct drm_device *dev = sender->dev;
|
||||
|
||||
dev_dbg(sender->dev->dev, "Handling error 0x%08x\n", mask);
|
||||
|
||||
switch (mask) {
|
||||
case BIT(0):
|
||||
case BIT(1):
|
||||
case BIT(2):
|
||||
case BIT(3):
|
||||
case BIT(4):
|
||||
case BIT(5):
|
||||
case BIT(6):
|
||||
case BIT(7):
|
||||
case BIT(8):
|
||||
case BIT(9):
|
||||
case BIT(10):
|
||||
case BIT(11):
|
||||
case BIT(12):
|
||||
case BIT(13):
|
||||
dev_dbg(sender->dev->dev, "No Action required\n");
|
||||
break;
|
||||
case BIT(14):
|
||||
/*wait for all fifo empty*/
|
||||
/*wait_for_all_fifos_empty(sender)*/;
|
||||
break;
|
||||
case BIT(15):
|
||||
dev_dbg(sender->dev->dev, "No Action required\n");
|
||||
break;
|
||||
case BIT(16):
|
||||
break;
|
||||
case BIT(17):
|
||||
break;
|
||||
case BIT(18):
|
||||
case BIT(19):
|
||||
dev_dbg(sender->dev->dev, "High/Low contention detected\n");
|
||||
/*wait for contention recovery time*/
|
||||
/*mdelay(10);*/
|
||||
/*wait for all fifo empty*/
|
||||
if (0)
|
||||
wait_for_all_fifos_empty(sender);
|
||||
break;
|
||||
case BIT(20):
|
||||
dev_dbg(sender->dev->dev, "No Action required\n");
|
||||
break;
|
||||
case BIT(21):
|
||||
/*wait for all fifo empty*/
|
||||
/*wait_for_all_fifos_empty(sender);*/
|
||||
break;
|
||||
case BIT(22):
|
||||
break;
|
||||
case BIT(23):
|
||||
case BIT(24):
|
||||
case BIT(25):
|
||||
case BIT(26):
|
||||
case BIT(27):
|
||||
dev_dbg(sender->dev->dev, "HS Gen fifo full\n");
|
||||
REG_WRITE(intr_stat_reg, mask);
|
||||
wait_for_hs_fifos_empty(sender);
|
||||
break;
|
||||
case BIT(28):
|
||||
dev_dbg(sender->dev->dev, "LP Gen fifo full\n");
|
||||
REG_WRITE(intr_stat_reg, mask);
|
||||
wait_for_lp_fifos_empty(sender);
|
||||
break;
|
||||
case BIT(29):
|
||||
case BIT(30):
|
||||
case BIT(31):
|
||||
dev_dbg(sender->dev->dev, "No Action required\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (mask & REG_READ(intr_stat_reg))
|
||||
dev_dbg(sender->dev->dev,
|
||||
"Cannot clean interrupt 0x%08x\n", mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dsi_error_handler(struct mdfld_dsi_pkg_sender *sender)
|
||||
{
|
||||
struct drm_device *dev = sender->dev;
|
||||
u32 intr_stat_reg = sender->mipi_intr_stat_reg;
|
||||
u32 mask;
|
||||
u32 intr_stat;
|
||||
int i;
|
||||
int err = 0;
|
||||
|
||||
intr_stat = REG_READ(intr_stat_reg);
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
mask = (0x00000001UL) << i;
|
||||
if (intr_stat & mask) {
|
||||
dev_dbg(sender->dev->dev, "[DSI]: %s\n", dsi_errors[i]);
|
||||
err = handle_dsi_error(sender, mask);
|
||||
if (err)
|
||||
DRM_ERROR("Cannot handle error\n");
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int send_short_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
|
||||
u8 cmd, u8 param, bool hs)
|
||||
{
|
||||
struct drm_device *dev = sender->dev;
|
||||
u32 ctrl_reg;
|
||||
u32 val;
|
||||
u8 virtual_channel = 0;
|
||||
|
||||
if (hs) {
|
||||
ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
|
||||
|
||||
/* FIXME: wait_for_hs_fifos_empty(sender); */
|
||||
} else {
|
||||
ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
|
||||
|
||||
/* FIXME: wait_for_lp_fifos_empty(sender); */
|
||||
}
|
||||
|
||||
val = FLD_VAL(param, 23, 16) | FLD_VAL(cmd, 15, 8) |
|
||||
FLD_VAL(virtual_channel, 7, 6) | FLD_VAL(data_type, 5, 0);
|
||||
|
||||
REG_WRITE(ctrl_reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_long_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
|
||||
u8 *data, int len, bool hs)
|
||||
{
|
||||
struct drm_device *dev = sender->dev;
|
||||
u32 ctrl_reg;
|
||||
u32 data_reg;
|
||||
u32 val;
|
||||
u8 *p;
|
||||
u8 b1, b2, b3, b4;
|
||||
u8 virtual_channel = 0;
|
||||
int i;
|
||||
|
||||
if (hs) {
|
||||
ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
|
||||
data_reg = sender->mipi_hs_gen_data_reg;
|
||||
|
||||
/* FIXME: wait_for_hs_fifos_empty(sender); */
|
||||
} else {
|
||||
ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
|
||||
data_reg = sender->mipi_lp_gen_data_reg;
|
||||
|
||||
/* FIXME: wait_for_lp_fifos_empty(sender); */
|
||||
}
|
||||
|
||||
p = data;
|
||||
for (i = 0; i < len / 4; i++) {
|
||||
b1 = *p++;
|
||||
b2 = *p++;
|
||||
b3 = *p++;
|
||||
b4 = *p++;
|
||||
|
||||
REG_WRITE(data_reg, b4 << 24 | b3 << 16 | b2 << 8 | b1);
|
||||
}
|
||||
|
||||
i = len % 4;
|
||||
if (i) {
|
||||
b1 = 0; b2 = 0; b3 = 0;
|
||||
|
||||
switch (i) {
|
||||
case 3:
|
||||
b1 = *p++;
|
||||
b2 = *p++;
|
||||
b3 = *p++;
|
||||
break;
|
||||
case 2:
|
||||
b1 = *p++;
|
||||
b2 = *p++;
|
||||
break;
|
||||
case 1:
|
||||
b1 = *p++;
|
||||
break;
|
||||
}
|
||||
|
||||
REG_WRITE(data_reg, b3 << 16 | b2 << 8 | b1);
|
||||
}
|
||||
|
||||
val = FLD_VAL(len, 23, 8) | FLD_VAL(virtual_channel, 7, 6) |
|
||||
FLD_VAL(data_type, 5, 0);
|
||||
|
||||
REG_WRITE(ctrl_reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
|
||||
u8 *data, u16 len)
|
||||
{
|
||||
u8 cmd;
|
||||
|
||||
switch (data_type) {
|
||||
case DSI_DT_DCS_SHORT_WRITE_0:
|
||||
case DSI_DT_DCS_SHORT_WRITE_1:
|
||||
case DSI_DT_DCS_LONG_WRITE:
|
||||
cmd = *data;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*this prevents other package sending while doing msleep*/
|
||||
sender->status = MDFLD_DSI_PKG_SENDER_BUSY;
|
||||
|
||||
/*wait for 120 milliseconds in case exit_sleep_mode just be sent*/
|
||||
if (unlikely(cmd == DCS_ENTER_SLEEP_MODE)) {
|
||||
/*TODO: replace it with msleep later*/
|
||||
mdelay(120);
|
||||
}
|
||||
|
||||
if (unlikely(cmd == DCS_EXIT_SLEEP_MODE)) {
|
||||
/*TODO: replace it with msleep later*/
|
||||
mdelay(120);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
|
||||
u8 *data, u16 len)
|
||||
{
|
||||
u8 cmd;
|
||||
|
||||
switch (data_type) {
|
||||
case DSI_DT_DCS_SHORT_WRITE_0:
|
||||
case DSI_DT_DCS_SHORT_WRITE_1:
|
||||
case DSI_DT_DCS_LONG_WRITE:
|
||||
cmd = *data;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*update panel status*/
|
||||
if (unlikely(cmd == DCS_ENTER_SLEEP_MODE)) {
|
||||
sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP;
|
||||
/*TODO: replace it with msleep later*/
|
||||
mdelay(120);
|
||||
} else if (unlikely(cmd == DCS_EXIT_SLEEP_MODE)) {
|
||||
sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP;
|
||||
/*TODO: replace it with msleep later*/
|
||||
mdelay(120);
|
||||
} else if (unlikely(cmd == DCS_SOFT_RESET)) {
|
||||
/*TODO: replace it with msleep later*/
|
||||
mdelay(5);
|
||||
}
|
||||
|
||||
sender->status = MDFLD_DSI_PKG_SENDER_FREE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int send_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
|
||||
u8 *data, u16 len, bool hs)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*handle DSI error*/
|
||||
ret = dsi_error_handler(sender);
|
||||
if (ret) {
|
||||
DRM_ERROR("Error handling failed\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
/* send pkg */
|
||||
if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) {
|
||||
DRM_ERROR("sender is busy\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
ret = send_pkg_prepare(sender, data_type, data, len);
|
||||
if (ret) {
|
||||
DRM_ERROR("send_pkg_prepare error\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (data_type) {
|
||||
case DSI_DT_GENERIC_SHORT_WRITE_0:
|
||||
case DSI_DT_GENERIC_SHORT_WRITE_1:
|
||||
case DSI_DT_GENERIC_SHORT_WRITE_2:
|
||||
case DSI_DT_GENERIC_READ_0:
|
||||
case DSI_DT_GENERIC_READ_1:
|
||||
case DSI_DT_GENERIC_READ_2:
|
||||
case DSI_DT_DCS_SHORT_WRITE_0:
|
||||
case DSI_DT_DCS_SHORT_WRITE_1:
|
||||
case DSI_DT_DCS_READ:
|
||||
ret = send_short_pkg(sender, data_type, data[0], data[1], hs);
|
||||
break;
|
||||
case DSI_DT_GENERIC_LONG_WRITE:
|
||||
case DSI_DT_DCS_LONG_WRITE:
|
||||
ret = send_long_pkg(sender, data_type, data, len, hs);
|
||||
break;
|
||||
}
|
||||
|
||||
send_pkg_done(sender, data_type, data, len);
|
||||
|
||||
/*FIXME: should I query complete and fifo empty here?*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
|
||||
u32 len, bool hs)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!sender || !data || !len) {
|
||||
DRM_ERROR("Invalid parameters\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&sender->lock, flags);
|
||||
send_pkg(sender, DSI_DT_DCS_LONG_WRITE, data, len, hs);
|
||||
spin_unlock_irqrestore(&sender->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
|
||||
u8 param, u8 param_num, bool hs)
|
||||
{
|
||||
u8 data[2];
|
||||
unsigned long flags;
|
||||
u8 data_type;
|
||||
|
||||
if (!sender) {
|
||||
DRM_ERROR("Invalid parameter\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
data[0] = cmd;
|
||||
|
||||
if (param_num) {
|
||||
data_type = DSI_DT_DCS_SHORT_WRITE_1;
|
||||
data[1] = param;
|
||||
} else {
|
||||
data_type = DSI_DT_DCS_SHORT_WRITE_0;
|
||||
data[1] = 0;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&sender->lock, flags);
|
||||
send_pkg(sender, data_type, data, sizeof(data), hs);
|
||||
spin_unlock_irqrestore(&sender->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0,
|
||||
u8 param1, u8 param_num, bool hs)
|
||||
{
|
||||
u8 data[2];
|
||||
unsigned long flags;
|
||||
u8 data_type;
|
||||
|
||||
if (!sender || param_num > 2) {
|
||||
DRM_ERROR("Invalid parameter\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (param_num) {
|
||||
case 0:
|
||||
data_type = DSI_DT_GENERIC_SHORT_WRITE_0;
|
||||
data[0] = 0;
|
||||
data[1] = 0;
|
||||
break;
|
||||
case 1:
|
||||
data_type = DSI_DT_GENERIC_SHORT_WRITE_1;
|
||||
data[0] = param0;
|
||||
data[1] = 0;
|
||||
break;
|
||||
case 2:
|
||||
data_type = DSI_DT_GENERIC_SHORT_WRITE_2;
|
||||
data[0] = param0;
|
||||
data[1] = param1;
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&sender->lock, flags);
|
||||
send_pkg(sender, data_type, data, sizeof(data), hs);
|
||||
spin_unlock_irqrestore(&sender->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
|
||||
u32 len, bool hs)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!sender || !data || !len) {
|
||||
DRM_ERROR("Invalid parameters\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&sender->lock, flags);
|
||||
send_pkg(sender, DSI_DT_GENERIC_LONG_WRITE, data, len, hs);
|
||||
spin_unlock_irqrestore(&sender->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
|
||||
u8 *data, u16 len, u32 *data_out, u16 len_out, bool hs)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct drm_device *dev = sender->dev;
|
||||
int i;
|
||||
u32 gen_data_reg;
|
||||
int retry = MDFLD_DSI_READ_MAX_COUNT;
|
||||
|
||||
if (!sender || !data_out || !len_out) {
|
||||
DRM_ERROR("Invalid parameters\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* do reading.
|
||||
* 0) send out generic read request
|
||||
* 1) polling read data avail interrupt
|
||||
* 2) read data
|
||||
*/
|
||||
spin_lock_irqsave(&sender->lock, flags);
|
||||
|
||||
REG_WRITE(sender->mipi_intr_stat_reg, BIT(29));
|
||||
|
||||
if ((REG_READ(sender->mipi_intr_stat_reg) & BIT(29)))
|
||||
DRM_ERROR("Can NOT clean read data valid interrupt\n");
|
||||
|
||||
/*send out read request*/
|
||||
send_pkg(sender, data_type, data, len, hs);
|
||||
|
||||
/*polling read data avail interrupt*/
|
||||
while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & BIT(29))) {
|
||||
udelay(100);
|
||||
retry--;
|
||||
}
|
||||
|
||||
if (!retry) {
|
||||
spin_unlock_irqrestore(&sender->lock, flags);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
REG_WRITE(sender->mipi_intr_stat_reg, BIT(29));
|
||||
|
||||
/*read data*/
|
||||
if (hs)
|
||||
gen_data_reg = sender->mipi_hs_gen_data_reg;
|
||||
else
|
||||
gen_data_reg = sender->mipi_lp_gen_data_reg;
|
||||
|
||||
for (i = 0; i < len_out; i++)
|
||||
*(data_out + i) = REG_READ(gen_data_reg);
|
||||
|
||||
spin_unlock_irqrestore(&sender->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
|
||||
u32 *data, u16 len, bool hs)
|
||||
{
|
||||
if (!sender || !data || !len) {
|
||||
DRM_ERROR("Invalid parameters\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return __read_panel_data(sender, DSI_DT_DCS_READ, &cmd, 1,
|
||||
data, len, hs);
|
||||
}
|
||||
|
||||
int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
|
||||
int pipe)
|
||||
{
|
||||
struct mdfld_dsi_pkg_sender *pkg_sender;
|
||||
struct mdfld_dsi_config *dsi_config =
|
||||
mdfld_dsi_get_config(dsi_connector);
|
||||
struct drm_device *dev = dsi_config->dev;
|
||||
u32 mipi_val = 0;
|
||||
|
||||
if (!dsi_connector) {
|
||||
DRM_ERROR("Invalid parameter\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pkg_sender = dsi_connector->pkg_sender;
|
||||
|
||||
if (!pkg_sender || IS_ERR(pkg_sender)) {
|
||||
pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender),
|
||||
GFP_KERNEL);
|
||||
if (!pkg_sender) {
|
||||
DRM_ERROR("Create DSI pkg sender failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
dsi_connector->pkg_sender = (void *)pkg_sender;
|
||||
}
|
||||
|
||||
pkg_sender->dev = dev;
|
||||
pkg_sender->dsi_connector = dsi_connector;
|
||||
pkg_sender->pipe = pipe;
|
||||
pkg_sender->pkg_num = 0;
|
||||
pkg_sender->panel_mode = 0;
|
||||
pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE;
|
||||
|
||||
/*init regs*/
|
||||
if (pipe == 0) {
|
||||
pkg_sender->dpll_reg = MRST_DPLL_A;
|
||||
pkg_sender->dspcntr_reg = DSPACNTR;
|
||||
pkg_sender->pipeconf_reg = PIPEACONF;
|
||||
pkg_sender->dsplinoff_reg = DSPALINOFF;
|
||||
pkg_sender->dspsurf_reg = DSPASURF;
|
||||
pkg_sender->pipestat_reg = PIPEASTAT;
|
||||
} else if (pipe == 2) {
|
||||
pkg_sender->dpll_reg = MRST_DPLL_A;
|
||||
pkg_sender->dspcntr_reg = DSPCCNTR;
|
||||
pkg_sender->pipeconf_reg = PIPECCONF;
|
||||
pkg_sender->dsplinoff_reg = DSPCLINOFF;
|
||||
pkg_sender->dspsurf_reg = DSPCSURF;
|
||||
pkg_sender->pipestat_reg = PIPECSTAT;
|
||||
}
|
||||
|
||||
pkg_sender->mipi_intr_stat_reg = MIPI_INTR_STAT_REG(pipe);
|
||||
pkg_sender->mipi_lp_gen_data_reg = MIPI_LP_GEN_DATA_REG(pipe);
|
||||
pkg_sender->mipi_hs_gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe);
|
||||
pkg_sender->mipi_lp_gen_ctrl_reg = MIPI_LP_GEN_CTRL_REG(pipe);
|
||||
pkg_sender->mipi_hs_gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe);
|
||||
pkg_sender->mipi_gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
|
||||
pkg_sender->mipi_data_addr_reg = MIPI_DATA_ADD_REG(pipe);
|
||||
pkg_sender->mipi_data_len_reg = MIPI_DATA_LEN_REG(pipe);
|
||||
pkg_sender->mipi_cmd_addr_reg = MIPI_CMD_ADD_REG(pipe);
|
||||
pkg_sender->mipi_cmd_len_reg = MIPI_CMD_LEN_REG(pipe);
|
||||
|
||||
/*init lock*/
|
||||
spin_lock_init(&pkg_sender->lock);
|
||||
|
||||
if (mdfld_get_panel_type(dev, pipe) != TC35876X) {
|
||||
/**
|
||||
* For video mode, don't enable DPI timing output here,
|
||||
* will init the DPI timing output during mode setting.
|
||||
*/
|
||||
mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
|
||||
|
||||
if (pipe == 0)
|
||||
mipi_val |= 0x2;
|
||||
|
||||
REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi_val);
|
||||
REG_READ(MIPI_PORT_CONTROL(pipe));
|
||||
|
||||
/* do dsi controller init */
|
||||
mdfld_dsi_controller_init(dsi_config, pipe);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender)
|
||||
{
|
||||
if (!sender || IS_ERR(sender))
|
||||
return;
|
||||
|
||||
/*free*/
|
||||
kfree(sender);
|
||||
}
|
||||
|
||||
|
92
drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h
Normal file
92
drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright © 2010 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:
|
||||
* Jackie Li<yaodong.li@intel.com>
|
||||
*/
|
||||
#ifndef __MDFLD_DSI_PKG_SENDER_H__
|
||||
#define __MDFLD_DSI_PKG_SENDER_H__
|
||||
|
||||
#include <linux/kthread.h>
|
||||
|
||||
#define MDFLD_MAX_DCS_PARAM 8
|
||||
|
||||
struct mdfld_dsi_pkg_sender {
|
||||
struct drm_device *dev;
|
||||
struct mdfld_dsi_connector *dsi_connector;
|
||||
u32 status;
|
||||
u32 panel_mode;
|
||||
|
||||
int pipe;
|
||||
|
||||
spinlock_t lock;
|
||||
|
||||
u32 pkg_num;
|
||||
|
||||
/* Registers */
|
||||
u32 dpll_reg;
|
||||
u32 dspcntr_reg;
|
||||
u32 pipeconf_reg;
|
||||
u32 pipestat_reg;
|
||||
u32 dsplinoff_reg;
|
||||
u32 dspsurf_reg;
|
||||
|
||||
u32 mipi_intr_stat_reg;
|
||||
u32 mipi_lp_gen_data_reg;
|
||||
u32 mipi_hs_gen_data_reg;
|
||||
u32 mipi_lp_gen_ctrl_reg;
|
||||
u32 mipi_hs_gen_ctrl_reg;
|
||||
u32 mipi_gen_fifo_stat_reg;
|
||||
u32 mipi_data_addr_reg;
|
||||
u32 mipi_data_len_reg;
|
||||
u32 mipi_cmd_addr_reg;
|
||||
u32 mipi_cmd_len_reg;
|
||||
};
|
||||
|
||||
/* DCS definitions */
|
||||
#define DCS_SOFT_RESET 0x01
|
||||
#define DCS_ENTER_SLEEP_MODE 0x10
|
||||
#define DCS_EXIT_SLEEP_MODE 0x11
|
||||
#define DCS_SET_DISPLAY_OFF 0x28
|
||||
#define DCS_SET_DISPLAY_ON 0x29
|
||||
#define DCS_SET_COLUMN_ADDRESS 0x2a
|
||||
#define DCS_SET_PAGE_ADDRESS 0x2b
|
||||
#define DCS_WRITE_MEM_START 0x2c
|
||||
#define DCS_SET_TEAR_OFF 0x34
|
||||
#define DCS_SET_TEAR_ON 0x35
|
||||
|
||||
extern int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
|
||||
int pipe);
|
||||
extern void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender);
|
||||
int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
|
||||
u8 param, u8 param_num, bool hs);
|
||||
int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
|
||||
u32 len, bool hs);
|
||||
int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0,
|
||||
u8 param1, u8 param_num, bool hs);
|
||||
int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
|
||||
u32 len, bool hs);
|
||||
/* Read interfaces */
|
||||
int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
|
||||
u32 *data, u16 len, bool hs);
|
||||
|
||||
#endif
|
1180
drivers/gpu/drm/gma500/mdfld_intel_display.c
Normal file
1180
drivers/gpu/drm/gma500/mdfld_intel_display.c
Normal file
File diff suppressed because it is too large
Load Diff
74
drivers/gpu/drm/gma500/mdfld_output.c
Normal file
74
drivers/gpu/drm/gma500/mdfld_output.c
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2010 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, sublicensen
|
||||
* 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:
|
||||
* Thomas Eaton <thomas.g.eaton@intel.com>
|
||||
* Scott Rowe <scott.m.rowe@intel.com>
|
||||
*/
|
||||
|
||||
#include "mdfld_output.h"
|
||||
#include "mdfld_dsi_dpi.h"
|
||||
#include "mdfld_dsi_output.h"
|
||||
|
||||
#include "tc35876x-dsi-lvds.h"
|
||||
|
||||
int mdfld_get_panel_type(struct drm_device *dev, int pipe)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
return dev_priv->mdfld_panel_id;
|
||||
}
|
||||
|
||||
static void mdfld_init_panel(struct drm_device *dev, int mipi_pipe,
|
||||
int p_type)
|
||||
{
|
||||
switch (p_type) {
|
||||
case TPO_VID:
|
||||
mdfld_dsi_output_init(dev, mipi_pipe, &mdfld_tpo_vid_funcs);
|
||||
break;
|
||||
case TC35876X:
|
||||
tc35876x_init(dev);
|
||||
mdfld_dsi_output_init(dev, mipi_pipe, &mdfld_tc35876x_funcs);
|
||||
break;
|
||||
case TMD_VID:
|
||||
mdfld_dsi_output_init(dev, mipi_pipe, &mdfld_tmd_vid_funcs);
|
||||
break;
|
||||
case HDMI:
|
||||
/* if (dev_priv->mdfld_hdmi_present)
|
||||
mdfld_hdmi_init(dev, &dev_priv->mode_dev); */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int mdfld_output_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
|
||||
/* FIXME: hardcoded for now */
|
||||
dev_priv->mdfld_panel_id = TC35876X;
|
||||
/* MIPI panel 1 */
|
||||
mdfld_init_panel(dev, 0, dev_priv->mdfld_panel_id);
|
||||
/* HDMI panel */
|
||||
mdfld_init_panel(dev, 1, HDMI);
|
||||
return 0;
|
||||
}
|
||||
|
77
drivers/gpu/drm/gma500/mdfld_output.h
Normal file
77
drivers/gpu/drm/gma500/mdfld_output.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2010 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, sublicensen
|
||||
* 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:
|
||||
* Thomas Eaton <thomas.g.eaton@intel.com>
|
||||
* Scott Rowe <scott.m.rowe@intel.com>
|
||||
*/
|
||||
|
||||
#ifndef MDFLD_OUTPUT_H
|
||||
#define MDFLD_OUTPUT_H
|
||||
|
||||
#include "psb_drv.h"
|
||||
|
||||
#define TPO_PANEL_WIDTH 84
|
||||
#define TPO_PANEL_HEIGHT 46
|
||||
#define TMD_PANEL_WIDTH 39
|
||||
#define TMD_PANEL_HEIGHT 71
|
||||
|
||||
struct mdfld_dsi_config;
|
||||
|
||||
enum panel_type {
|
||||
TPO_VID,
|
||||
TMD_VID,
|
||||
HDMI,
|
||||
TC35876X,
|
||||
};
|
||||
|
||||
struct panel_info {
|
||||
u32 width_mm;
|
||||
u32 height_mm;
|
||||
/* Other info */
|
||||
};
|
||||
|
||||
struct panel_funcs {
|
||||
const struct drm_encoder_funcs *encoder_funcs;
|
||||
const struct drm_encoder_helper_funcs *encoder_helper_funcs;
|
||||
struct drm_display_mode * (*get_config_mode)(struct drm_device *);
|
||||
int (*get_panel_info)(struct drm_device *, int, struct panel_info *);
|
||||
int (*reset)(int pipe);
|
||||
void (*drv_ic_init)(struct mdfld_dsi_config *dsi_config, int pipe);
|
||||
};
|
||||
|
||||
int mdfld_output_init(struct drm_device *dev);
|
||||
|
||||
struct backlight_device *mdfld_get_backlight_device(void);
|
||||
int mdfld_set_brightness(struct backlight_device *bd);
|
||||
|
||||
int mdfld_get_panel_type(struct drm_device *dev, int pipe);
|
||||
|
||||
extern const struct drm_crtc_helper_funcs mdfld_helper_funcs;
|
||||
|
||||
extern const struct panel_funcs mdfld_tmd_vid_funcs;
|
||||
extern const struct panel_funcs mdfld_tpo_vid_funcs;
|
||||
|
||||
extern void mdfld_disable_crtc(struct drm_device *dev, int pipe);
|
||||
extern void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe);
|
||||
extern void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe);
|
||||
#endif
|
201
drivers/gpu/drm/gma500/mdfld_tmd_vid.c
Normal file
201
drivers/gpu/drm/gma500/mdfld_tmd_vid.c
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright © 2010 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:
|
||||
* Jim Liu <jim.liu@intel.com>
|
||||
* Jackie Li<yaodong.li@intel.com>
|
||||
* Gideon Eaton <eaton.
|
||||
* Scott Rowe <scott.m.rowe@intel.com>
|
||||
*/
|
||||
|
||||
#include "mdfld_dsi_dpi.h"
|
||||
#include "mdfld_dsi_pkg_sender.h"
|
||||
|
||||
static struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct oaktrail_timing_info *ti = &dev_priv->gct_data.DTD;
|
||||
bool use_gct = false; /*Disable GCT for now*/
|
||||
|
||||
mode = kzalloc(sizeof(*mode), GFP_KERNEL);
|
||||
if (!mode)
|
||||
return NULL;
|
||||
|
||||
if (use_gct) {
|
||||
mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
|
||||
mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
|
||||
mode->hsync_start = mode->hdisplay + \
|
||||
((ti->hsync_offset_hi << 8) | \
|
||||
ti->hsync_offset_lo);
|
||||
mode->hsync_end = mode->hsync_start + \
|
||||
((ti->hsync_pulse_width_hi << 8) | \
|
||||
ti->hsync_pulse_width_lo);
|
||||
mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
|
||||
ti->hblank_lo);
|
||||
mode->vsync_start = \
|
||||
mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
|
||||
ti->vsync_offset_lo);
|
||||
mode->vsync_end = \
|
||||
mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
|
||||
ti->vsync_pulse_width_lo);
|
||||
mode->vtotal = mode->vdisplay + \
|
||||
((ti->vblank_hi << 8) | ti->vblank_lo);
|
||||
mode->clock = ti->pixel_clock * 10;
|
||||
|
||||
dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
|
||||
dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
|
||||
dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
|
||||
dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
|
||||
dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
|
||||
dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
|
||||
dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
|
||||
dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
|
||||
dev_dbg(dev->dev, "clock is %d\n", mode->clock);
|
||||
} else {
|
||||
mode->hdisplay = 480;
|
||||
mode->vdisplay = 854;
|
||||
mode->hsync_start = 487;
|
||||
mode->hsync_end = 490;
|
||||
mode->htotal = 499;
|
||||
mode->vsync_start = 861;
|
||||
mode->vsync_end = 865;
|
||||
mode->vtotal = 873;
|
||||
mode->clock = 33264;
|
||||
}
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
drm_mode_set_crtcinfo(mode, 0);
|
||||
|
||||
mode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static int tmd_vid_get_panel_info(struct drm_device *dev,
|
||||
int pipe,
|
||||
struct panel_info *pi)
|
||||
{
|
||||
if (!dev || !pi)
|
||||
return -EINVAL;
|
||||
|
||||
pi->width_mm = TMD_PANEL_WIDTH;
|
||||
pi->height_mm = TMD_PANEL_HEIGHT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ************************************************************************* *\
|
||||
* FUNCTION: mdfld_init_TMD_MIPI
|
||||
*
|
||||
* DESCRIPTION: This function is called only by mrst_dsi_mode_set and
|
||||
* restore_display_registers. since this function does not
|
||||
* acquire the mutex, it is important that the calling function
|
||||
* does!
|
||||
\* ************************************************************************* */
|
||||
|
||||
/* FIXME: make the below data u8 instead of u32; note byte order! */
|
||||
static u32 tmd_cmd_mcap_off[] = {0x000000b2};
|
||||
static u32 tmd_cmd_enable_lane_switch[] = {0x000101ef};
|
||||
static u32 tmd_cmd_set_lane_num[] = {0x006360ef};
|
||||
static u32 tmd_cmd_pushing_clock0[] = {0x00cc2fef};
|
||||
static u32 tmd_cmd_pushing_clock1[] = {0x00dd6eef};
|
||||
static u32 tmd_cmd_set_mode[] = {0x000000b3};
|
||||
static u32 tmd_cmd_set_sync_pulse_mode[] = {0x000961ef};
|
||||
static u32 tmd_cmd_set_column[] = {0x0100002a, 0x000000df};
|
||||
static u32 tmd_cmd_set_page[] = {0x0300002b, 0x00000055};
|
||||
static u32 tmd_cmd_set_video_mode[] = {0x00000153};
|
||||
/*no auto_bl,need add in furture*/
|
||||
static u32 tmd_cmd_enable_backlight[] = {0x00005ab4};
|
||||
static u32 tmd_cmd_set_backlight_dimming[] = {0x00000ebd};
|
||||
|
||||
static void mdfld_dsi_tmd_drv_ic_init(struct mdfld_dsi_config *dsi_config,
|
||||
int pipe)
|
||||
{
|
||||
struct mdfld_dsi_pkg_sender *sender
|
||||
= mdfld_dsi_get_pkg_sender(dsi_config);
|
||||
|
||||
DRM_INFO("Enter mdfld init TMD MIPI display.\n");
|
||||
|
||||
if (!sender) {
|
||||
DRM_ERROR("Cannot get sender\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dsi_config->dvr_ic_inited)
|
||||
return;
|
||||
|
||||
msleep(3);
|
||||
|
||||
/* FIXME: make the below data u8 instead of u32; note byte order! */
|
||||
|
||||
mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_mcap_off,
|
||||
sizeof(tmd_cmd_mcap_off), false);
|
||||
mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_enable_lane_switch,
|
||||
sizeof(tmd_cmd_enable_lane_switch), false);
|
||||
mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_lane_num,
|
||||
sizeof(tmd_cmd_set_lane_num), false);
|
||||
mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_pushing_clock0,
|
||||
sizeof(tmd_cmd_pushing_clock0), false);
|
||||
mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_pushing_clock1,
|
||||
sizeof(tmd_cmd_pushing_clock1), false);
|
||||
mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_mode,
|
||||
sizeof(tmd_cmd_set_mode), false);
|
||||
mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_sync_pulse_mode,
|
||||
sizeof(tmd_cmd_set_sync_pulse_mode), false);
|
||||
mdfld_dsi_send_mcs_long(sender, (u8 *) tmd_cmd_set_column,
|
||||
sizeof(tmd_cmd_set_column), false);
|
||||
mdfld_dsi_send_mcs_long(sender, (u8 *) tmd_cmd_set_page,
|
||||
sizeof(tmd_cmd_set_page), false);
|
||||
mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_video_mode,
|
||||
sizeof(tmd_cmd_set_video_mode), false);
|
||||
mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_enable_backlight,
|
||||
sizeof(tmd_cmd_enable_backlight), false);
|
||||
mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_backlight_dimming,
|
||||
sizeof(tmd_cmd_set_backlight_dimming), false);
|
||||
|
||||
dsi_config->dvr_ic_inited = 1;
|
||||
}
|
||||
|
||||
/*TPO DPI encoder helper funcs*/
|
||||
static const struct drm_encoder_helper_funcs
|
||||
mdfld_tpo_dpi_encoder_helper_funcs = {
|
||||
.dpms = mdfld_dsi_dpi_dpms,
|
||||
.mode_fixup = mdfld_dsi_dpi_mode_fixup,
|
||||
.prepare = mdfld_dsi_dpi_prepare,
|
||||
.mode_set = mdfld_dsi_dpi_mode_set,
|
||||
.commit = mdfld_dsi_dpi_commit,
|
||||
};
|
||||
|
||||
/*TPO DPI encoder funcs*/
|
||||
static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
const struct panel_funcs mdfld_tmd_vid_funcs = {
|
||||
.encoder_funcs = &mdfld_tpo_dpi_encoder_funcs,
|
||||
.encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs,
|
||||
.get_config_mode = &tmd_vid_get_config_mode,
|
||||
.get_panel_info = tmd_vid_get_panel_info,
|
||||
.reset = mdfld_dsi_panel_reset,
|
||||
.drv_ic_init = mdfld_dsi_tmd_drv_ic_init,
|
||||
};
|
124
drivers/gpu/drm/gma500/mdfld_tpo_vid.c
Normal file
124
drivers/gpu/drm/gma500/mdfld_tpo_vid.c
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright © 2010 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:
|
||||
* jim liu <jim.liu@intel.com>
|
||||
* Jackie Li<yaodong.li@intel.com>
|
||||
*/
|
||||
|
||||
#include "mdfld_dsi_dpi.h"
|
||||
|
||||
static struct drm_display_mode *tpo_vid_get_config_mode(struct drm_device *dev)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct oaktrail_timing_info *ti = &dev_priv->gct_data.DTD;
|
||||
bool use_gct = false;
|
||||
|
||||
mode = kzalloc(sizeof(*mode), GFP_KERNEL);
|
||||
if (!mode)
|
||||
return NULL;
|
||||
|
||||
if (use_gct) {
|
||||
mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
|
||||
mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
|
||||
mode->hsync_start = mode->hdisplay +
|
||||
((ti->hsync_offset_hi << 8) |
|
||||
ti->hsync_offset_lo);
|
||||
mode->hsync_end = mode->hsync_start +
|
||||
((ti->hsync_pulse_width_hi << 8) |
|
||||
ti->hsync_pulse_width_lo);
|
||||
mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) |
|
||||
ti->hblank_lo);
|
||||
mode->vsync_start =
|
||||
mode->vdisplay + ((ti->vsync_offset_hi << 8) |
|
||||
ti->vsync_offset_lo);
|
||||
mode->vsync_end =
|
||||
mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) |
|
||||
ti->vsync_pulse_width_lo);
|
||||
mode->vtotal = mode->vdisplay +
|
||||
((ti->vblank_hi << 8) | ti->vblank_lo);
|
||||
mode->clock = ti->pixel_clock * 10;
|
||||
|
||||
dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
|
||||
dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
|
||||
dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
|
||||
dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
|
||||
dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
|
||||
dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
|
||||
dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
|
||||
dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
|
||||
dev_dbg(dev->dev, "clock is %d\n", mode->clock);
|
||||
} else {
|
||||
mode->hdisplay = 864;
|
||||
mode->vdisplay = 480;
|
||||
mode->hsync_start = 873;
|
||||
mode->hsync_end = 876;
|
||||
mode->htotal = 887;
|
||||
mode->vsync_start = 487;
|
||||
mode->vsync_end = 490;
|
||||
mode->vtotal = 499;
|
||||
mode->clock = 33264;
|
||||
}
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
drm_mode_set_crtcinfo(mode, 0);
|
||||
|
||||
mode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static int tpo_vid_get_panel_info(struct drm_device *dev,
|
||||
int pipe,
|
||||
struct panel_info *pi)
|
||||
{
|
||||
if (!dev || !pi)
|
||||
return -EINVAL;
|
||||
|
||||
pi->width_mm = TPO_PANEL_WIDTH;
|
||||
pi->height_mm = TPO_PANEL_HEIGHT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*TPO DPI encoder helper funcs*/
|
||||
static const struct drm_encoder_helper_funcs
|
||||
mdfld_tpo_dpi_encoder_helper_funcs = {
|
||||
.dpms = mdfld_dsi_dpi_dpms,
|
||||
.mode_fixup = mdfld_dsi_dpi_mode_fixup,
|
||||
.prepare = mdfld_dsi_dpi_prepare,
|
||||
.mode_set = mdfld_dsi_dpi_mode_set,
|
||||
.commit = mdfld_dsi_dpi_commit,
|
||||
};
|
||||
|
||||
/*TPO DPI encoder funcs*/
|
||||
static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
const struct panel_funcs mdfld_tpo_vid_funcs = {
|
||||
.encoder_funcs = &mdfld_tpo_dpi_encoder_funcs,
|
||||
.encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs,
|
||||
.get_config_mode = &tpo_vid_get_config_mode,
|
||||
.get_panel_info = tpo_vid_get_panel_info,
|
||||
};
|
@ -270,7 +270,7 @@ out_err1:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void psb_mmu_free_pt(struct psb_mmu_pt *pt)
|
||||
static void psb_mmu_free_pt(struct psb_mmu_pt *pt)
|
||||
{
|
||||
__free_page(pt->p);
|
||||
kfree(pt);
|
||||
@ -351,7 +351,7 @@ static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd)
|
||||
return pt;
|
||||
}
|
||||
|
||||
struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
|
||||
static struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd,
|
||||
unsigned long addr)
|
||||
{
|
||||
uint32_t index = psb_mmu_pd_index(addr);
|
||||
@ -488,15 +488,6 @@ struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver)
|
||||
return pd;
|
||||
}
|
||||
|
||||
/* Returns the physical address of the PD shared by sgx/msvdx */
|
||||
uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver)
|
||||
{
|
||||
struct psb_mmu_pd *pd;
|
||||
|
||||
pd = psb_mmu_get_default_pd(driver);
|
||||
return page_to_pfn(pd->p) << PAGE_SHIFT;
|
||||
}
|
||||
|
||||
void psb_mmu_driver_takedown(struct psb_mmu_driver *driver)
|
||||
{
|
||||
psb_mmu_free_pagedir(driver->default_pd);
|
||||
|
@ -115,7 +115,7 @@ static void oaktrail_clock(int refclk, struct oaktrail_clock_t *clock)
|
||||
clock->dot = (refclk * clock->m) / (14 * clock->p1);
|
||||
}
|
||||
|
||||
void mrstPrintPll(char *prefix, struct oaktrail_clock_t *clock)
|
||||
static void mrstPrintPll(char *prefix, struct oaktrail_clock_t *clock)
|
||||
{
|
||||
pr_debug("%s: dotclock = %d, m = %d, p1 = %d.\n",
|
||||
prefix, clock->dot, clock->m, clock->p1);
|
||||
@ -169,7 +169,6 @@ static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
int dspbase_reg = (pipe == 0) ? MRST_DSPABASE : DSPBBASE;
|
||||
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
|
||||
u32 temp;
|
||||
bool enabled;
|
||||
|
||||
if (!gma_power_begin(dev, true))
|
||||
return;
|
||||
@ -253,8 +252,6 @@ static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
break;
|
||||
}
|
||||
|
||||
enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
|
||||
|
||||
/*Set FIFO Watermarks*/
|
||||
REG_WRITE(DSPARB, 0x3FFF);
|
||||
REG_WRITE(DSPFW1, 0x3F88080A);
|
||||
@ -310,7 +307,7 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc,
|
||||
struct oaktrail_clock_t clock;
|
||||
u32 dpll = 0, fp = 0, dspcntr, pipeconf;
|
||||
bool ok, is_sdvo = false;
|
||||
bool is_crt = false, is_lvds = false, is_tv = false;
|
||||
bool is_lvds = false;
|
||||
bool is_mipi = false;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
struct psb_intel_encoder *psb_intel_encoder = NULL;
|
||||
@ -340,12 +337,6 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc,
|
||||
case INTEL_OUTPUT_SDVO:
|
||||
is_sdvo = true;
|
||||
break;
|
||||
case INTEL_OUTPUT_TVOUT:
|
||||
is_tv = true;
|
||||
break;
|
||||
case INTEL_OUTPUT_ANALOG:
|
||||
is_crt = true;
|
||||
break;
|
||||
case INTEL_OUTPUT_MIPI:
|
||||
is_mipi = true;
|
||||
break;
|
||||
@ -428,9 +419,6 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc,
|
||||
else
|
||||
dspcntr |= DISPPLANE_SEL_PIPE_B;
|
||||
|
||||
dev_priv->dspcntr = dspcntr |= DISPLAY_PLANE_ENABLE;
|
||||
dev_priv->pipeconf = pipeconf |= PIPEACONF_ENABLE;
|
||||
|
||||
if (is_mipi)
|
||||
goto oaktrail_crtc_mode_set_exit;
|
||||
|
||||
@ -517,7 +505,7 @@ static bool oaktrail_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
return true;
|
||||
}
|
||||
|
||||
int oaktrail_pipe_set_base(struct drm_crtc *crtc,
|
||||
static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
|
||||
int x, int y, struct drm_framebuffer *old_fb)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
|
@ -141,7 +141,7 @@ static const struct backlight_ops oaktrail_ops = {
|
||||
.update_status = oaktrail_set_brightness,
|
||||
};
|
||||
|
||||
int oaktrail_backlight_init(struct drm_device *dev)
|
||||
static int oaktrail_backlight_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
@ -176,10 +176,6 @@ int oaktrail_backlight_init(struct drm_device *dev)
|
||||
* for power management
|
||||
*/
|
||||
|
||||
static void oaktrail_init_pm(struct drm_device *dev)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* oaktrail_save_display_registers - save registers lost on suspend
|
||||
* @dev: our DRM device
|
||||
@ -190,81 +186,82 @@ static void oaktrail_init_pm(struct drm_device *dev)
|
||||
static int oaktrail_save_display_registers(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct psb_save_area *regs = &dev_priv->regs;
|
||||
int i;
|
||||
u32 pp_stat;
|
||||
|
||||
/* Display arbitration control + watermarks */
|
||||
dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
|
||||
dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
|
||||
dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
|
||||
dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
|
||||
dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
|
||||
dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
|
||||
dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
|
||||
dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
|
||||
regs->psb.saveDSPARB = PSB_RVDC32(DSPARB);
|
||||
regs->psb.saveDSPFW1 = PSB_RVDC32(DSPFW1);
|
||||
regs->psb.saveDSPFW2 = PSB_RVDC32(DSPFW2);
|
||||
regs->psb.saveDSPFW3 = PSB_RVDC32(DSPFW3);
|
||||
regs->psb.saveDSPFW4 = PSB_RVDC32(DSPFW4);
|
||||
regs->psb.saveDSPFW5 = PSB_RVDC32(DSPFW5);
|
||||
regs->psb.saveDSPFW6 = PSB_RVDC32(DSPFW6);
|
||||
regs->psb.saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
|
||||
|
||||
/* Pipe & plane A info */
|
||||
dev_priv->savePIPEACONF = PSB_RVDC32(PIPEACONF);
|
||||
dev_priv->savePIPEASRC = PSB_RVDC32(PIPEASRC);
|
||||
dev_priv->saveFPA0 = PSB_RVDC32(MRST_FPA0);
|
||||
dev_priv->saveFPA1 = PSB_RVDC32(MRST_FPA1);
|
||||
dev_priv->saveDPLL_A = PSB_RVDC32(MRST_DPLL_A);
|
||||
dev_priv->saveHTOTAL_A = PSB_RVDC32(HTOTAL_A);
|
||||
dev_priv->saveHBLANK_A = PSB_RVDC32(HBLANK_A);
|
||||
dev_priv->saveHSYNC_A = PSB_RVDC32(HSYNC_A);
|
||||
dev_priv->saveVTOTAL_A = PSB_RVDC32(VTOTAL_A);
|
||||
dev_priv->saveVBLANK_A = PSB_RVDC32(VBLANK_A);
|
||||
dev_priv->saveVSYNC_A = PSB_RVDC32(VSYNC_A);
|
||||
dev_priv->saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A);
|
||||
dev_priv->saveDSPACNTR = PSB_RVDC32(DSPACNTR);
|
||||
dev_priv->saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE);
|
||||
dev_priv->saveDSPAADDR = PSB_RVDC32(DSPABASE);
|
||||
dev_priv->saveDSPASURF = PSB_RVDC32(DSPASURF);
|
||||
dev_priv->saveDSPALINOFF = PSB_RVDC32(DSPALINOFF);
|
||||
dev_priv->saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF);
|
||||
regs->psb.savePIPEACONF = PSB_RVDC32(PIPEACONF);
|
||||
regs->psb.savePIPEASRC = PSB_RVDC32(PIPEASRC);
|
||||
regs->psb.saveFPA0 = PSB_RVDC32(MRST_FPA0);
|
||||
regs->psb.saveFPA1 = PSB_RVDC32(MRST_FPA1);
|
||||
regs->psb.saveDPLL_A = PSB_RVDC32(MRST_DPLL_A);
|
||||
regs->psb.saveHTOTAL_A = PSB_RVDC32(HTOTAL_A);
|
||||
regs->psb.saveHBLANK_A = PSB_RVDC32(HBLANK_A);
|
||||
regs->psb.saveHSYNC_A = PSB_RVDC32(HSYNC_A);
|
||||
regs->psb.saveVTOTAL_A = PSB_RVDC32(VTOTAL_A);
|
||||
regs->psb.saveVBLANK_A = PSB_RVDC32(VBLANK_A);
|
||||
regs->psb.saveVSYNC_A = PSB_RVDC32(VSYNC_A);
|
||||
regs->psb.saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A);
|
||||
regs->psb.saveDSPACNTR = PSB_RVDC32(DSPACNTR);
|
||||
regs->psb.saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE);
|
||||
regs->psb.saveDSPAADDR = PSB_RVDC32(DSPABASE);
|
||||
regs->psb.saveDSPASURF = PSB_RVDC32(DSPASURF);
|
||||
regs->psb.saveDSPALINOFF = PSB_RVDC32(DSPALINOFF);
|
||||
regs->psb.saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF);
|
||||
|
||||
/* Save cursor regs */
|
||||
dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
|
||||
dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
|
||||
dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
|
||||
regs->psb.saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
|
||||
regs->psb.saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
|
||||
regs->psb.saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
|
||||
|
||||
/* Save palette (gamma) */
|
||||
for (i = 0; i < 256; i++)
|
||||
dev_priv->save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i << 2));
|
||||
regs->psb.save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i << 2));
|
||||
|
||||
if (dev_priv->hdmi_priv)
|
||||
oaktrail_hdmi_save(dev);
|
||||
|
||||
/* Save performance state */
|
||||
dev_priv->savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE);
|
||||
regs->psb.savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE);
|
||||
|
||||
/* LVDS state */
|
||||
dev_priv->savePP_CONTROL = PSB_RVDC32(PP_CONTROL);
|
||||
dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
|
||||
dev_priv->savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS);
|
||||
dev_priv->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL);
|
||||
dev_priv->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2);
|
||||
dev_priv->saveLVDS = PSB_RVDC32(LVDS);
|
||||
dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
|
||||
dev_priv->savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON);
|
||||
dev_priv->savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF);
|
||||
dev_priv->savePP_DIVISOR = PSB_RVDC32(PP_CYCLE);
|
||||
regs->psb.savePP_CONTROL = PSB_RVDC32(PP_CONTROL);
|
||||
regs->psb.savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
|
||||
regs->psb.savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS);
|
||||
regs->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL);
|
||||
regs->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2);
|
||||
regs->psb.saveLVDS = PSB_RVDC32(LVDS);
|
||||
regs->psb.savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
|
||||
regs->psb.savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON);
|
||||
regs->psb.savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF);
|
||||
regs->psb.savePP_DIVISOR = PSB_RVDC32(PP_CYCLE);
|
||||
|
||||
/* HW overlay */
|
||||
dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
|
||||
dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
|
||||
dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
|
||||
dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
|
||||
dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
|
||||
dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
|
||||
dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
|
||||
regs->psb.saveOV_OVADD = PSB_RVDC32(OV_OVADD);
|
||||
regs->psb.saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
|
||||
regs->psb.saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
|
||||
regs->psb.saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
|
||||
regs->psb.saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
|
||||
regs->psb.saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
|
||||
regs->psb.saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
|
||||
|
||||
/* DPST registers */
|
||||
dev_priv->saveHISTOGRAM_INT_CONTROL_REG =
|
||||
regs->psb.saveHISTOGRAM_INT_CONTROL_REG =
|
||||
PSB_RVDC32(HISTOGRAM_INT_CONTROL);
|
||||
dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG =
|
||||
regs->psb.saveHISTOGRAM_LOGIC_CONTROL_REG =
|
||||
PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
|
||||
dev_priv->savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC);
|
||||
regs->psb.savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC);
|
||||
|
||||
if (dev_priv->iLVDS_enable) {
|
||||
/* Shut down the panel */
|
||||
@ -302,79 +299,80 @@ static int oaktrail_save_display_registers(struct drm_device *dev)
|
||||
static int oaktrail_restore_display_registers(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct psb_save_area *regs = &dev_priv->regs;
|
||||
u32 pp_stat;
|
||||
int i;
|
||||
|
||||
/* Display arbitration + watermarks */
|
||||
PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
|
||||
PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
|
||||
PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
|
||||
PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
|
||||
PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
|
||||
PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
|
||||
PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
|
||||
PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
|
||||
PSB_WVDC32(regs->psb.saveDSPARB, DSPARB);
|
||||
PSB_WVDC32(regs->psb.saveDSPFW1, DSPFW1);
|
||||
PSB_WVDC32(regs->psb.saveDSPFW2, DSPFW2);
|
||||
PSB_WVDC32(regs->psb.saveDSPFW3, DSPFW3);
|
||||
PSB_WVDC32(regs->psb.saveDSPFW4, DSPFW4);
|
||||
PSB_WVDC32(regs->psb.saveDSPFW5, DSPFW5);
|
||||
PSB_WVDC32(regs->psb.saveDSPFW6, DSPFW6);
|
||||
PSB_WVDC32(regs->psb.saveCHICKENBIT, DSPCHICKENBIT);
|
||||
|
||||
/* Make sure VGA plane is off. it initializes to on after reset!*/
|
||||
PSB_WVDC32(0x80000000, VGACNTRL);
|
||||
|
||||
/* set the plls */
|
||||
PSB_WVDC32(dev_priv->saveFPA0, MRST_FPA0);
|
||||
PSB_WVDC32(dev_priv->saveFPA1, MRST_FPA1);
|
||||
PSB_WVDC32(regs->psb.saveFPA0, MRST_FPA0);
|
||||
PSB_WVDC32(regs->psb.saveFPA1, MRST_FPA1);
|
||||
|
||||
/* Actually enable it */
|
||||
PSB_WVDC32(dev_priv->saveDPLL_A, MRST_DPLL_A);
|
||||
PSB_WVDC32(regs->psb.saveDPLL_A, MRST_DPLL_A);
|
||||
DRM_UDELAY(150);
|
||||
|
||||
/* Restore mode */
|
||||
PSB_WVDC32(dev_priv->saveHTOTAL_A, HTOTAL_A);
|
||||
PSB_WVDC32(dev_priv->saveHBLANK_A, HBLANK_A);
|
||||
PSB_WVDC32(dev_priv->saveHSYNC_A, HSYNC_A);
|
||||
PSB_WVDC32(dev_priv->saveVTOTAL_A, VTOTAL_A);
|
||||
PSB_WVDC32(dev_priv->saveVBLANK_A, VBLANK_A);
|
||||
PSB_WVDC32(dev_priv->saveVSYNC_A, VSYNC_A);
|
||||
PSB_WVDC32(dev_priv->savePIPEASRC, PIPEASRC);
|
||||
PSB_WVDC32(dev_priv->saveBCLRPAT_A, BCLRPAT_A);
|
||||
PSB_WVDC32(regs->psb.saveHTOTAL_A, HTOTAL_A);
|
||||
PSB_WVDC32(regs->psb.saveHBLANK_A, HBLANK_A);
|
||||
PSB_WVDC32(regs->psb.saveHSYNC_A, HSYNC_A);
|
||||
PSB_WVDC32(regs->psb.saveVTOTAL_A, VTOTAL_A);
|
||||
PSB_WVDC32(regs->psb.saveVBLANK_A, VBLANK_A);
|
||||
PSB_WVDC32(regs->psb.saveVSYNC_A, VSYNC_A);
|
||||
PSB_WVDC32(regs->psb.savePIPEASRC, PIPEASRC);
|
||||
PSB_WVDC32(regs->psb.saveBCLRPAT_A, BCLRPAT_A);
|
||||
|
||||
/* Restore performance mode*/
|
||||
PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE);
|
||||
PSB_WVDC32(regs->psb.savePERF_MODE, MRST_PERF_MODE);
|
||||
|
||||
/* Enable the pipe*/
|
||||
if (dev_priv->iLVDS_enable)
|
||||
PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF);
|
||||
PSB_WVDC32(regs->psb.savePIPEACONF, PIPEACONF);
|
||||
|
||||
/* Set up the plane*/
|
||||
PSB_WVDC32(dev_priv->saveDSPALINOFF, DSPALINOFF);
|
||||
PSB_WVDC32(dev_priv->saveDSPASTRIDE, DSPASTRIDE);
|
||||
PSB_WVDC32(dev_priv->saveDSPATILEOFF, DSPATILEOFF);
|
||||
PSB_WVDC32(regs->psb.saveDSPALINOFF, DSPALINOFF);
|
||||
PSB_WVDC32(regs->psb.saveDSPASTRIDE, DSPASTRIDE);
|
||||
PSB_WVDC32(regs->psb.saveDSPATILEOFF, DSPATILEOFF);
|
||||
|
||||
/* Enable the plane */
|
||||
PSB_WVDC32(dev_priv->saveDSPACNTR, DSPACNTR);
|
||||
PSB_WVDC32(dev_priv->saveDSPASURF, DSPASURF);
|
||||
PSB_WVDC32(regs->psb.saveDSPACNTR, DSPACNTR);
|
||||
PSB_WVDC32(regs->psb.saveDSPASURF, DSPASURF);
|
||||
|
||||
/* Enable Cursor A */
|
||||
PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
|
||||
PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
|
||||
PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
|
||||
PSB_WVDC32(regs->psb.saveDSPACURSOR_CTRL, CURACNTR);
|
||||
PSB_WVDC32(regs->psb.saveDSPACURSOR_POS, CURAPOS);
|
||||
PSB_WVDC32(regs->psb.saveDSPACURSOR_BASE, CURABASE);
|
||||
|
||||
/* Restore palette (gamma) */
|
||||
for (i = 0; i < 256; i++)
|
||||
PSB_WVDC32(dev_priv->save_palette_a[i], PALETTE_A + (i << 2));
|
||||
PSB_WVDC32(regs->psb.save_palette_a[i], PALETTE_A + (i << 2));
|
||||
|
||||
if (dev_priv->hdmi_priv)
|
||||
oaktrail_hdmi_restore(dev);
|
||||
|
||||
if (dev_priv->iLVDS_enable) {
|
||||
PSB_WVDC32(dev_priv->saveBLC_PWM_CTL2, BLC_PWM_CTL2);
|
||||
PSB_WVDC32(dev_priv->saveLVDS, LVDS); /*port 61180h*/
|
||||
PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
|
||||
PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
|
||||
PSB_WVDC32(dev_priv->savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS);
|
||||
PSB_WVDC32(dev_priv->saveBLC_PWM_CTL, BLC_PWM_CTL);
|
||||
PSB_WVDC32(dev_priv->savePP_ON_DELAYS, LVDSPP_ON);
|
||||
PSB_WVDC32(dev_priv->savePP_OFF_DELAYS, LVDSPP_OFF);
|
||||
PSB_WVDC32(dev_priv->savePP_DIVISOR, PP_CYCLE);
|
||||
PSB_WVDC32(dev_priv->savePP_CONTROL, PP_CONTROL);
|
||||
PSB_WVDC32(regs->saveBLC_PWM_CTL2, BLC_PWM_CTL2);
|
||||
PSB_WVDC32(regs->psb.saveLVDS, LVDS); /*port 61180h*/
|
||||
PSB_WVDC32(regs->psb.savePFIT_CONTROL, PFIT_CONTROL);
|
||||
PSB_WVDC32(regs->psb.savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
|
||||
PSB_WVDC32(regs->psb.savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS);
|
||||
PSB_WVDC32(regs->saveBLC_PWM_CTL, BLC_PWM_CTL);
|
||||
PSB_WVDC32(regs->psb.savePP_ON_DELAYS, LVDSPP_ON);
|
||||
PSB_WVDC32(regs->psb.savePP_OFF_DELAYS, LVDSPP_OFF);
|
||||
PSB_WVDC32(regs->psb.savePP_DIVISOR, PP_CYCLE);
|
||||
PSB_WVDC32(regs->psb.savePP_CONTROL, PP_CONTROL);
|
||||
}
|
||||
|
||||
/* Wait for cycle delay */
|
||||
@ -388,20 +386,20 @@ static int oaktrail_restore_display_registers(struct drm_device *dev)
|
||||
} while (pp_stat & 0x10000000);
|
||||
|
||||
/* Restore HW overlay */
|
||||
PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
|
||||
PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
|
||||
PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
|
||||
PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
|
||||
PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
|
||||
PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
|
||||
PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
|
||||
PSB_WVDC32(regs->psb.saveOV_OVADD, OV_OVADD);
|
||||
PSB_WVDC32(regs->psb.saveOV_OGAMC0, OV_OGAMC0);
|
||||
PSB_WVDC32(regs->psb.saveOV_OGAMC1, OV_OGAMC1);
|
||||
PSB_WVDC32(regs->psb.saveOV_OGAMC2, OV_OGAMC2);
|
||||
PSB_WVDC32(regs->psb.saveOV_OGAMC3, OV_OGAMC3);
|
||||
PSB_WVDC32(regs->psb.saveOV_OGAMC4, OV_OGAMC4);
|
||||
PSB_WVDC32(regs->psb.saveOV_OGAMC5, OV_OGAMC5);
|
||||
|
||||
/* DPST registers */
|
||||
PSB_WVDC32(dev_priv->saveHISTOGRAM_INT_CONTROL_REG,
|
||||
PSB_WVDC32(regs->psb.saveHISTOGRAM_INT_CONTROL_REG,
|
||||
HISTOGRAM_INT_CONTROL);
|
||||
PSB_WVDC32(dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG,
|
||||
PSB_WVDC32(regs->psb.saveHISTOGRAM_LOGIC_CONTROL_REG,
|
||||
HISTOGRAM_LOGIC_CONTROL);
|
||||
PSB_WVDC32(dev_priv->savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC);
|
||||
PSB_WVDC32(regs->psb.savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -502,7 +500,6 @@ const struct psb_ops oaktrail_chip_ops = {
|
||||
.backlight_init = oaktrail_backlight_init,
|
||||
#endif
|
||||
|
||||
.init_pm = oaktrail_init_pm,
|
||||
.save_regs = oaktrail_save_display_registers,
|
||||
.restore_regs = oaktrail_restore_display_registers,
|
||||
.power_down = oaktrail_power_down,
|
||||
|
@ -125,59 +125,6 @@ static const struct oaktrail_hdmi_limit oaktrail_hdmi_limit = {
|
||||
.nf = { .min = NF_MIN, .max = NF_MAX },
|
||||
};
|
||||
|
||||
static void wait_for_vblank(struct drm_device *dev)
|
||||
{
|
||||
/* FIXME: Can we do this as a sleep ? */
|
||||
/* Wait for 20ms, i.e. one cycle at 50hz. */
|
||||
mdelay(20);
|
||||
}
|
||||
|
||||
static void scu_busy_loop(void *scu_base)
|
||||
{
|
||||
u32 status = 0;
|
||||
u32 loop_count = 0;
|
||||
|
||||
status = readl(scu_base + 0x04);
|
||||
while (status & 1) {
|
||||
udelay(1); /* scu processing time is in few u secods */
|
||||
status = readl(scu_base + 0x04);
|
||||
loop_count++;
|
||||
/* break if scu doesn't reset busy bit after huge retry */
|
||||
if (loop_count > 1000) {
|
||||
DRM_DEBUG_KMS("SCU IPC timed out");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void oaktrail_hdmi_reset(struct drm_device *dev)
|
||||
{
|
||||
void *base;
|
||||
/* FIXME: at least make these defines */
|
||||
unsigned int scu_ipc_mmio = 0xff11c000;
|
||||
int scu_len = 1024;
|
||||
|
||||
base = ioremap((resource_size_t)scu_ipc_mmio, scu_len);
|
||||
if (base == NULL) {
|
||||
DRM_ERROR("failed to map SCU mmio\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* scu ipc: assert hdmi controller reset */
|
||||
writel(0xff11d118, base + 0x0c);
|
||||
writel(0x7fffffdf, base + 0x80);
|
||||
writel(0x42005, base + 0x0);
|
||||
scu_busy_loop(base);
|
||||
|
||||
/* scu ipc: de-assert hdmi controller reset */
|
||||
writel(0xff11d118, base + 0x0c);
|
||||
writel(0x7fffffff, base + 0x80);
|
||||
writel(0x42005, base + 0x0);
|
||||
scu_busy_loop(base);
|
||||
|
||||
iounmap(base);
|
||||
}
|
||||
|
||||
static void oaktrail_hdmi_audio_enable(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
@ -208,104 +155,6 @@ static void oaktrail_hdmi_audio_disable(struct drm_device *dev)
|
||||
HDMI_READ(HDMI_HCR);
|
||||
}
|
||||
|
||||
void oaktrail_crtc_hdmi_dpms(struct drm_crtc *crtc, int mode)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
u32 temp;
|
||||
|
||||
switch (mode) {
|
||||
case DRM_MODE_DPMS_OFF:
|
||||
/* Disable VGACNTRL */
|
||||
REG_WRITE(VGACNTRL, 0x80000000);
|
||||
|
||||
/* Disable plane */
|
||||
temp = REG_READ(DSPBCNTR);
|
||||
if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
|
||||
REG_WRITE(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
|
||||
REG_READ(DSPBCNTR);
|
||||
/* Flush the plane changes */
|
||||
REG_WRITE(DSPBSURF, REG_READ(DSPBSURF));
|
||||
REG_READ(DSPBSURF);
|
||||
}
|
||||
|
||||
/* Disable pipe B */
|
||||
temp = REG_READ(PIPEBCONF);
|
||||
if ((temp & PIPEACONF_ENABLE) != 0) {
|
||||
REG_WRITE(PIPEBCONF, temp & ~PIPEACONF_ENABLE);
|
||||
REG_READ(PIPEBCONF);
|
||||
}
|
||||
|
||||
/* Disable LNW Pipes, etc */
|
||||
temp = REG_READ(PCH_PIPEBCONF);
|
||||
if ((temp & PIPEACONF_ENABLE) != 0) {
|
||||
REG_WRITE(PCH_PIPEBCONF, temp & ~PIPEACONF_ENABLE);
|
||||
REG_READ(PCH_PIPEBCONF);
|
||||
}
|
||||
/* wait for pipe off */
|
||||
udelay(150);
|
||||
/* Disable dpll */
|
||||
temp = REG_READ(DPLL_CTRL);
|
||||
if ((temp & DPLL_PWRDN) == 0) {
|
||||
REG_WRITE(DPLL_CTRL, temp | (DPLL_PWRDN | DPLL_RESET));
|
||||
REG_WRITE(DPLL_STATUS, 0x1);
|
||||
}
|
||||
/* wait for dpll off */
|
||||
udelay(150);
|
||||
break;
|
||||
case DRM_MODE_DPMS_ON:
|
||||
case DRM_MODE_DPMS_STANDBY:
|
||||
case DRM_MODE_DPMS_SUSPEND:
|
||||
/* Enable dpll */
|
||||
temp = REG_READ(DPLL_CTRL);
|
||||
if ((temp & DPLL_PWRDN) != 0) {
|
||||
REG_WRITE(DPLL_CTRL, temp & ~(DPLL_PWRDN | DPLL_RESET));
|
||||
temp = REG_READ(DPLL_CLK_ENABLE);
|
||||
REG_WRITE(DPLL_CLK_ENABLE, temp | DPLL_EN_DISP | DPLL_SEL_HDMI | DPLL_EN_HDMI);
|
||||
REG_READ(DPLL_CLK_ENABLE);
|
||||
}
|
||||
/* wait for dpll warm up */
|
||||
udelay(150);
|
||||
|
||||
/* Enable pipe B */
|
||||
temp = REG_READ(PIPEBCONF);
|
||||
if ((temp & PIPEACONF_ENABLE) == 0) {
|
||||
REG_WRITE(PIPEBCONF, temp | PIPEACONF_ENABLE);
|
||||
REG_READ(PIPEBCONF);
|
||||
}
|
||||
|
||||
/* Enable LNW Pipe B */
|
||||
temp = REG_READ(PCH_PIPEBCONF);
|
||||
if ((temp & PIPEACONF_ENABLE) == 0) {
|
||||
REG_WRITE(PCH_PIPEBCONF, temp | PIPEACONF_ENABLE);
|
||||
REG_READ(PCH_PIPEBCONF);
|
||||
}
|
||||
wait_for_vblank(dev);
|
||||
|
||||
/* Enable plane */
|
||||
temp = REG_READ(DSPBCNTR);
|
||||
if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
|
||||
REG_WRITE(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE);
|
||||
/* Flush the plane changes */
|
||||
REG_WRITE(DSPBSURF, REG_READ(DSPBSURF));
|
||||
REG_READ(DSPBSURF);
|
||||
}
|
||||
psb_intel_crtc_load_lut(crtc);
|
||||
}
|
||||
/* DSPARB */
|
||||
REG_WRITE(DSPARB, 0x00003fbf);
|
||||
/* FW1 */
|
||||
REG_WRITE(0x70034, 0x3f880a0a);
|
||||
/* FW2 */
|
||||
REG_WRITE(0x70038, 0x0b060808);
|
||||
/* FW4 */
|
||||
REG_WRITE(0x70050, 0x08030404);
|
||||
/* FW5 */
|
||||
REG_WRITE(0x70054, 0x04040404);
|
||||
/* LNC Chicken Bits */
|
||||
REG_WRITE(0x70400, 0x4000);
|
||||
}
|
||||
|
||||
|
||||
static void oaktrail_hdmi_dpms(struct drm_encoder *encoder, int mode)
|
||||
{
|
||||
static int dpms_mode = -1;
|
||||
@ -327,182 +176,6 @@ static void oaktrail_hdmi_dpms(struct drm_encoder *encoder, int mode)
|
||||
HDMI_WRITE(HDMI_VIDEO_REG, temp);
|
||||
}
|
||||
|
||||
static unsigned int htotal_calculate(struct drm_display_mode *mode)
|
||||
{
|
||||
u32 htotal, new_crtc_htotal;
|
||||
|
||||
htotal = (mode->crtc_hdisplay - 1) | ((mode->crtc_htotal - 1) << 16);
|
||||
|
||||
/*
|
||||
* 1024 x 768 new_crtc_htotal = 0x1024;
|
||||
* 1280 x 1024 new_crtc_htotal = 0x0c34;
|
||||
*/
|
||||
new_crtc_htotal = (mode->crtc_htotal - 1) * 200 * 1000 / mode->clock;
|
||||
|
||||
return (mode->crtc_hdisplay - 1) | (new_crtc_htotal << 16);
|
||||
}
|
||||
|
||||
static void oaktrail_hdmi_find_dpll(struct drm_crtc *crtc, int target,
|
||||
int refclk, struct oaktrail_hdmi_clock *best_clock)
|
||||
{
|
||||
int np_min, np_max, nr_min, nr_max;
|
||||
int np, nr, nf;
|
||||
|
||||
np_min = DIV_ROUND_UP(oaktrail_hdmi_limit.vco.min, target * 10);
|
||||
np_max = oaktrail_hdmi_limit.vco.max / (target * 10);
|
||||
if (np_min < oaktrail_hdmi_limit.np.min)
|
||||
np_min = oaktrail_hdmi_limit.np.min;
|
||||
if (np_max > oaktrail_hdmi_limit.np.max)
|
||||
np_max = oaktrail_hdmi_limit.np.max;
|
||||
|
||||
nr_min = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_max));
|
||||
nr_max = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_min));
|
||||
if (nr_min < oaktrail_hdmi_limit.nr.min)
|
||||
nr_min = oaktrail_hdmi_limit.nr.min;
|
||||
if (nr_max > oaktrail_hdmi_limit.nr.max)
|
||||
nr_max = oaktrail_hdmi_limit.nr.max;
|
||||
|
||||
np = DIV_ROUND_UP((refclk * 1000), (target * 10 * nr_max));
|
||||
nr = DIV_ROUND_UP((refclk * 1000), (target * 10 * np));
|
||||
nf = DIV_ROUND_CLOSEST((target * 10 * np * nr), refclk);
|
||||
DRM_DEBUG_KMS("np, nr, nf %d %d %d\n", np, nr, nf);
|
||||
|
||||
/*
|
||||
* 1024 x 768 np = 1; nr = 0x26; nf = 0x0fd8000;
|
||||
* 1280 x 1024 np = 1; nr = 0x17; nf = 0x1034000;
|
||||
*/
|
||||
best_clock->np = np;
|
||||
best_clock->nr = nr - 1;
|
||||
best_clock->nf = (nf << 14);
|
||||
}
|
||||
|
||||
int oaktrail_crtc_hdmi_mode_set(struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode,
|
||||
int x, int y,
|
||||
struct drm_framebuffer *old_fb)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
|
||||
int pipe = 1;
|
||||
int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
|
||||
int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
|
||||
int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
|
||||
int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
|
||||
int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
|
||||
int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
|
||||
int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
|
||||
int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
|
||||
int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
|
||||
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
|
||||
int refclk;
|
||||
struct oaktrail_hdmi_clock clock;
|
||||
u32 dspcntr, pipeconf, dpll, temp;
|
||||
int dspcntr_reg = DSPBCNTR;
|
||||
|
||||
/* Disable the VGA plane that we never use */
|
||||
REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
|
||||
|
||||
/* XXX: Disable the panel fitter if it was on our pipe */
|
||||
|
||||
/* Disable dpll if necessary */
|
||||
dpll = REG_READ(DPLL_CTRL);
|
||||
if ((dpll & DPLL_PWRDN) == 0) {
|
||||
REG_WRITE(DPLL_CTRL, dpll | (DPLL_PWRDN | DPLL_RESET));
|
||||
REG_WRITE(DPLL_DIV_CTRL, 0x00000000);
|
||||
REG_WRITE(DPLL_STATUS, 0x1);
|
||||
}
|
||||
udelay(150);
|
||||
|
||||
/* reset controller: FIXME - can we sort out the ioremap mess ? */
|
||||
iounmap(hdmi_dev->regs);
|
||||
oaktrail_hdmi_reset(dev);
|
||||
|
||||
/* program and enable dpll */
|
||||
refclk = 25000;
|
||||
oaktrail_hdmi_find_dpll(crtc, adjusted_mode->clock, refclk, &clock);
|
||||
|
||||
/* Setting DPLL */
|
||||
dpll = REG_READ(DPLL_CTRL);
|
||||
dpll &= ~DPLL_PDIV_MASK;
|
||||
dpll &= ~(DPLL_PWRDN | DPLL_RESET);
|
||||
REG_WRITE(DPLL_CTRL, 0x00000008);
|
||||
REG_WRITE(DPLL_DIV_CTRL, ((clock.nf << 6) | clock.nr));
|
||||
REG_WRITE(DPLL_ADJUST, ((clock.nf >> 14) - 1));
|
||||
REG_WRITE(DPLL_CTRL, (dpll | (clock.np << DPLL_PDIV_SHIFT) | DPLL_ENSTAT | DPLL_DITHEN));
|
||||
REG_WRITE(DPLL_UPDATE, 0x80000000);
|
||||
REG_WRITE(DPLL_CLK_ENABLE, 0x80050102);
|
||||
udelay(150);
|
||||
|
||||
hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len);
|
||||
if (hdmi_dev->regs == NULL) {
|
||||
DRM_ERROR("failed to do hdmi mmio mapping\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* configure HDMI */
|
||||
HDMI_WRITE(0x1004, 0x1fd);
|
||||
HDMI_WRITE(0x2000, 0x1);
|
||||
HDMI_WRITE(0x2008, 0x0);
|
||||
HDMI_WRITE(0x3130, 0x8);
|
||||
HDMI_WRITE(0x101c, 0x1800810);
|
||||
|
||||
temp = htotal_calculate(adjusted_mode);
|
||||
REG_WRITE(htot_reg, temp);
|
||||
REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16));
|
||||
REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16));
|
||||
REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16));
|
||||
REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16));
|
||||
REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16));
|
||||
REG_WRITE(pipesrc_reg,
|
||||
((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
|
||||
|
||||
REG_WRITE(PCH_HTOTAL_B, (adjusted_mode->crtc_hdisplay - 1) | ((adjusted_mode->crtc_htotal - 1) << 16));
|
||||
REG_WRITE(PCH_HBLANK_B, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16));
|
||||
REG_WRITE(PCH_HSYNC_B, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16));
|
||||
REG_WRITE(PCH_VTOTAL_B, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16));
|
||||
REG_WRITE(PCH_VBLANK_B, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16));
|
||||
REG_WRITE(PCH_VSYNC_B, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16));
|
||||
REG_WRITE(PCH_PIPEBSRC,
|
||||
((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
|
||||
|
||||
temp = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start;
|
||||
HDMI_WRITE(HDMI_HBLANK_A, ((adjusted_mode->crtc_hdisplay - 1) << 16) | temp);
|
||||
|
||||
REG_WRITE(dspsize_reg,
|
||||
((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
|
||||
REG_WRITE(dsppos_reg, 0);
|
||||
|
||||
/* Flush the plane changes */
|
||||
{
|
||||
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
||||
crtc_funcs->mode_set_base(crtc, x, y, old_fb);
|
||||
}
|
||||
|
||||
/* Set up the display plane register */
|
||||
dspcntr = REG_READ(dspcntr_reg);
|
||||
dspcntr |= DISPPLANE_GAMMA_ENABLE;
|
||||
dspcntr |= DISPPLANE_SEL_PIPE_B;
|
||||
dspcntr |= DISPLAY_PLANE_ENABLE;
|
||||
|
||||
/* setup pipeconf */
|
||||
pipeconf = REG_READ(pipeconf_reg);
|
||||
pipeconf |= PIPEACONF_ENABLE;
|
||||
|
||||
REG_WRITE(pipeconf_reg, pipeconf);
|
||||
REG_READ(pipeconf_reg);
|
||||
|
||||
REG_WRITE(PCH_PIPEBCONF, pipeconf);
|
||||
REG_READ(PCH_PIPEBCONF);
|
||||
wait_for_vblank(dev);
|
||||
|
||||
REG_WRITE(dspcntr_reg, dspcntr);
|
||||
wait_for_vblank(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int oaktrail_hdmi_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
@ -692,7 +365,7 @@ failed_connector:
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) },
|
||||
{}
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
void oaktrail_hdmi_setup(struct drm_device *dev)
|
||||
@ -766,6 +439,7 @@ void oaktrail_hdmi_save(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
|
||||
struct psb_state *regs = &dev_priv->regs.psb;
|
||||
int i;
|
||||
|
||||
/* dpll */
|
||||
@ -776,14 +450,14 @@ void oaktrail_hdmi_save(struct drm_device *dev)
|
||||
hdmi_dev->saveDPLL_CLK_ENABLE = PSB_RVDC32(DPLL_CLK_ENABLE);
|
||||
|
||||
/* pipe B */
|
||||
dev_priv->savePIPEBCONF = PSB_RVDC32(PIPEBCONF);
|
||||
dev_priv->savePIPEBSRC = PSB_RVDC32(PIPEBSRC);
|
||||
dev_priv->saveHTOTAL_B = PSB_RVDC32(HTOTAL_B);
|
||||
dev_priv->saveHBLANK_B = PSB_RVDC32(HBLANK_B);
|
||||
dev_priv->saveHSYNC_B = PSB_RVDC32(HSYNC_B);
|
||||
dev_priv->saveVTOTAL_B = PSB_RVDC32(VTOTAL_B);
|
||||
dev_priv->saveVBLANK_B = PSB_RVDC32(VBLANK_B);
|
||||
dev_priv->saveVSYNC_B = PSB_RVDC32(VSYNC_B);
|
||||
regs->savePIPEBCONF = PSB_RVDC32(PIPEBCONF);
|
||||
regs->savePIPEBSRC = PSB_RVDC32(PIPEBSRC);
|
||||
regs->saveHTOTAL_B = PSB_RVDC32(HTOTAL_B);
|
||||
regs->saveHBLANK_B = PSB_RVDC32(HBLANK_B);
|
||||
regs->saveHSYNC_B = PSB_RVDC32(HSYNC_B);
|
||||
regs->saveVTOTAL_B = PSB_RVDC32(VTOTAL_B);
|
||||
regs->saveVBLANK_B = PSB_RVDC32(VBLANK_B);
|
||||
regs->saveVSYNC_B = PSB_RVDC32(VSYNC_B);
|
||||
|
||||
hdmi_dev->savePCH_PIPEBCONF = PSB_RVDC32(PCH_PIPEBCONF);
|
||||
hdmi_dev->savePCH_PIPEBSRC = PSB_RVDC32(PCH_PIPEBSRC);
|
||||
@ -795,21 +469,21 @@ void oaktrail_hdmi_save(struct drm_device *dev)
|
||||
hdmi_dev->savePCH_VSYNC_B = PSB_RVDC32(PCH_VSYNC_B);
|
||||
|
||||
/* plane */
|
||||
dev_priv->saveDSPBCNTR = PSB_RVDC32(DSPBCNTR);
|
||||
dev_priv->saveDSPBSTRIDE = PSB_RVDC32(DSPBSTRIDE);
|
||||
dev_priv->saveDSPBADDR = PSB_RVDC32(DSPBBASE);
|
||||
dev_priv->saveDSPBSURF = PSB_RVDC32(DSPBSURF);
|
||||
dev_priv->saveDSPBLINOFF = PSB_RVDC32(DSPBLINOFF);
|
||||
dev_priv->saveDSPBTILEOFF = PSB_RVDC32(DSPBTILEOFF);
|
||||
regs->saveDSPBCNTR = PSB_RVDC32(DSPBCNTR);
|
||||
regs->saveDSPBSTRIDE = PSB_RVDC32(DSPBSTRIDE);
|
||||
regs->saveDSPBADDR = PSB_RVDC32(DSPBBASE);
|
||||
regs->saveDSPBSURF = PSB_RVDC32(DSPBSURF);
|
||||
regs->saveDSPBLINOFF = PSB_RVDC32(DSPBLINOFF);
|
||||
regs->saveDSPBTILEOFF = PSB_RVDC32(DSPBTILEOFF);
|
||||
|
||||
/* cursor B */
|
||||
dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
|
||||
dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
|
||||
dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
|
||||
regs->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
|
||||
regs->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
|
||||
regs->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
|
||||
|
||||
/* save palette */
|
||||
for (i = 0; i < 256; i++)
|
||||
dev_priv->save_palette_b[i] = PSB_RVDC32(PALETTE_B + (i << 2));
|
||||
regs->save_palette_b[i] = PSB_RVDC32(PALETTE_B + (i << 2));
|
||||
}
|
||||
|
||||
/* restore HDMI register state */
|
||||
@ -817,6 +491,7 @@ void oaktrail_hdmi_restore(struct drm_device *dev)
|
||||
{
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
|
||||
struct psb_state *regs = &dev_priv->regs.psb;
|
||||
int i;
|
||||
|
||||
/* dpll */
|
||||
@ -828,13 +503,13 @@ void oaktrail_hdmi_restore(struct drm_device *dev)
|
||||
DRM_UDELAY(150);
|
||||
|
||||
/* pipe */
|
||||
PSB_WVDC32(dev_priv->savePIPEBSRC, PIPEBSRC);
|
||||
PSB_WVDC32(dev_priv->saveHTOTAL_B, HTOTAL_B);
|
||||
PSB_WVDC32(dev_priv->saveHBLANK_B, HBLANK_B);
|
||||
PSB_WVDC32(dev_priv->saveHSYNC_B, HSYNC_B);
|
||||
PSB_WVDC32(dev_priv->saveVTOTAL_B, VTOTAL_B);
|
||||
PSB_WVDC32(dev_priv->saveVBLANK_B, VBLANK_B);
|
||||
PSB_WVDC32(dev_priv->saveVSYNC_B, VSYNC_B);
|
||||
PSB_WVDC32(regs->savePIPEBSRC, PIPEBSRC);
|
||||
PSB_WVDC32(regs->saveHTOTAL_B, HTOTAL_B);
|
||||
PSB_WVDC32(regs->saveHBLANK_B, HBLANK_B);
|
||||
PSB_WVDC32(regs->saveHSYNC_B, HSYNC_B);
|
||||
PSB_WVDC32(regs->saveVTOTAL_B, VTOTAL_B);
|
||||
PSB_WVDC32(regs->saveVBLANK_B, VBLANK_B);
|
||||
PSB_WVDC32(regs->saveVSYNC_B, VSYNC_B);
|
||||
|
||||
PSB_WVDC32(hdmi_dev->savePCH_PIPEBSRC, PCH_PIPEBSRC);
|
||||
PSB_WVDC32(hdmi_dev->savePCH_HTOTAL_B, PCH_HTOTAL_B);
|
||||
@ -844,22 +519,22 @@ void oaktrail_hdmi_restore(struct drm_device *dev)
|
||||
PSB_WVDC32(hdmi_dev->savePCH_VBLANK_B, PCH_VBLANK_B);
|
||||
PSB_WVDC32(hdmi_dev->savePCH_VSYNC_B, PCH_VSYNC_B);
|
||||
|
||||
PSB_WVDC32(dev_priv->savePIPEBCONF, PIPEBCONF);
|
||||
PSB_WVDC32(regs->savePIPEBCONF, PIPEBCONF);
|
||||
PSB_WVDC32(hdmi_dev->savePCH_PIPEBCONF, PCH_PIPEBCONF);
|
||||
|
||||
/* plane */
|
||||
PSB_WVDC32(dev_priv->saveDSPBLINOFF, DSPBLINOFF);
|
||||
PSB_WVDC32(dev_priv->saveDSPBSTRIDE, DSPBSTRIDE);
|
||||
PSB_WVDC32(dev_priv->saveDSPBTILEOFF, DSPBTILEOFF);
|
||||
PSB_WVDC32(dev_priv->saveDSPBCNTR, DSPBCNTR);
|
||||
PSB_WVDC32(dev_priv->saveDSPBSURF, DSPBSURF);
|
||||
PSB_WVDC32(regs->saveDSPBLINOFF, DSPBLINOFF);
|
||||
PSB_WVDC32(regs->saveDSPBSTRIDE, DSPBSTRIDE);
|
||||
PSB_WVDC32(regs->saveDSPBTILEOFF, DSPBTILEOFF);
|
||||
PSB_WVDC32(regs->saveDSPBCNTR, DSPBCNTR);
|
||||
PSB_WVDC32(regs->saveDSPBSURF, DSPBSURF);
|
||||
|
||||
/* cursor B */
|
||||
PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
|
||||
PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
|
||||
PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
|
||||
PSB_WVDC32(regs->saveDSPBCURSOR_CTRL, CURBCNTR);
|
||||
PSB_WVDC32(regs->saveDSPBCURSOR_POS, CURBPOS);
|
||||
PSB_WVDC32(regs->saveDSPBCURSOR_BASE, CURBBASE);
|
||||
|
||||
/* restore palette */
|
||||
for (i = 0; i < 256; i++)
|
||||
PSB_WVDC32(dev_priv->save_palette_b[i], PALETTE_B + (i << 2));
|
||||
PSB_WVDC32(regs->save_palette_b[i], PALETTE_B + (i << 2));
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ static int oaktrail_hdmi_i2c_access(struct i2c_adapter *adap,
|
||||
{
|
||||
struct oaktrail_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
|
||||
struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
|
||||
int i, err = 0;
|
||||
int i;
|
||||
|
||||
mutex_lock(&i2c_dev->i2c_lock);
|
||||
|
||||
@ -139,9 +139,9 @@ static int oaktrail_hdmi_i2c_access(struct i2c_adapter *adap,
|
||||
for (i = 0; i < num; i++) {
|
||||
if (pmsg->len && pmsg->buf) {
|
||||
if (pmsg->flags & I2C_M_RD)
|
||||
err = xfer_read(adap, pmsg);
|
||||
xfer_read(adap, pmsg);
|
||||
else
|
||||
err = xfer_write(adap, pmsg);
|
||||
xfer_write(adap, pmsg);
|
||||
}
|
||||
pmsg++; /* next message */
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ static u32 oaktrail_lvds_get_max_backlight(struct drm_device *dev)
|
||||
|
||||
gma_power_end(dev);
|
||||
} else
|
||||
ret = ((dev_priv->saveBLC_PWM_CTL &
|
||||
ret = ((dev_priv->regs.saveBLC_PWM_CTL &
|
||||
BACKLIGHT_MODULATION_FREQ_MASK) >>
|
||||
BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
|
||||
|
||||
@ -331,7 +331,6 @@ void oaktrail_lvds_init(struct drm_device *dev,
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct edid *edid;
|
||||
int ret = 0;
|
||||
struct i2c_adapter *i2c_adap;
|
||||
struct drm_display_mode *scan; /* *modes, *bios_mode; */
|
||||
|
||||
@ -400,7 +399,7 @@ void oaktrail_lvds_init(struct drm_device *dev,
|
||||
if (edid) {
|
||||
drm_mode_connector_update_edid_property(connector,
|
||||
edid);
|
||||
ret = drm_add_edid_modes(connector, edid);
|
||||
drm_add_edid_modes(connector, edid);
|
||||
kfree(edid);
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,8 @@ void gma_power_init(struct drm_device *dev)
|
||||
spin_lock_init(&power_ctrl_lock);
|
||||
mutex_init(&power_mutex);
|
||||
|
||||
dev_priv->ops->init_pm(dev);
|
||||
if (dev_priv->ops->init_pm)
|
||||
dev_priv->ops->init_pm(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -132,9 +133,9 @@ static void gma_suspend_pci(struct pci_dev *pdev)
|
||||
|
||||
pci_save_state(pdev);
|
||||
pci_read_config_dword(pdev, 0x5C, &bsm);
|
||||
dev_priv->saveBSM = bsm;
|
||||
dev_priv->regs.saveBSM = bsm;
|
||||
pci_read_config_dword(pdev, 0xFC, &vbt);
|
||||
dev_priv->saveVBT = vbt;
|
||||
dev_priv->regs.saveVBT = vbt;
|
||||
pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr);
|
||||
pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data);
|
||||
|
||||
@ -162,8 +163,8 @@ static bool gma_resume_pci(struct pci_dev *pdev)
|
||||
|
||||
pci_set_power_state(pdev, PCI_D0);
|
||||
pci_restore_state(pdev);
|
||||
pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM);
|
||||
pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT);
|
||||
pci_write_config_dword(pdev, 0x5c, dev_priv->regs.saveBSM);
|
||||
pci_write_config_dword(pdev, 0xFC, dev_priv->regs.saveVBT);
|
||||
/* restoring MSI address and data in PCIx space */
|
||||
pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr);
|
||||
pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data);
|
||||
|
@ -177,16 +177,17 @@ static int psb_save_display_registers(struct drm_device *dev)
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_connector *connector;
|
||||
struct psb_state *regs = &dev_priv->regs.psb;
|
||||
|
||||
/* Display arbitration control + watermarks */
|
||||
dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
|
||||
dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
|
||||
dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
|
||||
dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
|
||||
dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
|
||||
dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
|
||||
dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
|
||||
dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
|
||||
regs->saveDSPARB = PSB_RVDC32(DSPARB);
|
||||
regs->saveDSPFW1 = PSB_RVDC32(DSPFW1);
|
||||
regs->saveDSPFW2 = PSB_RVDC32(DSPFW2);
|
||||
regs->saveDSPFW3 = PSB_RVDC32(DSPFW3);
|
||||
regs->saveDSPFW4 = PSB_RVDC32(DSPFW4);
|
||||
regs->saveDSPFW5 = PSB_RVDC32(DSPFW5);
|
||||
regs->saveDSPFW6 = PSB_RVDC32(DSPFW6);
|
||||
regs->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
|
||||
|
||||
/* Save crtc and output state */
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
@ -213,16 +214,17 @@ static int psb_restore_display_registers(struct drm_device *dev)
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_connector *connector;
|
||||
struct psb_state *regs = &dev_priv->regs.psb;
|
||||
|
||||
/* Display arbitration + watermarks */
|
||||
PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
|
||||
PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
|
||||
PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
|
||||
PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
|
||||
PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
|
||||
PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
|
||||
PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
|
||||
PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
|
||||
PSB_WVDC32(regs->saveDSPARB, DSPARB);
|
||||
PSB_WVDC32(regs->saveDSPFW1, DSPFW1);
|
||||
PSB_WVDC32(regs->saveDSPFW2, DSPFW2);
|
||||
PSB_WVDC32(regs->saveDSPFW3, DSPFW3);
|
||||
PSB_WVDC32(regs->saveDSPFW4, DSPFW4);
|
||||
PSB_WVDC32(regs->saveDSPFW5, DSPFW5);
|
||||
PSB_WVDC32(regs->saveDSPFW6, DSPFW6);
|
||||
PSB_WVDC32(regs->saveCHICKENBIT, DSPCHICKENBIT);
|
||||
|
||||
/*make sure VGA plane is off. it initializes to on after reset!*/
|
||||
PSB_WVDC32(0x80000000, VGACNTRL);
|
||||
|
@ -60,6 +60,16 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
|
||||
/* Atom E620 */
|
||||
{ 0x8086, 0x4108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
|
||||
#endif
|
||||
#if defined(CONFIG_DRM_MEDFIELD)
|
||||
{0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
|
||||
{0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
|
||||
{0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
|
||||
{0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
|
||||
{0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
|
||||
{0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
|
||||
{0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
|
||||
{0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
|
||||
#endif
|
||||
#if defined(CONFIG_DRM_GMA3600)
|
||||
{ 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
|
||||
{ 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
|
||||
@ -70,7 +80,7 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
|
||||
{ 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
|
||||
{ 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
|
||||
#endif
|
||||
{ 0, 0, 0}
|
||||
{ 0, }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, pciidlist);
|
||||
|
||||
@ -78,27 +88,27 @@ MODULE_DEVICE_TABLE(pci, pciidlist);
|
||||
* Standard IOCTLs.
|
||||
*/
|
||||
|
||||
#define DRM_IOCTL_PSB_ADB \
|
||||
#define DRM_IOCTL_GMA_ADB \
|
||||
DRM_IOWR(DRM_GMA_ADB + DRM_COMMAND_BASE, uint32_t)
|
||||
#define DRM_IOCTL_PSB_MODE_OPERATION \
|
||||
#define DRM_IOCTL_GMA_MODE_OPERATION \
|
||||
DRM_IOWR(DRM_GMA_MODE_OPERATION + DRM_COMMAND_BASE, \
|
||||
struct drm_psb_mode_operation_arg)
|
||||
#define DRM_IOCTL_PSB_STOLEN_MEMORY \
|
||||
#define DRM_IOCTL_GMA_STOLEN_MEMORY \
|
||||
DRM_IOWR(DRM_GMA_STOLEN_MEMORY + DRM_COMMAND_BASE, \
|
||||
struct drm_psb_stolen_memory_arg)
|
||||
#define DRM_IOCTL_PSB_GAMMA \
|
||||
#define DRM_IOCTL_GMA_GAMMA \
|
||||
DRM_IOWR(DRM_GMA_GAMMA + DRM_COMMAND_BASE, \
|
||||
struct drm_psb_dpst_lut_arg)
|
||||
#define DRM_IOCTL_PSB_DPST_BL \
|
||||
#define DRM_IOCTL_GMA_DPST_BL \
|
||||
DRM_IOWR(DRM_GMA_DPST_BL + DRM_COMMAND_BASE, \
|
||||
uint32_t)
|
||||
#define DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID \
|
||||
#define DRM_IOCTL_GMA_GET_PIPE_FROM_CRTC_ID \
|
||||
DRM_IOWR(DRM_GMA_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \
|
||||
struct drm_psb_get_pipe_from_crtc_id_arg)
|
||||
#define DRM_IOCTL_PSB_GEM_CREATE \
|
||||
#define DRM_IOCTL_GMA_GEM_CREATE \
|
||||
DRM_IOWR(DRM_GMA_GEM_CREATE + DRM_COMMAND_BASE, \
|
||||
struct drm_psb_gem_create)
|
||||
#define DRM_IOCTL_PSB_GEM_MMAP \
|
||||
#define DRM_IOCTL_GMA_GEM_MMAP \
|
||||
DRM_IOWR(DRM_GMA_GEM_MMAP + DRM_COMMAND_BASE, \
|
||||
struct drm_psb_gem_mmap)
|
||||
|
||||
@ -113,22 +123,19 @@ static int psb_gamma_ioctl(struct drm_device *dev, void *data,
|
||||
static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
|
||||
#define PSB_IOCTL_DEF(ioctl, func, flags) \
|
||||
[DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func}
|
||||
|
||||
static struct drm_ioctl_desc psb_ioctls[] = {
|
||||
PSB_IOCTL_DEF(DRM_IOCTL_PSB_ADB, psb_adb_ioctl, DRM_AUTH),
|
||||
PSB_IOCTL_DEF(DRM_IOCTL_PSB_MODE_OPERATION, psb_mode_operation_ioctl,
|
||||
DRM_IOCTL_DEF_DRV(GMA_ADB, psb_adb_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF_DRV(GMA_MODE_OPERATION, psb_mode_operation_ioctl,
|
||||
DRM_AUTH),
|
||||
PSB_IOCTL_DEF(DRM_IOCTL_PSB_STOLEN_MEMORY, psb_stolen_memory_ioctl,
|
||||
DRM_IOCTL_DEF_DRV(GMA_STOLEN_MEMORY, psb_stolen_memory_ioctl,
|
||||
DRM_AUTH),
|
||||
PSB_IOCTL_DEF(DRM_IOCTL_PSB_GAMMA, psb_gamma_ioctl, DRM_AUTH),
|
||||
PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH),
|
||||
PSB_IOCTL_DEF(DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID,
|
||||
DRM_IOCTL_DEF_DRV(GMA_GAMMA, psb_gamma_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF_DRV(GMA_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH),
|
||||
DRM_IOCTL_DEF_DRV(GMA_GET_PIPE_FROM_CRTC_ID,
|
||||
psb_intel_get_pipe_from_crtc_id, 0),
|
||||
PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_CREATE, psb_gem_create_ioctl,
|
||||
DRM_IOCTL_DEF_DRV(GMA_GEM_CREATE, psb_gem_create_ioctl,
|
||||
DRM_UNLOCKED | DRM_AUTH),
|
||||
PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_MMAP, psb_gem_mmap_ioctl,
|
||||
DRM_IOCTL_DEF_DRV(GMA_GEM_MMAP, psb_gem_mmap_ioctl,
|
||||
DRM_UNLOCKED | DRM_AUTH),
|
||||
};
|
||||
|
||||
@ -268,10 +275,8 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
|
||||
{
|
||||
struct drm_psb_private *dev_priv;
|
||||
unsigned long resource_start;
|
||||
struct psb_gtt *pg;
|
||||
unsigned long irqflags;
|
||||
int ret = -ENOMEM;
|
||||
uint32_t tt_pages;
|
||||
struct drm_connector *connector;
|
||||
struct psb_intel_encoder *psb_intel_encoder;
|
||||
|
||||
@ -329,12 +334,6 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset)
|
||||
if (!dev_priv->mmu)
|
||||
goto out_err;
|
||||
|
||||
pg = &dev_priv->gtt;
|
||||
|
||||
tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
|
||||
(pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
|
||||
|
||||
|
||||
dev_priv->pf_pd = psb_mmu_alloc_pd(dev_priv->mmu, 1, 0);
|
||||
if (!dev_priv->pf_pd)
|
||||
goto out_err;
|
||||
@ -411,7 +410,7 @@ out_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int psb_driver_device_is_agp(struct drm_device *dev)
|
||||
static int psb_driver_device_is_agp(struct drm_device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -602,7 +601,7 @@ static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd,
|
||||
/* When a client dies:
|
||||
* - Check for and clean up flipped page state
|
||||
*/
|
||||
void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv)
|
||||
static void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv)
|
||||
{
|
||||
}
|
||||
|
||||
@ -679,7 +678,9 @@ static struct pci_driver psb_pci_driver = {
|
||||
.id_table = pciidlist,
|
||||
.probe = psb_probe,
|
||||
.remove = psb_remove,
|
||||
.driver.pm = &psb_pm_ops,
|
||||
.driver = {
|
||||
.pm = &psb_pm_ops,
|
||||
}
|
||||
};
|
||||
|
||||
static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
@ -276,6 +276,197 @@ struct intel_gmbus {
|
||||
u32 reg0;
|
||||
};
|
||||
|
||||
/*
|
||||
* Register save state. This is used to hold the context when the
|
||||
* device is powered off. In the case of Oaktrail this can (but does not
|
||||
* yet) include screen blank. Operations occuring during the save
|
||||
* update the register cache instead.
|
||||
*/
|
||||
struct psb_state {
|
||||
uint32_t saveDSPACNTR;
|
||||
uint32_t saveDSPBCNTR;
|
||||
uint32_t savePIPEACONF;
|
||||
uint32_t savePIPEBCONF;
|
||||
uint32_t savePIPEASRC;
|
||||
uint32_t savePIPEBSRC;
|
||||
uint32_t saveFPA0;
|
||||
uint32_t saveFPA1;
|
||||
uint32_t saveDPLL_A;
|
||||
uint32_t saveDPLL_A_MD;
|
||||
uint32_t saveHTOTAL_A;
|
||||
uint32_t saveHBLANK_A;
|
||||
uint32_t saveHSYNC_A;
|
||||
uint32_t saveVTOTAL_A;
|
||||
uint32_t saveVBLANK_A;
|
||||
uint32_t saveVSYNC_A;
|
||||
uint32_t saveDSPASTRIDE;
|
||||
uint32_t saveDSPASIZE;
|
||||
uint32_t saveDSPAPOS;
|
||||
uint32_t saveDSPABASE;
|
||||
uint32_t saveDSPASURF;
|
||||
uint32_t saveDSPASTATUS;
|
||||
uint32_t saveFPB0;
|
||||
uint32_t saveFPB1;
|
||||
uint32_t saveDPLL_B;
|
||||
uint32_t saveDPLL_B_MD;
|
||||
uint32_t saveHTOTAL_B;
|
||||
uint32_t saveHBLANK_B;
|
||||
uint32_t saveHSYNC_B;
|
||||
uint32_t saveVTOTAL_B;
|
||||
uint32_t saveVBLANK_B;
|
||||
uint32_t saveVSYNC_B;
|
||||
uint32_t saveDSPBSTRIDE;
|
||||
uint32_t saveDSPBSIZE;
|
||||
uint32_t saveDSPBPOS;
|
||||
uint32_t saveDSPBBASE;
|
||||
uint32_t saveDSPBSURF;
|
||||
uint32_t saveDSPBSTATUS;
|
||||
uint32_t saveVCLK_DIVISOR_VGA0;
|
||||
uint32_t saveVCLK_DIVISOR_VGA1;
|
||||
uint32_t saveVCLK_POST_DIV;
|
||||
uint32_t saveVGACNTRL;
|
||||
uint32_t saveADPA;
|
||||
uint32_t saveLVDS;
|
||||
uint32_t saveDVOA;
|
||||
uint32_t saveDVOB;
|
||||
uint32_t saveDVOC;
|
||||
uint32_t savePP_ON;
|
||||
uint32_t savePP_OFF;
|
||||
uint32_t savePP_CONTROL;
|
||||
uint32_t savePP_CYCLE;
|
||||
uint32_t savePFIT_CONTROL;
|
||||
uint32_t savePaletteA[256];
|
||||
uint32_t savePaletteB[256];
|
||||
uint32_t saveCLOCKGATING;
|
||||
uint32_t saveDSPARB;
|
||||
uint32_t saveDSPATILEOFF;
|
||||
uint32_t saveDSPBTILEOFF;
|
||||
uint32_t saveDSPAADDR;
|
||||
uint32_t saveDSPBADDR;
|
||||
uint32_t savePFIT_AUTO_RATIOS;
|
||||
uint32_t savePFIT_PGM_RATIOS;
|
||||
uint32_t savePP_ON_DELAYS;
|
||||
uint32_t savePP_OFF_DELAYS;
|
||||
uint32_t savePP_DIVISOR;
|
||||
uint32_t saveBCLRPAT_A;
|
||||
uint32_t saveBCLRPAT_B;
|
||||
uint32_t saveDSPALINOFF;
|
||||
uint32_t saveDSPBLINOFF;
|
||||
uint32_t savePERF_MODE;
|
||||
uint32_t saveDSPFW1;
|
||||
uint32_t saveDSPFW2;
|
||||
uint32_t saveDSPFW3;
|
||||
uint32_t saveDSPFW4;
|
||||
uint32_t saveDSPFW5;
|
||||
uint32_t saveDSPFW6;
|
||||
uint32_t saveCHICKENBIT;
|
||||
uint32_t saveDSPACURSOR_CTRL;
|
||||
uint32_t saveDSPBCURSOR_CTRL;
|
||||
uint32_t saveDSPACURSOR_BASE;
|
||||
uint32_t saveDSPBCURSOR_BASE;
|
||||
uint32_t saveDSPACURSOR_POS;
|
||||
uint32_t saveDSPBCURSOR_POS;
|
||||
uint32_t save_palette_a[256];
|
||||
uint32_t save_palette_b[256];
|
||||
uint32_t saveOV_OVADD;
|
||||
uint32_t saveOV_OGAMC0;
|
||||
uint32_t saveOV_OGAMC1;
|
||||
uint32_t saveOV_OGAMC2;
|
||||
uint32_t saveOV_OGAMC3;
|
||||
uint32_t saveOV_OGAMC4;
|
||||
uint32_t saveOV_OGAMC5;
|
||||
uint32_t saveOVC_OVADD;
|
||||
uint32_t saveOVC_OGAMC0;
|
||||
uint32_t saveOVC_OGAMC1;
|
||||
uint32_t saveOVC_OGAMC2;
|
||||
uint32_t saveOVC_OGAMC3;
|
||||
uint32_t saveOVC_OGAMC4;
|
||||
uint32_t saveOVC_OGAMC5;
|
||||
|
||||
/* DPST register save */
|
||||
uint32_t saveHISTOGRAM_INT_CONTROL_REG;
|
||||
uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG;
|
||||
uint32_t savePWM_CONTROL_LOGIC;
|
||||
};
|
||||
|
||||
struct medfield_state {
|
||||
uint32_t saveDPLL_A;
|
||||
uint32_t saveFPA0;
|
||||
uint32_t savePIPEACONF;
|
||||
uint32_t saveHTOTAL_A;
|
||||
uint32_t saveHBLANK_A;
|
||||
uint32_t saveHSYNC_A;
|
||||
uint32_t saveVTOTAL_A;
|
||||
uint32_t saveVBLANK_A;
|
||||
uint32_t saveVSYNC_A;
|
||||
uint32_t savePIPEASRC;
|
||||
uint32_t saveDSPASTRIDE;
|
||||
uint32_t saveDSPALINOFF;
|
||||
uint32_t saveDSPATILEOFF;
|
||||
uint32_t saveDSPASIZE;
|
||||
uint32_t saveDSPAPOS;
|
||||
uint32_t saveDSPASURF;
|
||||
uint32_t saveDSPACNTR;
|
||||
uint32_t saveDSPASTATUS;
|
||||
uint32_t save_palette_a[256];
|
||||
uint32_t saveMIPI;
|
||||
|
||||
uint32_t saveDPLL_B;
|
||||
uint32_t saveFPB0;
|
||||
uint32_t savePIPEBCONF;
|
||||
uint32_t saveHTOTAL_B;
|
||||
uint32_t saveHBLANK_B;
|
||||
uint32_t saveHSYNC_B;
|
||||
uint32_t saveVTOTAL_B;
|
||||
uint32_t saveVBLANK_B;
|
||||
uint32_t saveVSYNC_B;
|
||||
uint32_t savePIPEBSRC;
|
||||
uint32_t saveDSPBSTRIDE;
|
||||
uint32_t saveDSPBLINOFF;
|
||||
uint32_t saveDSPBTILEOFF;
|
||||
uint32_t saveDSPBSIZE;
|
||||
uint32_t saveDSPBPOS;
|
||||
uint32_t saveDSPBSURF;
|
||||
uint32_t saveDSPBCNTR;
|
||||
uint32_t saveDSPBSTATUS;
|
||||
uint32_t save_palette_b[256];
|
||||
|
||||
uint32_t savePIPECCONF;
|
||||
uint32_t saveHTOTAL_C;
|
||||
uint32_t saveHBLANK_C;
|
||||
uint32_t saveHSYNC_C;
|
||||
uint32_t saveVTOTAL_C;
|
||||
uint32_t saveVBLANK_C;
|
||||
uint32_t saveVSYNC_C;
|
||||
uint32_t savePIPECSRC;
|
||||
uint32_t saveDSPCSTRIDE;
|
||||
uint32_t saveDSPCLINOFF;
|
||||
uint32_t saveDSPCTILEOFF;
|
||||
uint32_t saveDSPCSIZE;
|
||||
uint32_t saveDSPCPOS;
|
||||
uint32_t saveDSPCSURF;
|
||||
uint32_t saveDSPCCNTR;
|
||||
uint32_t saveDSPCSTATUS;
|
||||
uint32_t save_palette_c[256];
|
||||
uint32_t saveMIPI_C;
|
||||
|
||||
uint32_t savePFIT_CONTROL;
|
||||
uint32_t savePFIT_PGM_RATIOS;
|
||||
uint32_t saveHDMIPHYMISCCTL;
|
||||
uint32_t saveHDMIB_CONTROL;
|
||||
};
|
||||
|
||||
struct psb_save_area {
|
||||
uint32_t saveBSM;
|
||||
uint32_t saveVBT;
|
||||
union {
|
||||
struct psb_state psb;
|
||||
struct medfield_state mdfld;
|
||||
};
|
||||
uint32_t saveBLC_PWM_CTL2;
|
||||
uint32_t saveBLC_PWM_CTL;
|
||||
};
|
||||
|
||||
struct psb_ops;
|
||||
|
||||
#define PSB_NUM_PIPE 3
|
||||
@ -397,215 +588,20 @@ struct drm_psb_private {
|
||||
struct oaktrail_vbt vbt_data;
|
||||
struct oaktrail_gct_data gct_data;
|
||||
|
||||
/* MIPI Panel type etc */
|
||||
int panel_id;
|
||||
bool dual_mipi; /* dual display - DPI & DBI */
|
||||
bool dpi_panel_on; /* The DPI panel power is on */
|
||||
bool dpi_panel_on2; /* The DPI panel power is on */
|
||||
bool dbi_panel_on; /* The DBI panel power is on */
|
||||
bool dbi_panel_on2; /* The DBI panel power is on */
|
||||
u32 dsr_fb_update; /* DSR FB update counter */
|
||||
|
||||
/* Moorestown HDMI state */
|
||||
/* Oaktrail HDMI state */
|
||||
struct oaktrail_hdmi_dev *hdmi_priv;
|
||||
|
||||
/* Moorestown pipe config register value cache */
|
||||
uint32_t pipeconf;
|
||||
uint32_t pipeconf1;
|
||||
uint32_t pipeconf2;
|
||||
|
||||
/* Moorestown plane control register value cache */
|
||||
uint32_t dspcntr;
|
||||
uint32_t dspcntr1;
|
||||
uint32_t dspcntr2;
|
||||
|
||||
/* Moorestown MM backlight cache */
|
||||
uint8_t saveBKLTCNT;
|
||||
uint8_t saveBKLTREQ;
|
||||
uint8_t saveBKLTBRTL;
|
||||
|
||||
|
||||
/*
|
||||
* Register state
|
||||
*/
|
||||
uint32_t saveDSPACNTR;
|
||||
uint32_t saveDSPBCNTR;
|
||||
uint32_t savePIPEACONF;
|
||||
uint32_t savePIPEBCONF;
|
||||
uint32_t savePIPEASRC;
|
||||
uint32_t savePIPEBSRC;
|
||||
uint32_t saveFPA0;
|
||||
uint32_t saveFPA1;
|
||||
uint32_t saveDPLL_A;
|
||||
uint32_t saveDPLL_A_MD;
|
||||
uint32_t saveHTOTAL_A;
|
||||
uint32_t saveHBLANK_A;
|
||||
uint32_t saveHSYNC_A;
|
||||
uint32_t saveVTOTAL_A;
|
||||
uint32_t saveVBLANK_A;
|
||||
uint32_t saveVSYNC_A;
|
||||
uint32_t saveDSPASTRIDE;
|
||||
uint32_t saveDSPASIZE;
|
||||
uint32_t saveDSPAPOS;
|
||||
uint32_t saveDSPABASE;
|
||||
uint32_t saveDSPASURF;
|
||||
uint32_t saveDSPASTATUS;
|
||||
uint32_t saveFPB0;
|
||||
uint32_t saveFPB1;
|
||||
uint32_t saveDPLL_B;
|
||||
uint32_t saveDPLL_B_MD;
|
||||
uint32_t saveHTOTAL_B;
|
||||
uint32_t saveHBLANK_B;
|
||||
uint32_t saveHSYNC_B;
|
||||
uint32_t saveVTOTAL_B;
|
||||
uint32_t saveVBLANK_B;
|
||||
uint32_t saveVSYNC_B;
|
||||
uint32_t saveDSPBSTRIDE;
|
||||
uint32_t saveDSPBSIZE;
|
||||
uint32_t saveDSPBPOS;
|
||||
uint32_t saveDSPBBASE;
|
||||
uint32_t saveDSPBSURF;
|
||||
uint32_t saveDSPBSTATUS;
|
||||
uint32_t saveVCLK_DIVISOR_VGA0;
|
||||
uint32_t saveVCLK_DIVISOR_VGA1;
|
||||
uint32_t saveVCLK_POST_DIV;
|
||||
uint32_t saveVGACNTRL;
|
||||
uint32_t saveADPA;
|
||||
uint32_t saveLVDS;
|
||||
uint32_t saveDVOA;
|
||||
uint32_t saveDVOB;
|
||||
uint32_t saveDVOC;
|
||||
uint32_t savePP_ON;
|
||||
uint32_t savePP_OFF;
|
||||
uint32_t savePP_CONTROL;
|
||||
uint32_t savePP_CYCLE;
|
||||
uint32_t savePFIT_CONTROL;
|
||||
uint32_t savePaletteA[256];
|
||||
uint32_t savePaletteB[256];
|
||||
uint32_t saveBLC_PWM_CTL2;
|
||||
uint32_t saveBLC_PWM_CTL;
|
||||
uint32_t saveCLOCKGATING;
|
||||
uint32_t saveDSPARB;
|
||||
uint32_t saveDSPATILEOFF;
|
||||
uint32_t saveDSPBTILEOFF;
|
||||
uint32_t saveDSPAADDR;
|
||||
uint32_t saveDSPBADDR;
|
||||
uint32_t savePFIT_AUTO_RATIOS;
|
||||
uint32_t savePFIT_PGM_RATIOS;
|
||||
uint32_t savePP_ON_DELAYS;
|
||||
uint32_t savePP_OFF_DELAYS;
|
||||
uint32_t savePP_DIVISOR;
|
||||
uint32_t saveBSM;
|
||||
uint32_t saveVBT;
|
||||
uint32_t saveBCLRPAT_A;
|
||||
uint32_t saveBCLRPAT_B;
|
||||
uint32_t saveDSPALINOFF;
|
||||
uint32_t saveDSPBLINOFF;
|
||||
uint32_t savePERF_MODE;
|
||||
uint32_t saveDSPFW1;
|
||||
uint32_t saveDSPFW2;
|
||||
uint32_t saveDSPFW3;
|
||||
uint32_t saveDSPFW4;
|
||||
uint32_t saveDSPFW5;
|
||||
uint32_t saveDSPFW6;
|
||||
uint32_t saveCHICKENBIT;
|
||||
uint32_t saveDSPACURSOR_CTRL;
|
||||
uint32_t saveDSPBCURSOR_CTRL;
|
||||
uint32_t saveDSPACURSOR_BASE;
|
||||
uint32_t saveDSPBCURSOR_BASE;
|
||||
uint32_t saveDSPACURSOR_POS;
|
||||
uint32_t saveDSPBCURSOR_POS;
|
||||
uint32_t save_palette_a[256];
|
||||
uint32_t save_palette_b[256];
|
||||
uint32_t saveOV_OVADD;
|
||||
uint32_t saveOV_OGAMC0;
|
||||
uint32_t saveOV_OGAMC1;
|
||||
uint32_t saveOV_OGAMC2;
|
||||
uint32_t saveOV_OGAMC3;
|
||||
uint32_t saveOV_OGAMC4;
|
||||
uint32_t saveOV_OGAMC5;
|
||||
uint32_t saveOVC_OVADD;
|
||||
uint32_t saveOVC_OGAMC0;
|
||||
uint32_t saveOVC_OGAMC1;
|
||||
uint32_t saveOVC_OGAMC2;
|
||||
uint32_t saveOVC_OGAMC3;
|
||||
uint32_t saveOVC_OGAMC4;
|
||||
uint32_t saveOVC_OGAMC5;
|
||||
|
||||
struct psb_save_area regs;
|
||||
|
||||
/* MSI reg save */
|
||||
uint32_t msi_addr;
|
||||
uint32_t msi_data;
|
||||
|
||||
/* Medfield specific register save state */
|
||||
uint32_t saveHDMIPHYMISCCTL;
|
||||
uint32_t saveHDMIB_CONTROL;
|
||||
uint32_t saveDSPCCNTR;
|
||||
uint32_t savePIPECCONF;
|
||||
uint32_t savePIPECSRC;
|
||||
uint32_t saveHTOTAL_C;
|
||||
uint32_t saveHBLANK_C;
|
||||
uint32_t saveHSYNC_C;
|
||||
uint32_t saveVTOTAL_C;
|
||||
uint32_t saveVBLANK_C;
|
||||
uint32_t saveVSYNC_C;
|
||||
uint32_t saveDSPCSTRIDE;
|
||||
uint32_t saveDSPCSIZE;
|
||||
uint32_t saveDSPCPOS;
|
||||
uint32_t saveDSPCSURF;
|
||||
uint32_t saveDSPCSTATUS;
|
||||
uint32_t saveDSPCLINOFF;
|
||||
uint32_t saveDSPCTILEOFF;
|
||||
uint32_t saveDSPCCURSOR_CTRL;
|
||||
uint32_t saveDSPCCURSOR_BASE;
|
||||
uint32_t saveDSPCCURSOR_POS;
|
||||
uint32_t save_palette_c[256];
|
||||
uint32_t saveOV_OVADD_C;
|
||||
uint32_t saveOV_OGAMC0_C;
|
||||
uint32_t saveOV_OGAMC1_C;
|
||||
uint32_t saveOV_OGAMC2_C;
|
||||
uint32_t saveOV_OGAMC3_C;
|
||||
uint32_t saveOV_OGAMC4_C;
|
||||
uint32_t saveOV_OGAMC5_C;
|
||||
|
||||
/* DSI register save */
|
||||
uint32_t saveDEVICE_READY_REG;
|
||||
uint32_t saveINTR_EN_REG;
|
||||
uint32_t saveDSI_FUNC_PRG_REG;
|
||||
uint32_t saveHS_TX_TIMEOUT_REG;
|
||||
uint32_t saveLP_RX_TIMEOUT_REG;
|
||||
uint32_t saveTURN_AROUND_TIMEOUT_REG;
|
||||
uint32_t saveDEVICE_RESET_REG;
|
||||
uint32_t saveDPI_RESOLUTION_REG;
|
||||
uint32_t saveHORIZ_SYNC_PAD_COUNT_REG;
|
||||
uint32_t saveHORIZ_BACK_PORCH_COUNT_REG;
|
||||
uint32_t saveHORIZ_FRONT_PORCH_COUNT_REG;
|
||||
uint32_t saveHORIZ_ACTIVE_AREA_COUNT_REG;
|
||||
uint32_t saveVERT_SYNC_PAD_COUNT_REG;
|
||||
uint32_t saveVERT_BACK_PORCH_COUNT_REG;
|
||||
uint32_t saveVERT_FRONT_PORCH_COUNT_REG;
|
||||
uint32_t saveHIGH_LOW_SWITCH_COUNT_REG;
|
||||
uint32_t saveINIT_COUNT_REG;
|
||||
uint32_t saveMAX_RET_PAK_REG;
|
||||
uint32_t saveVIDEO_FMT_REG;
|
||||
uint32_t saveEOT_DISABLE_REG;
|
||||
uint32_t saveLP_BYTECLK_REG;
|
||||
uint32_t saveHS_LS_DBI_ENABLE_REG;
|
||||
uint32_t saveTXCLKESC_REG;
|
||||
uint32_t saveDPHY_PARAM_REG;
|
||||
uint32_t saveMIPI_CONTROL_REG;
|
||||
uint32_t saveMIPI;
|
||||
uint32_t saveMIPI_C;
|
||||
|
||||
/* DPST register save */
|
||||
uint32_t saveHISTOGRAM_INT_CONTROL_REG;
|
||||
uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG;
|
||||
uint32_t savePWM_CONTROL_LOGIC;
|
||||
|
||||
/*
|
||||
* DSI info.
|
||||
*/
|
||||
void * dbi_dsr_info;
|
||||
void * dbi_dpu_info;
|
||||
void * dsi_configs[2];
|
||||
/*
|
||||
* LID-Switch
|
||||
*/
|
||||
@ -635,6 +631,24 @@ struct drm_psb_private {
|
||||
|
||||
/* 2D acceleration */
|
||||
spinlock_t lock_2d;
|
||||
|
||||
/*
|
||||
* Panel brightness
|
||||
*/
|
||||
int brightness;
|
||||
int brightness_adjusted;
|
||||
|
||||
bool dsr_enable;
|
||||
u32 dsr_fb_update;
|
||||
bool dpi_panel_on[3];
|
||||
void *dsi_configs[2];
|
||||
u32 bpp;
|
||||
u32 bpp2;
|
||||
|
||||
u32 pipeconf[3];
|
||||
u32 dspcntr[3];
|
||||
|
||||
int mdfld_panel_id;
|
||||
};
|
||||
|
||||
|
||||
@ -830,6 +844,9 @@ extern const struct psb_ops psb_chip_ops;
|
||||
/* oaktrail_device.c */
|
||||
extern const struct psb_ops oaktrail_chip_ops;
|
||||
|
||||
/* mdlfd_device.c */
|
||||
extern const struct psb_ops mdfld_chip_ops;
|
||||
|
||||
/* cdv_device.c */
|
||||
extern const struct psb_ops cdv_chip_ops;
|
||||
|
||||
|
@ -333,7 +333,7 @@ void psb_intel_wait_for_vblank(struct drm_device *dev)
|
||||
mdelay(20);
|
||||
}
|
||||
|
||||
int psb_intel_pipe_set_base(struct drm_crtc *crtc,
|
||||
static int psb_intel_pipe_set_base(struct drm_crtc *crtc,
|
||||
int x, int y, struct drm_framebuffer *old_fb)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
@ -433,7 +433,6 @@ static void psb_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
|
||||
int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
|
||||
u32 temp;
|
||||
bool enabled;
|
||||
|
||||
/* XXX: When our outputs are all unaware of DPMS modes other than off
|
||||
* and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
|
||||
@ -518,8 +517,6 @@ static void psb_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
|
||||
break;
|
||||
}
|
||||
|
||||
enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
|
||||
|
||||
/*Set FIFO Watermarks*/
|
||||
REG_WRITE(DSPARB, 0x3F3E);
|
||||
}
|
||||
@ -611,8 +608,8 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
int refclk;
|
||||
struct psb_intel_clock_t clock;
|
||||
u32 dpll = 0, fp = 0, dspcntr, pipeconf;
|
||||
bool ok, is_sdvo = false, is_dvo = false;
|
||||
bool is_crt = false, is_lvds = false, is_tv = false;
|
||||
bool ok, is_sdvo = false;
|
||||
bool is_lvds = false, is_tv = false;
|
||||
struct drm_mode_config *mode_config = &dev->mode_config;
|
||||
struct drm_connector *connector;
|
||||
|
||||
@ -637,15 +634,9 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc,
|
||||
case INTEL_OUTPUT_SDVO:
|
||||
is_sdvo = true;
|
||||
break;
|
||||
case INTEL_OUTPUT_DVO:
|
||||
is_dvo = true;
|
||||
break;
|
||||
case INTEL_OUTPUT_TVOUT:
|
||||
is_tv = true;
|
||||
break;
|
||||
case INTEL_OUTPUT_ANALOG:
|
||||
is_crt = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -845,7 +836,7 @@ void psb_intel_crtc_load_lut(struct drm_crtc *crtc)
|
||||
gma_power_end(dev);
|
||||
} else {
|
||||
for (i = 0; i < 256; i++) {
|
||||
dev_priv->save_palette_a[i] =
|
||||
dev_priv->regs.psb.save_palette_a[i] =
|
||||
((psb_intel_crtc->lut_r[i] +
|
||||
psb_intel_crtc->lut_adj[i]) << 16) |
|
||||
((psb_intel_crtc->lut_g[i] +
|
||||
@ -1141,18 +1132,20 @@ static int psb_intel_crtc_clock_get(struct drm_device *dev,
|
||||
gma_power_end(dev);
|
||||
} else {
|
||||
dpll = (pipe == 0) ?
|
||||
dev_priv->saveDPLL_A : dev_priv->saveDPLL_B;
|
||||
dev_priv->regs.psb.saveDPLL_A :
|
||||
dev_priv->regs.psb.saveDPLL_B;
|
||||
|
||||
if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
|
||||
fp = (pipe == 0) ?
|
||||
dev_priv->saveFPA0 :
|
||||
dev_priv->saveFPB0;
|
||||
dev_priv->regs.psb.saveFPA0 :
|
||||
dev_priv->regs.psb.saveFPB0;
|
||||
else
|
||||
fp = (pipe == 0) ?
|
||||
dev_priv->saveFPA1 :
|
||||
dev_priv->saveFPB1;
|
||||
dev_priv->regs.psb.saveFPA1 :
|
||||
dev_priv->regs.psb.saveFPB1;
|
||||
|
||||
is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN);
|
||||
is_lvds = (pipe == 1) && (dev_priv->regs.psb.saveLVDS &
|
||||
LVDS_PORT_EN);
|
||||
}
|
||||
|
||||
clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
|
||||
@ -1218,13 +1211,17 @@ struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
|
||||
gma_power_end(dev);
|
||||
} else {
|
||||
htot = (pipe == 0) ?
|
||||
dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B;
|
||||
dev_priv->regs.psb.saveHTOTAL_A :
|
||||
dev_priv->regs.psb.saveHTOTAL_B;
|
||||
hsync = (pipe == 0) ?
|
||||
dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B;
|
||||
dev_priv->regs.psb.saveHSYNC_A :
|
||||
dev_priv->regs.psb.saveHSYNC_B;
|
||||
vtot = (pipe == 0) ?
|
||||
dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B;
|
||||
dev_priv->regs.psb.saveVTOTAL_A :
|
||||
dev_priv->regs.psb.saveVTOTAL_B;
|
||||
vsync = (pipe == 0) ?
|
||||
dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B;
|
||||
dev_priv->regs.psb.saveVSYNC_A :
|
||||
dev_priv->regs.psb.saveVSYNC_B;
|
||||
}
|
||||
|
||||
mode = kzalloc(sizeof(*mode), GFP_KERNEL);
|
||||
@ -1419,13 +1416,6 @@ int psb_intel_connector_clones(struct drm_device *dev, int type_mask)
|
||||
return index_mask;
|
||||
}
|
||||
|
||||
|
||||
void psb_intel_modeset_cleanup(struct drm_device *dev)
|
||||
{
|
||||
drm_mode_config_cleanup(dev);
|
||||
}
|
||||
|
||||
|
||||
/* current intel driver doesn't take advantage of encoders
|
||||
always give back the encoder for the connector
|
||||
*/
|
||||
|
@ -77,7 +77,7 @@ static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev)
|
||||
ret = REG_READ(BLC_PWM_CTL);
|
||||
gma_power_end(dev);
|
||||
} else /* Powered off, use the saved value */
|
||||
ret = dev_priv->saveBLC_PWM_CTL;
|
||||
ret = dev_priv->regs.saveBLC_PWM_CTL;
|
||||
|
||||
/* Top 15bits hold the frequency mask */
|
||||
ret = (ret & BACKLIGHT_MODULATION_FREQ_MASK) >>
|
||||
@ -86,7 +86,7 @@ static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev)
|
||||
ret *= 2; /* Return a 16bit range as needed for setting */
|
||||
if (ret == 0)
|
||||
dev_err(dev->dev, "BL bug: Reg %08x save %08X\n",
|
||||
REG_READ(BLC_PWM_CTL), dev_priv->saveBLC_PWM_CTL);
|
||||
REG_READ(BLC_PWM_CTL), dev_priv->regs.saveBLC_PWM_CTL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -203,13 +203,13 @@ static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level)
|
||||
REG_WRITE(BLC_PWM_CTL,
|
||||
(blc_pwm_ctl |
|
||||
(level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
|
||||
dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
|
||||
dev_priv->regs.saveBLC_PWM_CTL = (blc_pwm_ctl |
|
||||
(level << BACKLIGHT_DUTY_CYCLE_SHIFT));
|
||||
gma_power_end(dev);
|
||||
} else {
|
||||
blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL &
|
||||
blc_pwm_ctl = dev_priv->regs.saveBLC_PWM_CTL &
|
||||
~BACKLIGHT_DUTY_CYCLE_MASK;
|
||||
dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
|
||||
dev_priv->regs.saveBLC_PWM_CTL = (blc_pwm_ctl |
|
||||
(level << BACKLIGHT_DUTY_CYCLE_SHIFT));
|
||||
}
|
||||
}
|
||||
@ -283,7 +283,7 @@ static void psb_intel_lvds_save(struct drm_connector *connector)
|
||||
lvds_priv->savePFIT_PGM_RATIOS = REG_READ(PFIT_PGM_RATIOS);
|
||||
|
||||
/*TODO: move backlight_duty_cycle to psb_intel_lvds_priv*/
|
||||
dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
|
||||
dev_priv->backlight_duty_cycle = (dev_priv->regs.saveBLC_PWM_CTL &
|
||||
BACKLIGHT_DUTY_CYCLE_MASK);
|
||||
|
||||
/*
|
||||
@ -713,7 +713,6 @@ void psb_intel_lvds_init(struct drm_device *dev,
|
||||
|
||||
psb_intel_encoder =
|
||||
kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL);
|
||||
|
||||
if (!psb_intel_encoder) {
|
||||
dev_err(dev->dev, "psb_intel_encoder allocation error\n");
|
||||
return;
|
||||
@ -721,10 +720,9 @@ void psb_intel_lvds_init(struct drm_device *dev,
|
||||
|
||||
psb_intel_connector =
|
||||
kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL);
|
||||
|
||||
if (!psb_intel_connector) {
|
||||
kfree(psb_intel_encoder);
|
||||
dev_err(dev->dev, "psb_intel_connector allocation error\n");
|
||||
goto failed_encoder;
|
||||
}
|
||||
|
||||
lvds_priv = kzalloc(sizeof(struct psb_intel_lvds_priv), GFP_KERNEL);
|
||||
@ -862,7 +860,8 @@ failed_blc_i2c:
|
||||
drm_encoder_cleanup(encoder);
|
||||
drm_connector_cleanup(connector);
|
||||
failed_connector:
|
||||
if (psb_intel_connector)
|
||||
kfree(psb_intel_connector);
|
||||
kfree(psb_intel_connector);
|
||||
failed_encoder:
|
||||
kfree(psb_intel_encoder);
|
||||
}
|
||||
|
||||
|
@ -1301,7 +1301,7 @@ psb_intel_sdvo_get_analog_edid(struct drm_connector *connector)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enum drm_connector_status
|
||||
static enum drm_connector_status
|
||||
psb_intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
|
||||
{
|
||||
struct psb_intel_sdvo *psb_intel_sdvo = intel_attached_sdvo(connector);
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include "psb_reg.h"
|
||||
#include "psb_intel_reg.h"
|
||||
#include "power.h"
|
||||
#include "psb_irq.h"
|
||||
#include "mdfld_output.h"
|
||||
|
||||
/*
|
||||
* inline functions
|
||||
@ -113,7 +115,7 @@ psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
|
||||
}
|
||||
}
|
||||
|
||||
void mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
|
||||
static void mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
|
||||
{
|
||||
if (gma_power_begin(dev_priv->dev, false)) {
|
||||
u32 pipe_event = mid_pipe_event(pipe);
|
||||
@ -124,7 +126,7 @@ void mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
|
||||
}
|
||||
}
|
||||
|
||||
void mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
|
||||
static void mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe)
|
||||
{
|
||||
if (dev_priv->pipestat[pipe] == 0) {
|
||||
if (gma_power_begin(dev_priv->dev, false)) {
|
||||
@ -453,6 +455,11 @@ int psb_enable_vblank(struct drm_device *dev, int pipe)
|
||||
uint32_t reg_val = 0;
|
||||
uint32_t pipeconf_reg = mid_pipeconf(pipe);
|
||||
|
||||
/* Medfield is different - we should perhaps extract out vblank
|
||||
and blacklight etc ops */
|
||||
if (IS_MFLD(dev))
|
||||
return mdfld_enable_te(dev, pipe);
|
||||
|
||||
if (gma_power_begin(dev, false)) {
|
||||
reg_val = REG_READ(pipeconf_reg);
|
||||
gma_power_end(dev);
|
||||
@ -485,6 +492,8 @@ void psb_disable_vblank(struct drm_device *dev, int pipe)
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
unsigned long irqflags;
|
||||
|
||||
if (IS_MFLD(dev))
|
||||
mdfld_disable_te(dev, pipe);
|
||||
spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
|
||||
|
||||
if (pipe == 0)
|
||||
@ -499,6 +508,55 @@ void psb_disable_vblank(struct drm_device *dev, int pipe)
|
||||
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
|
||||
}
|
||||
|
||||
/*
|
||||
* It is used to enable TE interrupt
|
||||
*/
|
||||
int mdfld_enable_te(struct drm_device *dev, int pipe)
|
||||
{
|
||||
struct drm_psb_private *dev_priv =
|
||||
(struct drm_psb_private *) dev->dev_private;
|
||||
unsigned long irqflags;
|
||||
uint32_t reg_val = 0;
|
||||
uint32_t pipeconf_reg = mid_pipeconf(pipe);
|
||||
|
||||
if (gma_power_begin(dev, false)) {
|
||||
reg_val = REG_READ(pipeconf_reg);
|
||||
gma_power_end(dev);
|
||||
}
|
||||
|
||||
if (!(reg_val & PIPEACONF_ENABLE))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
|
||||
|
||||
mid_enable_pipe_event(dev_priv, pipe);
|
||||
psb_enable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* It is used to disable TE interrupt
|
||||
*/
|
||||
void mdfld_disable_te(struct drm_device *dev, int pipe)
|
||||
{
|
||||
struct drm_psb_private *dev_priv =
|
||||
(struct drm_psb_private *) dev->dev_private;
|
||||
unsigned long irqflags;
|
||||
|
||||
if (!dev_priv->dsr_enable)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
|
||||
|
||||
mid_disable_pipe_event(dev_priv, pipe);
|
||||
psb_disable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
|
||||
}
|
||||
|
||||
/* Called from drm generic code, passed a 'crtc', which
|
||||
* we use as a pipe index
|
||||
*/
|
||||
|
@ -42,4 +42,6 @@ int psb_enable_vblank(struct drm_device *dev, int pipe);
|
||||
void psb_disable_vblank(struct drm_device *dev, int pipe);
|
||||
u32 psb_get_vblank_counter(struct drm_device *dev, int pipe);
|
||||
|
||||
int mdfld_enable_te(struct drm_device *dev, int pipe);
|
||||
void mdfld_disable_te(struct drm_device *dev, int pipe);
|
||||
#endif /* _SYSIRQ_H_ */
|
||||
|
829
drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c
Normal file
829
drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c
Normal file
@ -0,0 +1,829 @@
|
||||
/*
|
||||
* Copyright © 2011 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mdfld_dsi_dpi.h"
|
||||
#include "mdfld_output.h"
|
||||
#include "mdfld_dsi_pkg_sender.h"
|
||||
#include "tc35876x-dsi-lvds.h"
|
||||
#include <linux/i2c/tc35876x.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <asm/intel_scu_ipc.h>
|
||||
|
||||
static struct i2c_client *tc35876x_client;
|
||||
static struct i2c_client *cmi_lcd_i2c_client;
|
||||
|
||||
#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
|
||||
#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
|
||||
|
||||
/* DSI D-PHY Layer Registers */
|
||||
#define D0W_DPHYCONTTX 0x0004
|
||||
#define CLW_DPHYCONTRX 0x0020
|
||||
#define D0W_DPHYCONTRX 0x0024
|
||||
#define D1W_DPHYCONTRX 0x0028
|
||||
#define D2W_DPHYCONTRX 0x002C
|
||||
#define D3W_DPHYCONTRX 0x0030
|
||||
#define COM_DPHYCONTRX 0x0038
|
||||
#define CLW_CNTRL 0x0040
|
||||
#define D0W_CNTRL 0x0044
|
||||
#define D1W_CNTRL 0x0048
|
||||
#define D2W_CNTRL 0x004C
|
||||
#define D3W_CNTRL 0x0050
|
||||
#define DFTMODE_CNTRL 0x0054
|
||||
|
||||
/* DSI PPI Layer Registers */
|
||||
#define PPI_STARTPPI 0x0104
|
||||
#define PPI_BUSYPPI 0x0108
|
||||
#define PPI_LINEINITCNT 0x0110
|
||||
#define PPI_LPTXTIMECNT 0x0114
|
||||
#define PPI_LANEENABLE 0x0134
|
||||
#define PPI_TX_RX_TA 0x013C
|
||||
#define PPI_CLS_ATMR 0x0140
|
||||
#define PPI_D0S_ATMR 0x0144
|
||||
#define PPI_D1S_ATMR 0x0148
|
||||
#define PPI_D2S_ATMR 0x014C
|
||||
#define PPI_D3S_ATMR 0x0150
|
||||
#define PPI_D0S_CLRSIPOCOUNT 0x0164
|
||||
#define PPI_D1S_CLRSIPOCOUNT 0x0168
|
||||
#define PPI_D2S_CLRSIPOCOUNT 0x016C
|
||||
#define PPI_D3S_CLRSIPOCOUNT 0x0170
|
||||
#define CLS_PRE 0x0180
|
||||
#define D0S_PRE 0x0184
|
||||
#define D1S_PRE 0x0188
|
||||
#define D2S_PRE 0x018C
|
||||
#define D3S_PRE 0x0190
|
||||
#define CLS_PREP 0x01A0
|
||||
#define D0S_PREP 0x01A4
|
||||
#define D1S_PREP 0x01A8
|
||||
#define D2S_PREP 0x01AC
|
||||
#define D3S_PREP 0x01B0
|
||||
#define CLS_ZERO 0x01C0
|
||||
#define D0S_ZERO 0x01C4
|
||||
#define D1S_ZERO 0x01C8
|
||||
#define D2S_ZERO 0x01CC
|
||||
#define D3S_ZERO 0x01D0
|
||||
#define PPI_CLRFLG 0x01E0
|
||||
#define PPI_CLRSIPO 0x01E4
|
||||
#define HSTIMEOUT 0x01F0
|
||||
#define HSTIMEOUTENABLE 0x01F4
|
||||
|
||||
/* DSI Protocol Layer Registers */
|
||||
#define DSI_STARTDSI 0x0204
|
||||
#define DSI_BUSYDSI 0x0208
|
||||
#define DSI_LANEENABLE 0x0210
|
||||
#define DSI_LANESTATUS0 0x0214
|
||||
#define DSI_LANESTATUS1 0x0218
|
||||
#define DSI_INTSTATUS 0x0220
|
||||
#define DSI_INTMASK 0x0224
|
||||
#define DSI_INTCLR 0x0228
|
||||
#define DSI_LPTXTO 0x0230
|
||||
|
||||
/* DSI General Registers */
|
||||
#define DSIERRCNT 0x0300
|
||||
|
||||
/* DSI Application Layer Registers */
|
||||
#define APLCTRL 0x0400
|
||||
#define RDPKTLN 0x0404
|
||||
|
||||
/* Video Path Registers */
|
||||
#define VPCTRL 0x0450
|
||||
#define HTIM1 0x0454
|
||||
#define HTIM2 0x0458
|
||||
#define VTIM1 0x045C
|
||||
#define VTIM2 0x0460
|
||||
#define VFUEN 0x0464
|
||||
|
||||
/* LVDS Registers */
|
||||
#define LVMX0003 0x0480
|
||||
#define LVMX0407 0x0484
|
||||
#define LVMX0811 0x0488
|
||||
#define LVMX1215 0x048C
|
||||
#define LVMX1619 0x0490
|
||||
#define LVMX2023 0x0494
|
||||
#define LVMX2427 0x0498
|
||||
#define LVCFG 0x049C
|
||||
#define LVPHY0 0x04A0
|
||||
#define LVPHY1 0x04A4
|
||||
|
||||
/* System Registers */
|
||||
#define SYSSTAT 0x0500
|
||||
#define SYSRST 0x0504
|
||||
|
||||
/* GPIO Registers */
|
||||
/*#define GPIOC 0x0520*/
|
||||
#define GPIOO 0x0524
|
||||
#define GPIOI 0x0528
|
||||
|
||||
/* I2C Registers */
|
||||
#define I2CTIMCTRL 0x0540
|
||||
#define I2CMADDR 0x0544
|
||||
#define WDATAQ 0x0548
|
||||
#define RDATAQ 0x054C
|
||||
|
||||
/* Chip/Rev Registers */
|
||||
#define IDREG 0x0580
|
||||
|
||||
/* Debug Registers */
|
||||
#define DEBUG00 0x05A0
|
||||
#define DEBUG01 0x05A4
|
||||
|
||||
/* Panel CABC registers */
|
||||
#define PANEL_PWM_CONTROL 0x90
|
||||
#define PANEL_FREQ_DIVIDER_HI 0x91
|
||||
#define PANEL_FREQ_DIVIDER_LO 0x92
|
||||
#define PANEL_DUTY_CONTROL 0x93
|
||||
#define PANEL_MODIFY_RGB 0x94
|
||||
#define PANEL_FRAMERATE_CONTROL 0x96
|
||||
#define PANEL_PWM_MIN 0x97
|
||||
#define PANEL_PWM_REF 0x98
|
||||
#define PANEL_PWM_MAX 0x99
|
||||
#define PANEL_ALLOW_DISTORT 0x9A
|
||||
#define PANEL_BYPASS_PWMI 0x9B
|
||||
|
||||
/* Panel color management registers */
|
||||
#define PANEL_CM_ENABLE 0x700
|
||||
#define PANEL_CM_HUE 0x701
|
||||
#define PANEL_CM_SATURATION 0x702
|
||||
#define PANEL_CM_INTENSITY 0x703
|
||||
#define PANEL_CM_BRIGHTNESS 0x704
|
||||
#define PANEL_CM_CE_ENABLE 0x705
|
||||
#define PANEL_CM_PEAK_EN 0x710
|
||||
#define PANEL_CM_GAIN 0x711
|
||||
#define PANEL_CM_HUETABLE_START 0x730
|
||||
#define PANEL_CM_HUETABLE_END 0x747 /* inclusive */
|
||||
|
||||
/* Input muxing for registers LVMX0003...LVMX2427 */
|
||||
enum {
|
||||
INPUT_R0, /* 0 */
|
||||
INPUT_R1,
|
||||
INPUT_R2,
|
||||
INPUT_R3,
|
||||
INPUT_R4,
|
||||
INPUT_R5,
|
||||
INPUT_R6,
|
||||
INPUT_R7,
|
||||
INPUT_G0, /* 8 */
|
||||
INPUT_G1,
|
||||
INPUT_G2,
|
||||
INPUT_G3,
|
||||
INPUT_G4,
|
||||
INPUT_G5,
|
||||
INPUT_G6,
|
||||
INPUT_G7,
|
||||
INPUT_B0, /* 16 */
|
||||
INPUT_B1,
|
||||
INPUT_B2,
|
||||
INPUT_B3,
|
||||
INPUT_B4,
|
||||
INPUT_B5,
|
||||
INPUT_B6,
|
||||
INPUT_B7,
|
||||
INPUT_HSYNC, /* 24 */
|
||||
INPUT_VSYNC,
|
||||
INPUT_DE,
|
||||
LOGIC_0,
|
||||
/* 28...31 undefined */
|
||||
};
|
||||
|
||||
#define INPUT_MUX(lvmx03, lvmx02, lvmx01, lvmx00) \
|
||||
(FLD_VAL(lvmx03, 29, 24) | FLD_VAL(lvmx02, 20, 16) | \
|
||||
FLD_VAL(lvmx01, 12, 8) | FLD_VAL(lvmx00, 4, 0))
|
||||
|
||||
/**
|
||||
* tc35876x_regw - Write DSI-LVDS bridge register using I2C
|
||||
* @client: struct i2c_client to use
|
||||
* @reg: register address
|
||||
* @value: value to write
|
||||
*
|
||||
* Returns 0 on success, or a negative error value.
|
||||
*/
|
||||
static int tc35876x_regw(struct i2c_client *client, u16 reg, u32 value)
|
||||
{
|
||||
int r;
|
||||
u8 tx_data[] = {
|
||||
/* NOTE: Register address big-endian, data little-endian. */
|
||||
(reg >> 8) & 0xff,
|
||||
reg & 0xff,
|
||||
value & 0xff,
|
||||
(value >> 8) & 0xff,
|
||||
(value >> 16) & 0xff,
|
||||
(value >> 24) & 0xff,
|
||||
};
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = 0,
|
||||
.buf = tx_data,
|
||||
.len = ARRAY_SIZE(tx_data),
|
||||
},
|
||||
};
|
||||
|
||||
r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
|
||||
if (r < 0) {
|
||||
dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x error %d\n",
|
||||
__func__, reg, value, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (r < ARRAY_SIZE(msgs)) {
|
||||
dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x msgs %d\n",
|
||||
__func__, reg, value, r);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
dev_dbg(&client->dev, "%s: reg 0x%04x val 0x%08x\n",
|
||||
__func__, reg, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* tc35876x_regr - Read DSI-LVDS bridge register using I2C
|
||||
* @client: struct i2c_client to use
|
||||
* @reg: register address
|
||||
* @value: pointer for storing the value
|
||||
*
|
||||
* Returns 0 on success, or a negative error value.
|
||||
*/
|
||||
static int tc35876x_regr(struct i2c_client *client, u16 reg, u32 *value)
|
||||
{
|
||||
int r;
|
||||
u8 tx_data[] = {
|
||||
(reg >> 8) & 0xff,
|
||||
reg & 0xff,
|
||||
};
|
||||
u8 rx_data[4];
|
||||
struct i2c_msg msgs[] = {
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = 0,
|
||||
.buf = tx_data,
|
||||
.len = ARRAY_SIZE(tx_data),
|
||||
},
|
||||
{
|
||||
.addr = client->addr,
|
||||
.flags = I2C_M_RD,
|
||||
.buf = rx_data,
|
||||
.len = ARRAY_SIZE(rx_data),
|
||||
},
|
||||
};
|
||||
|
||||
r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
|
||||
if (r < 0) {
|
||||
dev_err(&client->dev, "%s: reg 0x%04x error %d\n", __func__,
|
||||
reg, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (r < ARRAY_SIZE(msgs)) {
|
||||
dev_err(&client->dev, "%s: reg 0x%04x msgs %d\n", __func__,
|
||||
reg, r);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
*value = rx_data[0] << 24 | rx_data[1] << 16 |
|
||||
rx_data[2] << 8 | rx_data[3];
|
||||
|
||||
dev_dbg(&client->dev, "%s: reg 0x%04x value 0x%08x\n", __func__,
|
||||
reg, *value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state)
|
||||
{
|
||||
struct tc35876x_platform_data *pdata;
|
||||
|
||||
if (WARN(!tc35876x_client, "%s called before probe", __func__))
|
||||
return;
|
||||
|
||||
dev_dbg(&tc35876x_client->dev, "%s: state %d\n", __func__, state);
|
||||
|
||||
pdata = dev_get_platdata(&tc35876x_client->dev);
|
||||
|
||||
if (pdata->gpio_bridge_reset == -1)
|
||||
return;
|
||||
|
||||
if (state) {
|
||||
gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0);
|
||||
mdelay(10);
|
||||
} else {
|
||||
/* Pull MIPI Bridge reset pin to Low */
|
||||
gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0);
|
||||
mdelay(20);
|
||||
/* Pull MIPI Bridge reset pin to High */
|
||||
gpio_set_value_cansleep(pdata->gpio_bridge_reset, 1);
|
||||
mdelay(40);
|
||||
}
|
||||
}
|
||||
|
||||
void tc35876x_configure_lvds_bridge(struct drm_device *dev)
|
||||
{
|
||||
struct i2c_client *i2c = tc35876x_client;
|
||||
u32 ppi_lptxtimecnt;
|
||||
u32 txtagocnt;
|
||||
u32 txtasurecnt;
|
||||
u32 id;
|
||||
|
||||
if (WARN(!tc35876x_client, "%s called before probe", __func__))
|
||||
return;
|
||||
|
||||
dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
|
||||
|
||||
if (!tc35876x_regr(i2c, IDREG, &id))
|
||||
dev_info(&tc35876x_client->dev, "tc35876x ID 0x%08x\n", id);
|
||||
else
|
||||
dev_err(&tc35876x_client->dev, "Cannot read ID\n");
|
||||
|
||||
ppi_lptxtimecnt = 4;
|
||||
txtagocnt = (5 * ppi_lptxtimecnt - 3) / 4;
|
||||
txtasurecnt = 3 * ppi_lptxtimecnt / 2;
|
||||
tc35876x_regw(i2c, PPI_TX_RX_TA, FLD_VAL(txtagocnt, 26, 16) |
|
||||
FLD_VAL(txtasurecnt, 10, 0));
|
||||
tc35876x_regw(i2c, PPI_LPTXTIMECNT, FLD_VAL(ppi_lptxtimecnt, 10, 0));
|
||||
|
||||
tc35876x_regw(i2c, PPI_D0S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
|
||||
tc35876x_regw(i2c, PPI_D1S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
|
||||
tc35876x_regw(i2c, PPI_D2S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
|
||||
tc35876x_regw(i2c, PPI_D3S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
|
||||
|
||||
/* Enabling MIPI & PPI lanes, Enable 4 lanes */
|
||||
tc35876x_regw(i2c, PPI_LANEENABLE,
|
||||
BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
|
||||
tc35876x_regw(i2c, DSI_LANEENABLE,
|
||||
BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
|
||||
tc35876x_regw(i2c, PPI_STARTPPI, BIT(0));
|
||||
tc35876x_regw(i2c, DSI_STARTDSI, BIT(0));
|
||||
|
||||
/* Setting LVDS output frequency */
|
||||
tc35876x_regw(i2c, LVPHY0, FLD_VAL(1, 20, 16) |
|
||||
FLD_VAL(2, 15, 14) | FLD_VAL(6, 4, 0)); /* 0x00048006 */
|
||||
|
||||
/* Setting video panel control register,0x00000120 VTGen=ON ?!?!? */
|
||||
tc35876x_regw(i2c, VPCTRL, BIT(8) | BIT(5));
|
||||
|
||||
/* Horizontal back porch and horizontal pulse width. 0x00280028 */
|
||||
tc35876x_regw(i2c, HTIM1, FLD_VAL(40, 24, 16) | FLD_VAL(40, 8, 0));
|
||||
|
||||
/* Horizontal front porch and horizontal active video size. 0x00500500*/
|
||||
tc35876x_regw(i2c, HTIM2, FLD_VAL(80, 24, 16) | FLD_VAL(1280, 10, 0));
|
||||
|
||||
/* Vertical back porch and vertical sync pulse width. 0x000e000a */
|
||||
tc35876x_regw(i2c, VTIM1, FLD_VAL(14, 23, 16) | FLD_VAL(10, 7, 0));
|
||||
|
||||
/* Vertical front porch and vertical display size. 0x000e0320 */
|
||||
tc35876x_regw(i2c, VTIM2, FLD_VAL(14, 23, 16) | FLD_VAL(800, 10, 0));
|
||||
|
||||
/* Set above HTIM1, HTIM2, VTIM1, and VTIM2 at next VSYNC. */
|
||||
tc35876x_regw(i2c, VFUEN, BIT(0));
|
||||
|
||||
/* Soft reset LCD controller. */
|
||||
tc35876x_regw(i2c, SYSRST, BIT(2));
|
||||
|
||||
/* LVDS-TX input muxing */
|
||||
tc35876x_regw(i2c, LVMX0003,
|
||||
INPUT_MUX(INPUT_R5, INPUT_R4, INPUT_R3, INPUT_R2));
|
||||
tc35876x_regw(i2c, LVMX0407,
|
||||
INPUT_MUX(INPUT_G2, INPUT_R7, INPUT_R1, INPUT_R6));
|
||||
tc35876x_regw(i2c, LVMX0811,
|
||||
INPUT_MUX(INPUT_G1, INPUT_G0, INPUT_G4, INPUT_G3));
|
||||
tc35876x_regw(i2c, LVMX1215,
|
||||
INPUT_MUX(INPUT_B2, INPUT_G7, INPUT_G6, INPUT_G5));
|
||||
tc35876x_regw(i2c, LVMX1619,
|
||||
INPUT_MUX(INPUT_B4, INPUT_B3, INPUT_B1, INPUT_B0));
|
||||
tc35876x_regw(i2c, LVMX2023,
|
||||
INPUT_MUX(LOGIC_0, INPUT_B7, INPUT_B6, INPUT_B5));
|
||||
tc35876x_regw(i2c, LVMX2427,
|
||||
INPUT_MUX(INPUT_R0, INPUT_DE, INPUT_VSYNC, INPUT_HSYNC));
|
||||
|
||||
/* Enable LVDS transmitter. */
|
||||
tc35876x_regw(i2c, LVCFG, BIT(0));
|
||||
|
||||
/* Clear notifications. Don't write reserved bits. Was write 0xffffffff
|
||||
* to 0x0288, must be in error?! */
|
||||
tc35876x_regw(i2c, DSI_INTCLR, FLD_MASK(31, 30) | FLD_MASK(22, 0));
|
||||
}
|
||||
|
||||
#define GPIOPWMCTRL 0x38F
|
||||
#define PWM0CLKDIV0 0x62 /* low byte */
|
||||
#define PWM0CLKDIV1 0x61 /* high byte */
|
||||
|
||||
#define SYSTEMCLK 19200000UL /* 19.2 MHz */
|
||||
#define PWM_FREQUENCY 9600 /* Hz */
|
||||
|
||||
/* f = baseclk / (clkdiv + 1) => clkdiv = (baseclk - f) / f */
|
||||
static inline u16 calc_clkdiv(unsigned long baseclk, unsigned int f)
|
||||
{
|
||||
return (baseclk - f) / f;
|
||||
}
|
||||
|
||||
static void tc35876x_brightness_init(struct drm_device *dev)
|
||||
{
|
||||
int ret;
|
||||
u8 pwmctrl;
|
||||
u16 clkdiv;
|
||||
|
||||
/* Make sure the PWM reference is the 19.2 MHz system clock. Read first
|
||||
* instead of setting directly to catch potential conflicts between PWM
|
||||
* users. */
|
||||
ret = intel_scu_ipc_ioread8(GPIOPWMCTRL, &pwmctrl);
|
||||
if (ret || pwmctrl != 0x01) {
|
||||
if (ret)
|
||||
dev_err(&dev->pdev->dev, "GPIOPWMCTRL read failed\n");
|
||||
else
|
||||
dev_warn(&dev->pdev->dev, "GPIOPWMCTRL was not set to system clock (pwmctrl = 0x%02x)\n", pwmctrl);
|
||||
|
||||
ret = intel_scu_ipc_iowrite8(GPIOPWMCTRL, 0x01);
|
||||
if (ret)
|
||||
dev_err(&dev->pdev->dev, "GPIOPWMCTRL set failed\n");
|
||||
}
|
||||
|
||||
clkdiv = calc_clkdiv(SYSTEMCLK, PWM_FREQUENCY);
|
||||
|
||||
ret = intel_scu_ipc_iowrite8(PWM0CLKDIV1, (clkdiv >> 8) & 0xff);
|
||||
if (!ret)
|
||||
ret = intel_scu_ipc_iowrite8(PWM0CLKDIV0, clkdiv & 0xff);
|
||||
|
||||
if (ret)
|
||||
dev_err(&dev->pdev->dev, "PWM0CLKDIV set failed\n");
|
||||
else
|
||||
dev_dbg(&dev->pdev->dev, "PWM0CLKDIV set to 0x%04x (%d Hz)\n",
|
||||
clkdiv, PWM_FREQUENCY);
|
||||
}
|
||||
|
||||
#define PWM0DUTYCYCLE 0x67
|
||||
|
||||
void tc35876x_brightness_control(struct drm_device *dev, int level)
|
||||
{
|
||||
int ret;
|
||||
u8 duty_val;
|
||||
u8 panel_duty_val;
|
||||
|
||||
level = clamp(level, 0, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
|
||||
|
||||
/* PWM duty cycle 0x00...0x63 corresponds to 0...99% */
|
||||
duty_val = level * 0x63 / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL;
|
||||
|
||||
/* I won't pretend to understand this formula. The panel spec is quite
|
||||
* bad engrish.
|
||||
*/
|
||||
panel_duty_val = (2 * level - 100) * 0xA9 /
|
||||
MDFLD_DSI_BRIGHTNESS_MAX_LEVEL + 0x56;
|
||||
|
||||
ret = intel_scu_ipc_iowrite8(PWM0DUTYCYCLE, duty_val);
|
||||
if (ret)
|
||||
dev_err(&tc35876x_client->dev, "%s: ipc write fail\n",
|
||||
__func__);
|
||||
|
||||
if (cmi_lcd_i2c_client) {
|
||||
ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
|
||||
PANEL_PWM_MAX, panel_duty_val);
|
||||
if (ret < 0)
|
||||
dev_err(&cmi_lcd_i2c_client->dev, "%s: i2c write failed\n",
|
||||
__func__);
|
||||
}
|
||||
}
|
||||
|
||||
void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev)
|
||||
{
|
||||
struct tc35876x_platform_data *pdata;
|
||||
|
||||
if (WARN(!tc35876x_client, "%s called before probe", __func__))
|
||||
return;
|
||||
|
||||
dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
|
||||
|
||||
pdata = dev_get_platdata(&tc35876x_client->dev);
|
||||
|
||||
if (pdata->gpio_panel_bl_en != -1)
|
||||
gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 0);
|
||||
|
||||
if (pdata->gpio_panel_vadd != -1)
|
||||
gpio_set_value_cansleep(pdata->gpio_panel_vadd, 0);
|
||||
}
|
||||
|
||||
void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev)
|
||||
{
|
||||
struct tc35876x_platform_data *pdata;
|
||||
struct drm_psb_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (WARN(!tc35876x_client, "%s called before probe", __func__))
|
||||
return;
|
||||
|
||||
dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
|
||||
|
||||
pdata = dev_get_platdata(&tc35876x_client->dev);
|
||||
|
||||
if (pdata->gpio_panel_vadd != -1) {
|
||||
gpio_set_value_cansleep(pdata->gpio_panel_vadd, 1);
|
||||
msleep(260);
|
||||
}
|
||||
|
||||
if (cmi_lcd_i2c_client) {
|
||||
int ret;
|
||||
dev_dbg(&cmi_lcd_i2c_client->dev, "setting TCON\n");
|
||||
/* Bit 4 is average_saving. Setting it to 1, the brightness is
|
||||
* referenced to the average of the frame content. 0 means
|
||||
* reference to the maximum of frame contents. Bits 3:0 are
|
||||
* allow_distort. When set to a nonzero value, all color values
|
||||
* between 255-allow_distort*2 and 255 are mapped to the
|
||||
* 255-allow_distort*2 value.
|
||||
*/
|
||||
ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
|
||||
PANEL_ALLOW_DISTORT, 0x10);
|
||||
if (ret < 0)
|
||||
dev_err(&cmi_lcd_i2c_client->dev,
|
||||
"i2c write failed (%d)\n", ret);
|
||||
ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
|
||||
PANEL_BYPASS_PWMI, 0);
|
||||
if (ret < 0)
|
||||
dev_err(&cmi_lcd_i2c_client->dev,
|
||||
"i2c write failed (%d)\n", ret);
|
||||
/* Set minimum brightness value - this is tunable */
|
||||
ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
|
||||
PANEL_PWM_MIN, 0x35);
|
||||
if (ret < 0)
|
||||
dev_err(&cmi_lcd_i2c_client->dev,
|
||||
"i2c write failed (%d)\n", ret);
|
||||
}
|
||||
|
||||
if (pdata->gpio_panel_bl_en != -1)
|
||||
gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 1);
|
||||
|
||||
tc35876x_brightness_control(dev, dev_priv->brightness_adjusted);
|
||||
}
|
||||
|
||||
static struct drm_display_mode *tc35876x_get_config_mode(struct drm_device *dev)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
dev_dbg(&dev->pdev->dev, "%s\n", __func__);
|
||||
|
||||
mode = kzalloc(sizeof(*mode), GFP_KERNEL);
|
||||
if (!mode)
|
||||
return NULL;
|
||||
|
||||
/* FIXME: do this properly. */
|
||||
mode->hdisplay = 1280;
|
||||
mode->vdisplay = 800;
|
||||
mode->hsync_start = 1360;
|
||||
mode->hsync_end = 1400;
|
||||
mode->htotal = 1440;
|
||||
mode->vsync_start = 814;
|
||||
mode->vsync_end = 824;
|
||||
mode->vtotal = 838;
|
||||
mode->clock = 33324 << 1;
|
||||
|
||||
dev_info(&dev->pdev->dev, "hdisplay(w) = %d\n", mode->hdisplay);
|
||||
dev_info(&dev->pdev->dev, "vdisplay(h) = %d\n", mode->vdisplay);
|
||||
dev_info(&dev->pdev->dev, "HSS = %d\n", mode->hsync_start);
|
||||
dev_info(&dev->pdev->dev, "HSE = %d\n", mode->hsync_end);
|
||||
dev_info(&dev->pdev->dev, "htotal = %d\n", mode->htotal);
|
||||
dev_info(&dev->pdev->dev, "VSS = %d\n", mode->vsync_start);
|
||||
dev_info(&dev->pdev->dev, "VSE = %d\n", mode->vsync_end);
|
||||
dev_info(&dev->pdev->dev, "vtotal = %d\n", mode->vtotal);
|
||||
dev_info(&dev->pdev->dev, "clock = %d\n", mode->clock);
|
||||
|
||||
drm_mode_set_name(mode);
|
||||
drm_mode_set_crtcinfo(mode, 0);
|
||||
|
||||
mode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
/* DV1 Active area 216.96 x 135.6 mm */
|
||||
#define DV1_PANEL_WIDTH 217
|
||||
#define DV1_PANEL_HEIGHT 136
|
||||
|
||||
static int tc35876x_get_panel_info(struct drm_device *dev, int pipe,
|
||||
struct panel_info *pi)
|
||||
{
|
||||
if (!dev || !pi)
|
||||
return -EINVAL;
|
||||
|
||||
pi->width_mm = DV1_PANEL_WIDTH;
|
||||
pi->height_mm = DV1_PANEL_HEIGHT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc35876x_bridge_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct tc35876x_platform_data *pdata;
|
||||
|
||||
dev_info(&client->dev, "%s\n", __func__);
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
||||
dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
|
||||
__func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pdata = dev_get_platdata(&client->dev);
|
||||
if (!pdata) {
|
||||
dev_err(&client->dev, "%s: no platform data\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (pdata->gpio_bridge_reset != -1) {
|
||||
gpio_request(pdata->gpio_bridge_reset, "tc35876x bridge reset");
|
||||
gpio_direction_output(pdata->gpio_bridge_reset, 0);
|
||||
}
|
||||
|
||||
if (pdata->gpio_panel_bl_en != -1) {
|
||||
gpio_request(pdata->gpio_panel_bl_en, "tc35876x panel bl en");
|
||||
gpio_direction_output(pdata->gpio_panel_bl_en, 0);
|
||||
}
|
||||
|
||||
if (pdata->gpio_panel_vadd != -1) {
|
||||
gpio_request(pdata->gpio_panel_vadd, "tc35876x panel vadd");
|
||||
gpio_direction_output(pdata->gpio_panel_vadd, 0);
|
||||
}
|
||||
|
||||
tc35876x_client = client;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc35876x_bridge_remove(struct i2c_client *client)
|
||||
{
|
||||
struct tc35876x_platform_data *pdata = dev_get_platdata(&client->dev);
|
||||
|
||||
dev_dbg(&client->dev, "%s\n", __func__);
|
||||
|
||||
if (pdata->gpio_bridge_reset != -1)
|
||||
gpio_free(pdata->gpio_bridge_reset);
|
||||
|
||||
if (pdata->gpio_panel_bl_en != -1)
|
||||
gpio_free(pdata->gpio_panel_bl_en);
|
||||
|
||||
if (pdata->gpio_panel_vadd != -1)
|
||||
gpio_free(pdata->gpio_panel_vadd);
|
||||
|
||||
tc35876x_client = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tc35876x_bridge_id[] = {
|
||||
{ "i2c_disp_brig", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tc35876x_bridge_id);
|
||||
|
||||
static struct i2c_driver tc35876x_bridge_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "i2c_disp_brig",
|
||||
},
|
||||
.id_table = tc35876x_bridge_id,
|
||||
.probe = tc35876x_bridge_probe,
|
||||
.remove = __devexit_p(tc35876x_bridge_remove),
|
||||
};
|
||||
|
||||
/* LCD panel I2C */
|
||||
static int cmi_lcd_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
dev_info(&client->dev, "%s\n", __func__);
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
||||
dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
|
||||
__func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
cmi_lcd_i2c_client = client;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmi_lcd_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
dev_dbg(&client->dev, "%s\n", __func__);
|
||||
|
||||
cmi_lcd_i2c_client = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id cmi_lcd_i2c_id[] = {
|
||||
{ "cmi-lcd", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cmi_lcd_i2c_id);
|
||||
|
||||
static struct i2c_driver cmi_lcd_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "cmi-lcd",
|
||||
},
|
||||
.id_table = cmi_lcd_i2c_id,
|
||||
.probe = cmi_lcd_i2c_probe,
|
||||
.remove = __devexit_p(cmi_lcd_i2c_remove),
|
||||
};
|
||||
|
||||
/* HACK to create I2C device while it's not created by platform code */
|
||||
#define CMI_LCD_I2C_ADAPTER 2
|
||||
#define CMI_LCD_I2C_ADDR 0x60
|
||||
|
||||
static int cmi_lcd_hack_create_device(void)
|
||||
{
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_client *client;
|
||||
struct i2c_board_info info = {
|
||||
.type = "cmi-lcd",
|
||||
.addr = CMI_LCD_I2C_ADDR,
|
||||
};
|
||||
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
adapter = i2c_get_adapter(CMI_LCD_I2C_ADAPTER);
|
||||
if (!adapter) {
|
||||
pr_err("%s: i2c_get_adapter(%d) failed\n", __func__,
|
||||
CMI_LCD_I2C_ADAPTER);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
client = i2c_new_device(adapter, &info);
|
||||
if (!client) {
|
||||
pr_err("%s: i2c_new_device() failed\n", __func__);
|
||||
i2c_put_adapter(adapter);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_encoder_helper_funcs tc35876x_encoder_helper_funcs = {
|
||||
.dpms = mdfld_dsi_dpi_dpms,
|
||||
.mode_fixup = mdfld_dsi_dpi_mode_fixup,
|
||||
.prepare = mdfld_dsi_dpi_prepare,
|
||||
.mode_set = mdfld_dsi_dpi_mode_set,
|
||||
.commit = mdfld_dsi_dpi_commit,
|
||||
};
|
||||
|
||||
static const struct drm_encoder_funcs tc35876x_encoder_funcs = {
|
||||
.destroy = drm_encoder_cleanup,
|
||||
};
|
||||
|
||||
const struct panel_funcs mdfld_tc35876x_funcs = {
|
||||
.encoder_funcs = &tc35876x_encoder_funcs,
|
||||
.encoder_helper_funcs = &tc35876x_encoder_helper_funcs,
|
||||
.get_config_mode = tc35876x_get_config_mode,
|
||||
.get_panel_info = tc35876x_get_panel_info,
|
||||
};
|
||||
|
||||
void tc35876x_init(struct drm_device *dev)
|
||||
{
|
||||
int r;
|
||||
|
||||
dev_dbg(&dev->pdev->dev, "%s\n", __func__);
|
||||
|
||||
cmi_lcd_hack_create_device();
|
||||
|
||||
r = i2c_add_driver(&cmi_lcd_i2c_driver);
|
||||
if (r < 0)
|
||||
dev_err(&dev->pdev->dev,
|
||||
"%s: i2c_add_driver() for %s failed (%d)\n",
|
||||
__func__, cmi_lcd_i2c_driver.driver.name, r);
|
||||
|
||||
r = i2c_add_driver(&tc35876x_bridge_i2c_driver);
|
||||
if (r < 0)
|
||||
dev_err(&dev->pdev->dev,
|
||||
"%s: i2c_add_driver() for %s failed (%d)\n",
|
||||
__func__, tc35876x_bridge_i2c_driver.driver.name, r);
|
||||
|
||||
tc35876x_brightness_init(dev);
|
||||
}
|
||||
|
||||
void tc35876x_exit(void)
|
||||
{
|
||||
pr_debug("%s\n", __func__);
|
||||
|
||||
i2c_del_driver(&tc35876x_bridge_i2c_driver);
|
||||
|
||||
if (cmi_lcd_i2c_client)
|
||||
i2c_del_driver(&cmi_lcd_i2c_driver);
|
||||
}
|
38
drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h
Normal file
38
drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright © 2011 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MDFLD_DSI_LVDS_BRIDGE_H__
|
||||
#define __MDFLD_DSI_LVDS_BRIDGE_H__
|
||||
|
||||
void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state);
|
||||
void tc35876x_configure_lvds_bridge(struct drm_device *dev);
|
||||
void tc35876x_brightness_control(struct drm_device *dev, int level);
|
||||
void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev);
|
||||
void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev);
|
||||
void tc35876x_init(struct drm_device *dev);
|
||||
void tc35876x_exit(void);
|
||||
|
||||
extern const struct panel_funcs mdfld_tc35876x_funcs;
|
||||
|
||||
#endif /*__MDFLD_DSI_LVDS_BRIDGE_H__*/
|
@ -83,9 +83,9 @@ struct drm_psb_gem_mmap {
|
||||
#define DRM_GMA_GAMMA 0x04 /* Set gamma table */
|
||||
#define DRM_GMA_ADB 0x05 /* Get backlight */
|
||||
#define DRM_GMA_DPST_BL 0x06 /* Set backlight */
|
||||
#define DRM_GMA_GET_PIPE_FROM_CRTC_ID 0x1 /* CRTC to physical pipe# */
|
||||
#define DRM_GMA_MODE_OPERATION 0x07 /* Mode validation/DC set */
|
||||
#define PSB_MODE_OPERATION_MODE_VALID 0x01
|
||||
#define DRM_GMA_GET_PIPE_FROM_CRTC_ID 0x08 /* CRTC to physical pipe# */
|
||||
|
||||
|
||||
#endif
|
||||
|
11
include/linux/i2c/tc35876x.h
Normal file
11
include/linux/i2c/tc35876x.h
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
#ifndef _TC35876X_H
|
||||
#define _TC35876X_H
|
||||
|
||||
struct tc35876x_platform_data {
|
||||
int gpio_bridge_reset;
|
||||
int gpio_panel_bl_en;
|
||||
int gpio_panel_vadd;
|
||||
};
|
||||
|
||||
#endif /* _TC35876X_H */
|
Loading…
x
Reference in New Issue
Block a user