cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

psb_device.c (9273B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/**************************************************************************
      3 * Copyright (c) 2011, Intel Corporation.
      4 * All Rights Reserved.
      5 *
      6 **************************************************************************/
      7
      8#include <linux/backlight.h>
      9
     10#include <drm/drm.h>
     11
     12#include "gma_device.h"
     13#include "intel_bios.h"
     14#include "psb_device.h"
     15#include "psb_drv.h"
     16#include "psb_intel_reg.h"
     17#include "psb_reg.h"
     18
     19static int psb_output_init(struct drm_device *dev)
     20{
     21	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
     22	psb_intel_lvds_init(dev, &dev_priv->mode_dev);
     23	psb_intel_sdvo_init(dev, SDVOB);
     24	return 0;
     25}
     26
     27#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
     28
     29/*
     30 *	Poulsbo Backlight Interfaces
     31 */
     32
     33#define BLC_PWM_PRECISION_FACTOR 100	/* 10000000 */
     34#define BLC_PWM_FREQ_CALC_CONSTANT 32
     35#define MHz 1000000
     36
     37#define PSB_BLC_PWM_PRECISION_FACTOR    10
     38#define PSB_BLC_MAX_PWM_REG_FREQ        0xFFFE
     39#define PSB_BLC_MIN_PWM_REG_FREQ        0x2
     40
     41#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
     42#define PSB_BACKLIGHT_PWM_CTL_SHIFT	(16)
     43
     44static int psb_brightness;
     45static struct backlight_device *psb_backlight_device;
     46
     47static int psb_get_brightness(struct backlight_device *bd)
     48{
     49	/* return locally cached var instead of HW read (due to DPST etc.) */
     50	/* FIXME: ideally return actual value in case firmware fiddled with
     51	   it */
     52	return psb_brightness;
     53}
     54
     55
     56static int psb_backlight_setup(struct drm_device *dev)
     57{
     58	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
     59	unsigned long core_clock;
     60	/* u32 bl_max_freq; */
     61	/* unsigned long value; */
     62	u16 bl_max_freq;
     63	uint32_t value;
     64	uint32_t blc_pwm_precision_factor;
     65
     66	/* get bl_max_freq and pol from dev_priv*/
     67	if (!dev_priv->lvds_bl) {
     68		dev_err(dev->dev, "Has no valid LVDS backlight info\n");
     69		return -ENOENT;
     70	}
     71	bl_max_freq = dev_priv->lvds_bl->freq;
     72	blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
     73
     74	core_clock = dev_priv->core_freq;
     75
     76	value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
     77	value *= blc_pwm_precision_factor;
     78	value /= bl_max_freq;
     79	value /= blc_pwm_precision_factor;
     80
     81	if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
     82		 value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
     83				return -ERANGE;
     84	else {
     85		value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
     86		REG_WRITE(BLC_PWM_CTL,
     87			(value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value));
     88	}
     89	return 0;
     90}
     91
     92static int psb_set_brightness(struct backlight_device *bd)
     93{
     94	struct drm_device *dev = bl_get_data(psb_backlight_device);
     95	int level = bd->props.brightness;
     96
     97	/* Percentage 1-100% being valid */
     98	if (level < 1)
     99		level = 1;
    100
    101	psb_intel_lvds_set_brightness(dev, level);
    102	psb_brightness = level;
    103	return 0;
    104}
    105
    106static const struct backlight_ops psb_ops = {
    107	.get_brightness = psb_get_brightness,
    108	.update_status  = psb_set_brightness,
    109};
    110
    111static int psb_backlight_init(struct drm_device *dev)
    112{
    113	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
    114	int ret;
    115	struct backlight_properties props;
    116
    117	memset(&props, 0, sizeof(struct backlight_properties));
    118	props.max_brightness = 100;
    119	props.type = BACKLIGHT_PLATFORM;
    120
    121	psb_backlight_device = backlight_device_register("psb-bl",
    122					NULL, (void *)dev, &psb_ops, &props);
    123	if (IS_ERR(psb_backlight_device))
    124		return PTR_ERR(psb_backlight_device);
    125
    126	ret = psb_backlight_setup(dev);
    127	if (ret < 0) {
    128		backlight_device_unregister(psb_backlight_device);
    129		psb_backlight_device = NULL;
    130		return ret;
    131	}
    132	psb_backlight_device->props.brightness = 100;
    133	psb_backlight_device->props.max_brightness = 100;
    134	backlight_update_status(psb_backlight_device);
    135	dev_priv->backlight_device = psb_backlight_device;
    136
    137	/* This must occur after the backlight is properly initialised */
    138	psb_lid_timer_init(dev_priv);
    139
    140	return 0;
    141}
    142
    143#endif
    144
    145/*
    146 *	Provide the Poulsbo specific chip logic and low level methods
    147 *	for power management
    148 */
    149
    150static void psb_init_pm(struct drm_device *dev)
    151{
    152	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
    153
    154	u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL);
    155	gating &= ~3;	/* Disable 2D clock gating */
    156	gating |= 1;
    157	PSB_WSGX32(gating, PSB_CR_CLKGATECTL);
    158	PSB_RSGX32(PSB_CR_CLKGATECTL);
    159}
    160
    161/**
    162 *	psb_save_display_registers	-	save registers lost on suspend
    163 *	@dev: our DRM device
    164 *
    165 *	Save the state we need in order to be able to restore the interface
    166 *	upon resume from suspend
    167 */
    168static int psb_save_display_registers(struct drm_device *dev)
    169{
    170	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
    171	struct gma_connector *gma_connector;
    172	struct drm_crtc *crtc;
    173	struct drm_connector_list_iter conn_iter;
    174	struct drm_connector *connector;
    175	struct psb_state *regs = &dev_priv->regs.psb;
    176
    177	/* Display arbitration control + watermarks */
    178	regs->saveDSPARB = PSB_RVDC32(DSPARB);
    179	regs->saveDSPFW1 = PSB_RVDC32(DSPFW1);
    180	regs->saveDSPFW2 = PSB_RVDC32(DSPFW2);
    181	regs->saveDSPFW3 = PSB_RVDC32(DSPFW3);
    182	regs->saveDSPFW4 = PSB_RVDC32(DSPFW4);
    183	regs->saveDSPFW5 = PSB_RVDC32(DSPFW5);
    184	regs->saveDSPFW6 = PSB_RVDC32(DSPFW6);
    185	regs->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
    186
    187	/* Save crtc and output state */
    188	drm_modeset_lock_all(dev);
    189	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
    190		if (drm_helper_crtc_in_use(crtc))
    191			dev_priv->ops->save_crtc(crtc);
    192	}
    193
    194	drm_connector_list_iter_begin(dev, &conn_iter);
    195	drm_for_each_connector_iter(connector, &conn_iter) {
    196		gma_connector = to_gma_connector(connector);
    197		if (gma_connector->save)
    198			gma_connector->save(connector);
    199	}
    200	drm_connector_list_iter_end(&conn_iter);
    201
    202	drm_modeset_unlock_all(dev);
    203	return 0;
    204}
    205
    206/**
    207 *	psb_restore_display_registers	-	restore lost register state
    208 *	@dev: our DRM device
    209 *
    210 *	Restore register state that was lost during suspend and resume.
    211 */
    212static int psb_restore_display_registers(struct drm_device *dev)
    213{
    214	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
    215	struct gma_connector *gma_connector;
    216	struct drm_crtc *crtc;
    217	struct drm_connector_list_iter conn_iter;
    218	struct drm_connector *connector;
    219	struct psb_state *regs = &dev_priv->regs.psb;
    220
    221	/* Display arbitration + watermarks */
    222	PSB_WVDC32(regs->saveDSPARB, DSPARB);
    223	PSB_WVDC32(regs->saveDSPFW1, DSPFW1);
    224	PSB_WVDC32(regs->saveDSPFW2, DSPFW2);
    225	PSB_WVDC32(regs->saveDSPFW3, DSPFW3);
    226	PSB_WVDC32(regs->saveDSPFW4, DSPFW4);
    227	PSB_WVDC32(regs->saveDSPFW5, DSPFW5);
    228	PSB_WVDC32(regs->saveDSPFW6, DSPFW6);
    229	PSB_WVDC32(regs->saveCHICKENBIT, DSPCHICKENBIT);
    230
    231	/*make sure VGA plane is off. it initializes to on after reset!*/
    232	PSB_WVDC32(0x80000000, VGACNTRL);
    233
    234	drm_modeset_lock_all(dev);
    235	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
    236		if (drm_helper_crtc_in_use(crtc))
    237			dev_priv->ops->restore_crtc(crtc);
    238
    239	drm_connector_list_iter_begin(dev, &conn_iter);
    240	drm_for_each_connector_iter(connector, &conn_iter) {
    241		gma_connector = to_gma_connector(connector);
    242		if (gma_connector->restore)
    243			gma_connector->restore(connector);
    244	}
    245	drm_connector_list_iter_end(&conn_iter);
    246
    247	drm_modeset_unlock_all(dev);
    248	return 0;
    249}
    250
    251static int psb_power_down(struct drm_device *dev)
    252{
    253	return 0;
    254}
    255
    256static int psb_power_up(struct drm_device *dev)
    257{
    258	return 0;
    259}
    260
    261/* Poulsbo */
    262static const struct psb_offset psb_regmap[2] = {
    263	{
    264		.fp0 = FPA0,
    265		.fp1 = FPA1,
    266		.cntr = DSPACNTR,
    267		.conf = PIPEACONF,
    268		.src = PIPEASRC,
    269		.dpll = DPLL_A,
    270		.htotal = HTOTAL_A,
    271		.hblank = HBLANK_A,
    272		.hsync = HSYNC_A,
    273		.vtotal = VTOTAL_A,
    274		.vblank = VBLANK_A,
    275		.vsync = VSYNC_A,
    276		.stride = DSPASTRIDE,
    277		.size = DSPASIZE,
    278		.pos = DSPAPOS,
    279		.base = DSPABASE,
    280		.surf = DSPASURF,
    281		.addr = DSPABASE,
    282		.status = PIPEASTAT,
    283		.linoff = DSPALINOFF,
    284		.tileoff = DSPATILEOFF,
    285		.palette = PALETTE_A,
    286	},
    287	{
    288		.fp0 = FPB0,
    289		.fp1 = FPB1,
    290		.cntr = DSPBCNTR,
    291		.conf = PIPEBCONF,
    292		.src = PIPEBSRC,
    293		.dpll = DPLL_B,
    294		.htotal = HTOTAL_B,
    295		.hblank = HBLANK_B,
    296		.hsync = HSYNC_B,
    297		.vtotal = VTOTAL_B,
    298		.vblank = VBLANK_B,
    299		.vsync = VSYNC_B,
    300		.stride = DSPBSTRIDE,
    301		.size = DSPBSIZE,
    302		.pos = DSPBPOS,
    303		.base = DSPBBASE,
    304		.surf = DSPBSURF,
    305		.addr = DSPBBASE,
    306		.status = PIPEBSTAT,
    307		.linoff = DSPBLINOFF,
    308		.tileoff = DSPBTILEOFF,
    309		.palette = PALETTE_B,
    310	}
    311};
    312
    313static int psb_chip_setup(struct drm_device *dev)
    314{
    315	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
    316	dev_priv->regmap = psb_regmap;
    317	gma_get_core_freq(dev);
    318	gma_intel_setup_gmbus(dev);
    319	psb_intel_opregion_init(dev);
    320	psb_intel_init_bios(dev);
    321	return 0;
    322}
    323
    324static void psb_chip_teardown(struct drm_device *dev)
    325{
    326	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
    327	psb_lid_timer_takedown(dev_priv);
    328	gma_intel_teardown_gmbus(dev);
    329}
    330
    331const struct psb_ops psb_chip_ops = {
    332	.name = "Poulsbo",
    333	.pipes = 2,
    334	.crtcs = 2,
    335	.hdmi_mask = (1 << 0),
    336	.lvds_mask = (1 << 1),
    337	.sdvo_mask = (1 << 0),
    338	.cursor_needs_phys = 1,
    339	.sgx_offset = PSB_SGX_OFFSET,
    340	.chip_setup = psb_chip_setup,
    341	.chip_teardown = psb_chip_teardown,
    342
    343	.crtc_helper = &psb_intel_helper_funcs,
    344	.clock_funcs = &psb_clock_funcs,
    345
    346	.output_init = psb_output_init,
    347
    348#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
    349	.backlight_init = psb_backlight_init,
    350#endif
    351
    352	.init_pm = psb_init_pm,
    353	.save_regs = psb_save_display_registers,
    354	.restore_regs = psb_restore_display_registers,
    355	.save_crtc = gma_crtc_save,
    356	.restore_crtc = gma_crtc_restore,
    357	.power_down = psb_power_down,
    358	.power_up = psb_power_up,
    359};
    360