18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/************************************************************************** 38c2ecf20Sopenharmony_ci * Copyright (c) 2011, Intel Corporation. 48c2ecf20Sopenharmony_ci * All Rights Reserved. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci **************************************************************************/ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/delay.h> 98c2ecf20Sopenharmony_ci#include <linux/gpio/machine.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <asm/intel_scu_ipc.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include "mdfld_dsi_output.h" 148c2ecf20Sopenharmony_ci#include "mdfld_output.h" 158c2ecf20Sopenharmony_ci#include "mid_bios.h" 168c2ecf20Sopenharmony_ci#include "psb_drv.h" 178c2ecf20Sopenharmony_ci#include "tc35876x-dsi-lvds.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF 228c2ecf20Sopenharmony_ci#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ 238c2ecf20Sopenharmony_ci#define BLC_PWM_FREQ_CALC_CONSTANT 32 248c2ecf20Sopenharmony_ci#define MHz 1000000 258c2ecf20Sopenharmony_ci#define BRIGHTNESS_MIN_LEVEL 1 268c2ecf20Sopenharmony_ci#define BRIGHTNESS_MAX_LEVEL 100 278c2ecf20Sopenharmony_ci#define BRIGHTNESS_MASK 0xFF 288c2ecf20Sopenharmony_ci#define BLC_POLARITY_NORMAL 0 298c2ecf20Sopenharmony_ci#define BLC_POLARITY_INVERSE 1 308c2ecf20Sopenharmony_ci#define BLC_ADJUSTMENT_MAX 100 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#define MDFLD_BLC_PWM_PRECISION_FACTOR 10 338c2ecf20Sopenharmony_ci#define MDFLD_BLC_MAX_PWM_REG_FREQ 0xFFFE 348c2ecf20Sopenharmony_ci#define MDFLD_BLC_MIN_PWM_REG_FREQ 0x2 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define MDFLD_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) 378c2ecf20Sopenharmony_ci#define MDFLD_BACKLIGHT_PWM_CTL_SHIFT (16) 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic struct backlight_device *mdfld_backlight_device; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ciint mdfld_set_brightness(struct backlight_device *bd) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci struct drm_device *dev = 448c2ecf20Sopenharmony_ci (struct drm_device *)bl_get_data(mdfld_backlight_device); 458c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 468c2ecf20Sopenharmony_ci int level = bd->props.brightness; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci DRM_DEBUG_DRIVER("backlight level set to %d\n", level); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci /* Perform value bounds checking */ 518c2ecf20Sopenharmony_ci if (level < BRIGHTNESS_MIN_LEVEL) 528c2ecf20Sopenharmony_ci level = BRIGHTNESS_MIN_LEVEL; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci if (gma_power_begin(dev, false)) { 558c2ecf20Sopenharmony_ci u32 adjusted_level = 0; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci /* 588c2ecf20Sopenharmony_ci * Adjust the backlight level with the percent in 598c2ecf20Sopenharmony_ci * dev_priv->blc_adj2 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_ci adjusted_level = level * dev_priv->blc_adj2; 628c2ecf20Sopenharmony_ci adjusted_level = adjusted_level / BLC_ADJUSTMENT_MAX; 638c2ecf20Sopenharmony_ci dev_priv->brightness_adjusted = adjusted_level; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci if (mdfld_get_panel_type(dev, 0) == TC35876X) { 668c2ecf20Sopenharmony_ci if (dev_priv->dpi_panel_on[0] || 678c2ecf20Sopenharmony_ci dev_priv->dpi_panel_on[2]) 688c2ecf20Sopenharmony_ci tc35876x_brightness_control(dev, 698c2ecf20Sopenharmony_ci dev_priv->brightness_adjusted); 708c2ecf20Sopenharmony_ci } else { 718c2ecf20Sopenharmony_ci if (dev_priv->dpi_panel_on[0]) 728c2ecf20Sopenharmony_ci mdfld_dsi_brightness_control(dev, 0, 738c2ecf20Sopenharmony_ci dev_priv->brightness_adjusted); 748c2ecf20Sopenharmony_ci } 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci if (dev_priv->dpi_panel_on[2]) 778c2ecf20Sopenharmony_ci mdfld_dsi_brightness_control(dev, 2, 788c2ecf20Sopenharmony_ci dev_priv->brightness_adjusted); 798c2ecf20Sopenharmony_ci gma_power_end(dev); 808c2ecf20Sopenharmony_ci } 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci /* cache the brightness for later use */ 838c2ecf20Sopenharmony_ci dev_priv->brightness = level; 848c2ecf20Sopenharmony_ci return 0; 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistatic int mdfld_get_brightness(struct backlight_device *bd) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci struct drm_device *dev = 908c2ecf20Sopenharmony_ci (struct drm_device *)bl_get_data(mdfld_backlight_device); 918c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci DRM_DEBUG_DRIVER("brightness = 0x%x \n", dev_priv->brightness); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci /* return locally cached var instead of HW read (due to DPST etc.) */ 968c2ecf20Sopenharmony_ci return dev_priv->brightness; 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic const struct backlight_ops mdfld_ops = { 1008c2ecf20Sopenharmony_ci .get_brightness = mdfld_get_brightness, 1018c2ecf20Sopenharmony_ci .update_status = mdfld_set_brightness, 1028c2ecf20Sopenharmony_ci}; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic int device_backlight_init(struct drm_device *dev) 1058c2ecf20Sopenharmony_ci{ 1068c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = (struct drm_psb_private *) 1078c2ecf20Sopenharmony_ci dev->dev_private; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX; 1108c2ecf20Sopenharmony_ci dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci return 0; 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic int mdfld_backlight_init(struct drm_device *dev) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci struct backlight_properties props; 1188c2ecf20Sopenharmony_ci int ret = 0; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci memset(&props, 0, sizeof(struct backlight_properties)); 1218c2ecf20Sopenharmony_ci props.max_brightness = BRIGHTNESS_MAX_LEVEL; 1228c2ecf20Sopenharmony_ci props.type = BACKLIGHT_PLATFORM; 1238c2ecf20Sopenharmony_ci mdfld_backlight_device = backlight_device_register("mdfld-bl", 1248c2ecf20Sopenharmony_ci NULL, (void *)dev, &mdfld_ops, &props); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci if (IS_ERR(mdfld_backlight_device)) 1278c2ecf20Sopenharmony_ci return PTR_ERR(mdfld_backlight_device); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci ret = device_backlight_init(dev); 1308c2ecf20Sopenharmony_ci if (ret) 1318c2ecf20Sopenharmony_ci return ret; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci mdfld_backlight_device->props.brightness = BRIGHTNESS_MAX_LEVEL; 1348c2ecf20Sopenharmony_ci mdfld_backlight_device->props.max_brightness = BRIGHTNESS_MAX_LEVEL; 1358c2ecf20Sopenharmony_ci backlight_update_status(mdfld_backlight_device); 1368c2ecf20Sopenharmony_ci return 0; 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci#endif 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistruct backlight_device *mdfld_get_backlight_device(void) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE 1438c2ecf20Sopenharmony_ci return mdfld_backlight_device; 1448c2ecf20Sopenharmony_ci#else 1458c2ecf20Sopenharmony_ci return NULL; 1468c2ecf20Sopenharmony_ci#endif 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci/* 1508c2ecf20Sopenharmony_ci * mdfld_save_display_registers 1518c2ecf20Sopenharmony_ci * 1528c2ecf20Sopenharmony_ci * Description: We are going to suspend so save current display 1538c2ecf20Sopenharmony_ci * register state. 1548c2ecf20Sopenharmony_ci * 1558c2ecf20Sopenharmony_ci * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio 1568c2ecf20Sopenharmony_ci */ 1578c2ecf20Sopenharmony_cistatic int mdfld_save_display_registers(struct drm_device *dev, int pipenum) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 1608c2ecf20Sopenharmony_ci struct medfield_state *regs = &dev_priv->regs.mdfld; 1618c2ecf20Sopenharmony_ci struct psb_pipe *pipe = &dev_priv->regs.pipe[pipenum]; 1628c2ecf20Sopenharmony_ci const struct psb_offset *map = &dev_priv->regmap[pipenum]; 1638c2ecf20Sopenharmony_ci int i; 1648c2ecf20Sopenharmony_ci u32 *mipi_val; 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci /* register */ 1678c2ecf20Sopenharmony_ci u32 mipi_reg = MIPI; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci switch (pipenum) { 1708c2ecf20Sopenharmony_ci case 0: 1718c2ecf20Sopenharmony_ci mipi_val = ®s->saveMIPI; 1728c2ecf20Sopenharmony_ci break; 1738c2ecf20Sopenharmony_ci case 1: 1748c2ecf20Sopenharmony_ci mipi_val = ®s->saveMIPI; 1758c2ecf20Sopenharmony_ci break; 1768c2ecf20Sopenharmony_ci case 2: 1778c2ecf20Sopenharmony_ci /* register */ 1788c2ecf20Sopenharmony_ci mipi_reg = MIPI_C; 1798c2ecf20Sopenharmony_ci /* pointer to values */ 1808c2ecf20Sopenharmony_ci mipi_val = ®s->saveMIPI_C; 1818c2ecf20Sopenharmony_ci break; 1828c2ecf20Sopenharmony_ci default: 1838c2ecf20Sopenharmony_ci DRM_ERROR("%s, invalid pipe number.\n", __func__); 1848c2ecf20Sopenharmony_ci return -EINVAL; 1858c2ecf20Sopenharmony_ci } 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci /* Pipe & plane A info */ 1888c2ecf20Sopenharmony_ci pipe->dpll = PSB_RVDC32(map->dpll); 1898c2ecf20Sopenharmony_ci pipe->fp0 = PSB_RVDC32(map->fp0); 1908c2ecf20Sopenharmony_ci pipe->conf = PSB_RVDC32(map->conf); 1918c2ecf20Sopenharmony_ci pipe->htotal = PSB_RVDC32(map->htotal); 1928c2ecf20Sopenharmony_ci pipe->hblank = PSB_RVDC32(map->hblank); 1938c2ecf20Sopenharmony_ci pipe->hsync = PSB_RVDC32(map->hsync); 1948c2ecf20Sopenharmony_ci pipe->vtotal = PSB_RVDC32(map->vtotal); 1958c2ecf20Sopenharmony_ci pipe->vblank = PSB_RVDC32(map->vblank); 1968c2ecf20Sopenharmony_ci pipe->vsync = PSB_RVDC32(map->vsync); 1978c2ecf20Sopenharmony_ci pipe->src = PSB_RVDC32(map->src); 1988c2ecf20Sopenharmony_ci pipe->stride = PSB_RVDC32(map->stride); 1998c2ecf20Sopenharmony_ci pipe->linoff = PSB_RVDC32(map->linoff); 2008c2ecf20Sopenharmony_ci pipe->tileoff = PSB_RVDC32(map->tileoff); 2018c2ecf20Sopenharmony_ci pipe->size = PSB_RVDC32(map->size); 2028c2ecf20Sopenharmony_ci pipe->pos = PSB_RVDC32(map->pos); 2038c2ecf20Sopenharmony_ci pipe->surf = PSB_RVDC32(map->surf); 2048c2ecf20Sopenharmony_ci pipe->cntr = PSB_RVDC32(map->cntr); 2058c2ecf20Sopenharmony_ci pipe->status = PSB_RVDC32(map->status); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci /*save palette (gamma) */ 2088c2ecf20Sopenharmony_ci for (i = 0; i < 256; i++) 2098c2ecf20Sopenharmony_ci pipe->palette[i] = PSB_RVDC32(map->palette + (i << 2)); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci if (pipenum == 1) { 2128c2ecf20Sopenharmony_ci regs->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL); 2138c2ecf20Sopenharmony_ci regs->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS); 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci regs->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL); 2168c2ecf20Sopenharmony_ci regs->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL); 2178c2ecf20Sopenharmony_ci return 0; 2188c2ecf20Sopenharmony_ci } 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci *mipi_val = PSB_RVDC32(mipi_reg); 2218c2ecf20Sopenharmony_ci return 0; 2228c2ecf20Sopenharmony_ci} 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci/* 2258c2ecf20Sopenharmony_ci * mdfld_restore_display_registers 2268c2ecf20Sopenharmony_ci * 2278c2ecf20Sopenharmony_ci * Description: We are going to resume so restore display register state. 2288c2ecf20Sopenharmony_ci * 2298c2ecf20Sopenharmony_ci * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio 2308c2ecf20Sopenharmony_ci */ 2318c2ecf20Sopenharmony_cistatic int mdfld_restore_display_registers(struct drm_device *dev, int pipenum) 2328c2ecf20Sopenharmony_ci{ 2338c2ecf20Sopenharmony_ci /* To get panel out of ULPS mode. */ 2348c2ecf20Sopenharmony_ci u32 temp = 0; 2358c2ecf20Sopenharmony_ci u32 device_ready_reg = DEVICE_READY_REG; 2368c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 2378c2ecf20Sopenharmony_ci struct mdfld_dsi_config *dsi_config = NULL; 2388c2ecf20Sopenharmony_ci struct medfield_state *regs = &dev_priv->regs.mdfld; 2398c2ecf20Sopenharmony_ci struct psb_pipe *pipe = &dev_priv->regs.pipe[pipenum]; 2408c2ecf20Sopenharmony_ci const struct psb_offset *map = &dev_priv->regmap[pipenum]; 2418c2ecf20Sopenharmony_ci u32 i; 2428c2ecf20Sopenharmony_ci u32 dpll; 2438c2ecf20Sopenharmony_ci u32 timeout = 0; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci /* register */ 2468c2ecf20Sopenharmony_ci u32 mipi_reg = MIPI; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci /* values */ 2498c2ecf20Sopenharmony_ci u32 dpll_val = pipe->dpll; 2508c2ecf20Sopenharmony_ci u32 mipi_val = regs->saveMIPI; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci switch (pipenum) { 2538c2ecf20Sopenharmony_ci case 0: 2548c2ecf20Sopenharmony_ci dpll_val &= ~DPLL_VCO_ENABLE; 2558c2ecf20Sopenharmony_ci dsi_config = dev_priv->dsi_configs[0]; 2568c2ecf20Sopenharmony_ci break; 2578c2ecf20Sopenharmony_ci case 1: 2588c2ecf20Sopenharmony_ci dpll_val &= ~DPLL_VCO_ENABLE; 2598c2ecf20Sopenharmony_ci break; 2608c2ecf20Sopenharmony_ci case 2: 2618c2ecf20Sopenharmony_ci mipi_reg = MIPI_C; 2628c2ecf20Sopenharmony_ci mipi_val = regs->saveMIPI_C; 2638c2ecf20Sopenharmony_ci dsi_config = dev_priv->dsi_configs[1]; 2648c2ecf20Sopenharmony_ci break; 2658c2ecf20Sopenharmony_ci default: 2668c2ecf20Sopenharmony_ci DRM_ERROR("%s, invalid pipe number.\n", __func__); 2678c2ecf20Sopenharmony_ci return -EINVAL; 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci /*make sure VGA plane is off. it initializes to on after reset!*/ 2718c2ecf20Sopenharmony_ci PSB_WVDC32(0x80000000, VGACNTRL); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci if (pipenum == 1) { 2748c2ecf20Sopenharmony_ci PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, map->dpll); 2758c2ecf20Sopenharmony_ci PSB_RVDC32(map->dpll); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->fp0, map->fp0); 2788c2ecf20Sopenharmony_ci } else { 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci dpll = PSB_RVDC32(map->dpll); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci if (!(dpll & DPLL_VCO_ENABLE)) { 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci /* When ungating power of DPLL, needs to wait 0.5us 2858c2ecf20Sopenharmony_ci before enable the VCO */ 2868c2ecf20Sopenharmony_ci if (dpll & MDFLD_PWR_GATE_EN) { 2878c2ecf20Sopenharmony_ci dpll &= ~MDFLD_PWR_GATE_EN; 2888c2ecf20Sopenharmony_ci PSB_WVDC32(dpll, map->dpll); 2898c2ecf20Sopenharmony_ci /* FIXME_MDFLD PO - change 500 to 1 after PO */ 2908c2ecf20Sopenharmony_ci udelay(500); 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->fp0, map->fp0); 2948c2ecf20Sopenharmony_ci PSB_WVDC32(dpll_val, map->dpll); 2958c2ecf20Sopenharmony_ci /* FIXME_MDFLD PO - change 500 to 1 after PO */ 2968c2ecf20Sopenharmony_ci udelay(500); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci dpll_val |= DPLL_VCO_ENABLE; 2998c2ecf20Sopenharmony_ci PSB_WVDC32(dpll_val, map->dpll); 3008c2ecf20Sopenharmony_ci PSB_RVDC32(map->dpll); 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci /* wait for DSI PLL to lock */ 3038c2ecf20Sopenharmony_ci while (timeout < 20000 && 3048c2ecf20Sopenharmony_ci !(PSB_RVDC32(map->conf) & PIPECONF_DSIPLL_LOCK)) { 3058c2ecf20Sopenharmony_ci udelay(150); 3068c2ecf20Sopenharmony_ci timeout++; 3078c2ecf20Sopenharmony_ci } 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci if (timeout == 20000) { 3108c2ecf20Sopenharmony_ci DRM_ERROR("%s, can't lock DSIPLL.\n", 3118c2ecf20Sopenharmony_ci __func__); 3128c2ecf20Sopenharmony_ci return -EINVAL; 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci /* Restore mode */ 3178c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->htotal, map->htotal); 3188c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->hblank, map->hblank); 3198c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->hsync, map->hsync); 3208c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->vtotal, map->vtotal); 3218c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->vblank, map->vblank); 3228c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->vsync, map->vsync); 3238c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->src, map->src); 3248c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->status, map->status); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci /*set up the plane*/ 3278c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->stride, map->stride); 3288c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->linoff, map->linoff); 3298c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->tileoff, map->tileoff); 3308c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->size, map->size); 3318c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->pos, map->pos); 3328c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->surf, map->surf); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci if (pipenum == 1) { 3358c2ecf20Sopenharmony_ci /* restore palette (gamma) */ 3368c2ecf20Sopenharmony_ci /* udelay(50000); */ 3378c2ecf20Sopenharmony_ci for (i = 0; i < 256; i++) 3388c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->palette[i], map->palette + (i << 2)); 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci PSB_WVDC32(regs->savePFIT_CONTROL, PFIT_CONTROL); 3418c2ecf20Sopenharmony_ci PSB_WVDC32(regs->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci /*TODO: resume HDMI port */ 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci /*TODO: resume pipe*/ 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci /*enable the plane*/ 3488c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->cntr & ~DISPLAY_PLANE_ENABLE, map->cntr); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci return 0; 3518c2ecf20Sopenharmony_ci } 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci /*set up pipe related registers*/ 3548c2ecf20Sopenharmony_ci PSB_WVDC32(mipi_val, mipi_reg); 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci /*setup MIPI adapter + MIPI IP registers*/ 3578c2ecf20Sopenharmony_ci if (dsi_config) 3588c2ecf20Sopenharmony_ci mdfld_dsi_controller_init(dsi_config, pipenum); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_ci if (in_atomic() || in_interrupt()) 3618c2ecf20Sopenharmony_ci mdelay(20); 3628c2ecf20Sopenharmony_ci else 3638c2ecf20Sopenharmony_ci msleep(20); 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci /*enable the plane*/ 3668c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->cntr, map->cntr); 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci if (in_atomic() || in_interrupt()) 3698c2ecf20Sopenharmony_ci mdelay(20); 3708c2ecf20Sopenharmony_ci else 3718c2ecf20Sopenharmony_ci msleep(20); 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci /* LP Hold Release */ 3748c2ecf20Sopenharmony_ci temp = REG_READ(mipi_reg); 3758c2ecf20Sopenharmony_ci temp |= LP_OUTPUT_HOLD_RELEASE; 3768c2ecf20Sopenharmony_ci REG_WRITE(mipi_reg, temp); 3778c2ecf20Sopenharmony_ci mdelay(1); 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci /* Set DSI host to exit from Utra Low Power State */ 3818c2ecf20Sopenharmony_ci temp = REG_READ(device_ready_reg); 3828c2ecf20Sopenharmony_ci temp &= ~ULPS_MASK; 3838c2ecf20Sopenharmony_ci temp |= 0x3; 3848c2ecf20Sopenharmony_ci temp |= EXIT_ULPS_DEV_READY; 3858c2ecf20Sopenharmony_ci REG_WRITE(device_ready_reg, temp); 3868c2ecf20Sopenharmony_ci mdelay(1); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci temp = REG_READ(device_ready_reg); 3898c2ecf20Sopenharmony_ci temp &= ~ULPS_MASK; 3908c2ecf20Sopenharmony_ci temp |= EXITING_ULPS; 3918c2ecf20Sopenharmony_ci REG_WRITE(device_ready_reg, temp); 3928c2ecf20Sopenharmony_ci mdelay(1); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci /*enable the pipe*/ 3958c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->conf, map->conf); 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci /* restore palette (gamma) */ 3988c2ecf20Sopenharmony_ci /* udelay(50000); */ 3998c2ecf20Sopenharmony_ci for (i = 0; i < 256; i++) 4008c2ecf20Sopenharmony_ci PSB_WVDC32(pipe->palette[i], map->palette + (i << 2)); 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci return 0; 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_cistatic int mdfld_save_registers(struct drm_device *dev) 4068c2ecf20Sopenharmony_ci{ 4078c2ecf20Sopenharmony_ci /* mdfld_save_cursor_overlay_registers(dev); */ 4088c2ecf20Sopenharmony_ci mdfld_save_display_registers(dev, 0); 4098c2ecf20Sopenharmony_ci mdfld_save_display_registers(dev, 2); 4108c2ecf20Sopenharmony_ci mdfld_disable_crtc(dev, 0); 4118c2ecf20Sopenharmony_ci mdfld_disable_crtc(dev, 2); 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci return 0; 4148c2ecf20Sopenharmony_ci} 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_cistatic int mdfld_restore_registers(struct drm_device *dev) 4178c2ecf20Sopenharmony_ci{ 4188c2ecf20Sopenharmony_ci mdfld_restore_display_registers(dev, 2); 4198c2ecf20Sopenharmony_ci mdfld_restore_display_registers(dev, 0); 4208c2ecf20Sopenharmony_ci /* mdfld_restore_cursor_overlay_registers(dev); */ 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci return 0; 4238c2ecf20Sopenharmony_ci} 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_cistatic int mdfld_power_down(struct drm_device *dev) 4268c2ecf20Sopenharmony_ci{ 4278c2ecf20Sopenharmony_ci /* FIXME */ 4288c2ecf20Sopenharmony_ci return 0; 4298c2ecf20Sopenharmony_ci} 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_cistatic int mdfld_power_up(struct drm_device *dev) 4328c2ecf20Sopenharmony_ci{ 4338c2ecf20Sopenharmony_ci /* FIXME */ 4348c2ecf20Sopenharmony_ci return 0; 4358c2ecf20Sopenharmony_ci} 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci/* Medfield */ 4388c2ecf20Sopenharmony_cistatic const struct psb_offset mdfld_regmap[3] = { 4398c2ecf20Sopenharmony_ci { 4408c2ecf20Sopenharmony_ci .fp0 = MRST_FPA0, 4418c2ecf20Sopenharmony_ci .fp1 = MRST_FPA1, 4428c2ecf20Sopenharmony_ci .cntr = DSPACNTR, 4438c2ecf20Sopenharmony_ci .conf = PIPEACONF, 4448c2ecf20Sopenharmony_ci .src = PIPEASRC, 4458c2ecf20Sopenharmony_ci .dpll = MRST_DPLL_A, 4468c2ecf20Sopenharmony_ci .htotal = HTOTAL_A, 4478c2ecf20Sopenharmony_ci .hblank = HBLANK_A, 4488c2ecf20Sopenharmony_ci .hsync = HSYNC_A, 4498c2ecf20Sopenharmony_ci .vtotal = VTOTAL_A, 4508c2ecf20Sopenharmony_ci .vblank = VBLANK_A, 4518c2ecf20Sopenharmony_ci .vsync = VSYNC_A, 4528c2ecf20Sopenharmony_ci .stride = DSPASTRIDE, 4538c2ecf20Sopenharmony_ci .size = DSPASIZE, 4548c2ecf20Sopenharmony_ci .pos = DSPAPOS, 4558c2ecf20Sopenharmony_ci .surf = DSPASURF, 4568c2ecf20Sopenharmony_ci .addr = MRST_DSPABASE, 4578c2ecf20Sopenharmony_ci .status = PIPEASTAT, 4588c2ecf20Sopenharmony_ci .linoff = DSPALINOFF, 4598c2ecf20Sopenharmony_ci .tileoff = DSPATILEOFF, 4608c2ecf20Sopenharmony_ci .palette = PALETTE_A, 4618c2ecf20Sopenharmony_ci }, 4628c2ecf20Sopenharmony_ci { 4638c2ecf20Sopenharmony_ci .fp0 = MDFLD_DPLL_DIV0, 4648c2ecf20Sopenharmony_ci .cntr = DSPBCNTR, 4658c2ecf20Sopenharmony_ci .conf = PIPEBCONF, 4668c2ecf20Sopenharmony_ci .src = PIPEBSRC, 4678c2ecf20Sopenharmony_ci .dpll = MDFLD_DPLL_B, 4688c2ecf20Sopenharmony_ci .htotal = HTOTAL_B, 4698c2ecf20Sopenharmony_ci .hblank = HBLANK_B, 4708c2ecf20Sopenharmony_ci .hsync = HSYNC_B, 4718c2ecf20Sopenharmony_ci .vtotal = VTOTAL_B, 4728c2ecf20Sopenharmony_ci .vblank = VBLANK_B, 4738c2ecf20Sopenharmony_ci .vsync = VSYNC_B, 4748c2ecf20Sopenharmony_ci .stride = DSPBSTRIDE, 4758c2ecf20Sopenharmony_ci .size = DSPBSIZE, 4768c2ecf20Sopenharmony_ci .pos = DSPBPOS, 4778c2ecf20Sopenharmony_ci .surf = DSPBSURF, 4788c2ecf20Sopenharmony_ci .addr = MRST_DSPBBASE, 4798c2ecf20Sopenharmony_ci .status = PIPEBSTAT, 4808c2ecf20Sopenharmony_ci .linoff = DSPBLINOFF, 4818c2ecf20Sopenharmony_ci .tileoff = DSPBTILEOFF, 4828c2ecf20Sopenharmony_ci .palette = PALETTE_B, 4838c2ecf20Sopenharmony_ci }, 4848c2ecf20Sopenharmony_ci { 4858c2ecf20Sopenharmony_ci .fp0 = MRST_FPA0, /* This is what the old code did ?? */ 4868c2ecf20Sopenharmony_ci .cntr = DSPCCNTR, 4878c2ecf20Sopenharmony_ci .conf = PIPECCONF, 4888c2ecf20Sopenharmony_ci .src = PIPECSRC, 4898c2ecf20Sopenharmony_ci /* No DPLL_C */ 4908c2ecf20Sopenharmony_ci .dpll = MRST_DPLL_A, 4918c2ecf20Sopenharmony_ci .htotal = HTOTAL_C, 4928c2ecf20Sopenharmony_ci .hblank = HBLANK_C, 4938c2ecf20Sopenharmony_ci .hsync = HSYNC_C, 4948c2ecf20Sopenharmony_ci .vtotal = VTOTAL_C, 4958c2ecf20Sopenharmony_ci .vblank = VBLANK_C, 4968c2ecf20Sopenharmony_ci .vsync = VSYNC_C, 4978c2ecf20Sopenharmony_ci .stride = DSPCSTRIDE, 4988c2ecf20Sopenharmony_ci .size = DSPBSIZE, 4998c2ecf20Sopenharmony_ci .pos = DSPCPOS, 5008c2ecf20Sopenharmony_ci .surf = DSPCSURF, 5018c2ecf20Sopenharmony_ci .addr = MDFLD_DSPCBASE, 5028c2ecf20Sopenharmony_ci .status = PIPECSTAT, 5038c2ecf20Sopenharmony_ci .linoff = DSPCLINOFF, 5048c2ecf20Sopenharmony_ci .tileoff = DSPCTILEOFF, 5058c2ecf20Sopenharmony_ci .palette = PALETTE_C, 5068c2ecf20Sopenharmony_ci }, 5078c2ecf20Sopenharmony_ci}; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci/* 5108c2ecf20Sopenharmony_ci * The GPIO lines for resetting DSI pipe 0 and 2 are available in the 5118c2ecf20Sopenharmony_ci * PCI device 0000:00:0c.0 on the Medfield. 5128c2ecf20Sopenharmony_ci */ 5138c2ecf20Sopenharmony_cistatic struct gpiod_lookup_table mdfld_dsi_pipe_gpio_table = { 5148c2ecf20Sopenharmony_ci .table = { 5158c2ecf20Sopenharmony_ci GPIO_LOOKUP("0000:00:0c.0", 128, "dsi-pipe0-reset", 5168c2ecf20Sopenharmony_ci GPIO_ACTIVE_HIGH), 5178c2ecf20Sopenharmony_ci GPIO_LOOKUP("0000:00:0c.0", 34, "dsi-pipe2-reset", 5188c2ecf20Sopenharmony_ci GPIO_ACTIVE_HIGH), 5198c2ecf20Sopenharmony_ci { }, 5208c2ecf20Sopenharmony_ci }, 5218c2ecf20Sopenharmony_ci}; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_cistatic int mdfld_chip_setup(struct drm_device *dev) 5248c2ecf20Sopenharmony_ci{ 5258c2ecf20Sopenharmony_ci struct drm_psb_private *dev_priv = dev->dev_private; 5268c2ecf20Sopenharmony_ci if (pci_enable_msi(dev->pdev)) 5278c2ecf20Sopenharmony_ci dev_warn(dev->dev, "Enabling MSI failed!\n"); 5288c2ecf20Sopenharmony_ci dev_priv->regmap = mdfld_regmap; 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci /* Associate the GPIO lines with the DRM device */ 5318c2ecf20Sopenharmony_ci mdfld_dsi_pipe_gpio_table.dev_id = dev_name(dev->dev); 5328c2ecf20Sopenharmony_ci gpiod_add_lookup_table(&mdfld_dsi_pipe_gpio_table); 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci return mid_chip_setup(dev); 5358c2ecf20Sopenharmony_ci} 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ciconst struct psb_ops mdfld_chip_ops = { 5388c2ecf20Sopenharmony_ci .name = "mdfld", 5398c2ecf20Sopenharmony_ci .accel_2d = 0, 5408c2ecf20Sopenharmony_ci .pipes = 3, 5418c2ecf20Sopenharmony_ci .crtcs = 3, 5428c2ecf20Sopenharmony_ci .lvds_mask = (1 << 1), 5438c2ecf20Sopenharmony_ci .hdmi_mask = (1 << 1), 5448c2ecf20Sopenharmony_ci .cursor_needs_phys = 0, 5458c2ecf20Sopenharmony_ci .sgx_offset = MRST_SGX_OFFSET, 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci .chip_setup = mdfld_chip_setup, 5488c2ecf20Sopenharmony_ci .crtc_helper = &mdfld_helper_funcs, 5498c2ecf20Sopenharmony_ci .crtc_funcs = &psb_intel_crtc_funcs, 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci .output_init = mdfld_output_init, 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE 5548c2ecf20Sopenharmony_ci .backlight_init = mdfld_backlight_init, 5558c2ecf20Sopenharmony_ci#endif 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci .save_regs = mdfld_save_registers, 5588c2ecf20Sopenharmony_ci .restore_regs = mdfld_restore_registers, 5598c2ecf20Sopenharmony_ci .save_crtc = gma_crtc_save, 5608c2ecf20Sopenharmony_ci .restore_crtc = gma_crtc_restore, 5618c2ecf20Sopenharmony_ci .power_down = mdfld_power_down, 5628c2ecf20Sopenharmony_ci .power_up = mdfld_power_up, 5638c2ecf20Sopenharmony_ci}; 564