// SPDX-License-Identifier: MIT
/*
* Copyright © 2022 Intel Corporation
*/
#include "i915_drv.h"
#include "i915_reg.h"
#include "vlv_sideband_reg.h"
#include "intel_display_power_map.h"
#include "intel_display_power_well.h"
#define __LIST_INLINE_ELEMS(__elem_type, ...) \
((__elem_type[]) { __VA_ARGS__ })
#define __LIST(__elems) { \
.list = __elems, \
.count = ARRAY_SIZE(__elems), \
}
#define I915_PW_DOMAINS(...) \
(const struct i915_power_domain_list) \
__LIST(__LIST_INLINE_ELEMS(const enum intel_display_power_domain, __VA_ARGS__))
#define I915_DECL_PW_DOMAINS(__name, ...) \
static const struct i915_power_domain_list __name = I915_PW_DOMAINS(__VA_ARGS__)
/* Zero-length list assigns all power domains, a NULL list assigns none. */
#define I915_PW_DOMAINS_NONE NULL
#define I915_PW_DOMAINS_ALL /* zero-length list */
#define I915_PW_INSTANCES(...) \
(const struct i915_power_well_instance_list) \
__LIST(__LIST_INLINE_ELEMS(const struct i915_power_well_instance, __VA_ARGS__))
#define I915_PW(_name, _domain_list, ...) \
{ .name = _name, .domain_list = _domain_list, ## __VA_ARGS__ }
struct i915_power_well_desc_list {
const struct i915_power_well_desc *list;
u8 count;
};
#define I915_PW_DESCRIPTORS(x) __LIST(x)
I915_DECL_PW_DOMAINS(i9xx_pwdoms_always_on, I915_PW_DOMAINS_ALL);
static const struct i915_power_well_desc i9xx_power_wells_always_on[] = {
{
.instances = &I915_PW_INSTANCES(
I915_PW("always-on", &i9xx_pwdoms_always_on),
),
.ops = &i9xx_always_on_power_well_ops,
.always_on = true,
},
};
static const struct i915_power_well_desc_list i9xx_power_wells[] = {
I915_PW_DESCRIPTORS(i9xx_power_wells_always_on),
};
I915_DECL_PW_DOMAINS(i830_pwdoms_pipes,
POWER_DOMAIN_PIPE_A,
POWER_DOMAIN_PIPE_B,
POWER_DOMAIN_PIPE_PANEL_FITTER_A,
POWER_DOMAIN_PIPE_PANEL_FITTER_B,
POWER_DOMAIN_TRANSCODER_A,
POWER_DOMAIN_TRANSCODER_B,
POWER_DOMAIN_INIT);
static const struct i915_power_well_desc i830_power_wells_main[] = {
{
.instances = &I915_PW_INSTANCES(
I915_PW("pipes", &i830_pwdoms_pipes),
),
.ops = &i830_pipes_power_well_ops,
},
};
static const struct i915_power_well_desc_list i830_power_wells[] = {
I915_PW_DESCRIPTORS(i9xx_power_wells_always_on),
I915_PW_DESCRIPTORS(i830_power_wells_main),
};
I915_DECL_PW_DOMAINS(hsw_pwdoms_display,
POWER_DOMAIN_PIPE_B,
POWER_DOMAIN_PIPE_C,
POWER_DOMAIN_PIPE_PANEL_FITTER_A,
POWER_DOMAIN_PIPE_PANEL_FITTER_B,
POWER_DOMAIN_PIPE_PANEL_FITTER_C,
POWER_DOMAIN_TRANSCODER_A,
POWER_DOMAIN_TRANSCODER_B,
POWER_DOMAIN_TRANSCODER_C,
POWER_DOMAIN_PORT_DDI_LANES_B,
POWER_DOMAIN_PORT_DDI_LANES_C,
POWER_DOMAIN_PORT_DDI_LANES_D,
POWER_DOMAIN_PORT_CRT, /* DDI E */
POWER_DOMAIN_VGA,
POWER_DOMAIN_AUDIO_MMIO,
POWER_DOMAIN_AUDIO_PLAYBACK,
POWER_DOMAIN_INIT);
static const struct i915_power_well_desc hsw_power_wells_main[] = {
{
.instances = &I915_PW_INSTANCES(
I915_PW("display", &hsw_pwdoms_display,
.hsw.idx = HSW_PW_CTL_IDX_GLOBAL,
.id = HSW_DISP_PW_GLOBAL),
),
.ops = &hsw_power_well_ops,
.has_vga = true,
},
};
static const struct i915_power_well_desc_list hsw_power_wells[] = {
I915_PW_DESCRIPTORS(i9xx_power_wells_always_on),
I915_PW_DESCRIPTORS(hsw_power_wells_main),
};
I915_DECL_PW_DOMAINS(bdw_pwdoms_display,
POWER_DOMAIN_PIPE_B,
POWER_DOMAIN_PIPE_C,
POWER_DOMAIN_PIPE_PANEL_FITTER_B,
POWER_DOMAIN_PIPE_PANEL_FITTER_C,
POWER_DOMAIN_TRANSCODER_A,
POWER_DOMAIN_TRANSCODER_B,
POWER_DOMAIN_TRANSCODER_C,
POWER_DOMAIN_PORT_DDI_LANES_B,
POWER_DOMAIN_PORT_DDI_LANES_C,
POWER_DOMAIN_PORT_DDI_LANES_D,
POWER_DOMAIN_PORT_CRT, /* DDI E */
POWER_DOMAIN_VGA,
POWER_DOMAIN_AUDIO_MMIO,
POWER_DOMAIN_AUDIO_PLAYBACK,
POWER_DOMAIN_INIT);
static const struct i915_power_well_desc bdw_power_wells_main[] = {
{
.instances = &I915_PW_INSTANCES(
I915_PW("display", &bdw_pwdoms_display,
.hsw.idx = HSW_PW_CTL_IDX_GLOBAL,
.id = HSW_DISP_PW_GLOBAL),
),
.ops = &hsw_power_well_ops,
.has_vga = true,
.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C),
},
};
static const struct i915_power_well_desc_list bdw_power_wells[] = {
I915_PW_DESCRIPTORS(i9xx_power_wells_always_on),
I915_PW_DESCRIPTORS(bdw_power_wells_main),
};
I915_DECL_PW_DOMAINS(vlv_pwdoms_display,
POWER_DOMAIN_DISPLAY_CORE,
POWER_DOMAIN_PIPE_A,
POWER_DOMAIN_PIPE_B,
POWER_DOMAIN_PIPE_PANEL_FITTER_A,
POWER_DOMAIN_PIPE_PANEL_FITTER_B,
POWER_DOMAIN_TRANSCODER_A,
POWER_DOMAIN_TRANSCODER_B,
POWER_DOMAIN_PORT_DDI_LANES_B,
POWER_DOMAIN_PORT_DDI_LANES_C,
POWER_DOMAIN_PORT_DSI,
POWER_DOMAIN_PORT_CRT,
POWER_DOMAIN_VGA,
POWER_DOMAIN_AUDIO_MMIO,
POWER_DOMAIN_AUDIO_PLAYBACK,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_AUX_C,
POWER_DOMAIN_GMBUS,
POWER_DOMAIN_INIT);
I915_DECL_PW_DOMAINS(vlv_pwdoms_dpio_cmn_bc,
POWER_DOMAIN_PORT_DDI_LANES_B,
POWER_DOMAIN_PORT_DDI_LANES_C,
POWER_DOMAIN_PORT_CRT,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_AUX_C,
POWER_DOMAIN_INIT);
I915_DECL_PW_DOMAINS(vlv_pwdoms_dpio_tx_bc_lanes,
POWER_DOMAIN_PORT_DDI_LANES_B,
POWER_DOMAIN_PORT_DDI_LANES_C,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_AUX_C,
POWER_DOMAIN_INIT);
static const struct i915_power_well_desc vlv_power_wells_main[] = {
{
.instances = &I915_PW_INSTANCES(
I915_PW("display", &vlv_pwdoms_display,
.vlv.idx = PUNIT_PWGT_IDX_DISP2D,
.id = VLV_DISP_PW_DISP2D),
),
.ops = &vlv_display_power_well_ops,
}, {
.instances = &I915_PW_INSTANCES(
I915_PW("dpio-tx-b-01", &vlv_pwdoms_dpio_tx_bc_lanes,
.vlv.idx = PUNIT_PWGT_IDX_DPIO_TX_B_LANES_01),
I915_PW("dpio-tx-b-23", &vlv_pwdoms_dpio_tx_bc_lanes,
.vlv.idx = PUNIT_PWGT_IDX_DPIO_TX_B_LANES_23),
I915_PW("dpio-tx-c-01", &vlv_pwdoms_dpio_tx_bc_lanes,
.vlv.idx = PUNIT_PWGT_IDX_DPIO_TX_C_LANES_01),
I915_PW("dpio-tx-c-23", &vlv_pwdoms_dpio_tx_bc_lanes,
.vlv.idx = PUNIT_PWGT_IDX_DPIO_TX_C_LANES_23),
),
.ops = &vlv_dpio_power_well_ops,
}, {
.instances = &I915_PW_INSTANCES(
I915_PW("dpio-common", &vlv_pwdoms_dpio_cmn_bc,
.vlv.idx = PUNIT_PWGT_IDX_DPIO_CMN_BC,
.id = VLV_DISP_PW_DPIO_CMN_BC),
),
.ops = &vlv_dpio_cmn_power_well_ops,
},
};
static const struct i915_power_well_desc_list vlv_power_wells[] = {
I915_PW_DESCRIPTORS(i9xx_power_wells_always_on),
I915_PW_DESCRIPTORS(vlv_power_wells_main),
};
I915_DECL_PW_DOMAINS(chv_pwdoms_display,
POWER_DOMAIN_DISPLAY_CORE,
POWER_DOMAIN_PIPE_A,
POWER_DOMAIN_PIPE_B,
POWER_DOMAIN_PIPE_C,
POWER_DOMAIN_PIPE_PANEL_FITTER_A,
POWER_DOMAIN_PIPE_PANEL_FITTER_B,
POWER_DOMAIN_PIPE_PANEL_FITTER_C,
POWER_DOMAIN_TRANSCODER_A,
POWER_DOMAIN_TRANSCODER_B,
POWER_DOMAIN_TRANSCODER_C,
POWER_DOMAIN_PORT_DDI_LANES_B,
POWER_DOMAIN_PORT_DDI_LANES_C,
POWER_DOMAIN_PORT_DDI_LANES_D,
POWER_DOMAIN_PORT_DSI,
POWER_DOMAIN_VGA,
POWER_DOMAIN_AUDIO_MMIO,
POWER_DOMAIN_AUDIO_PLAYBACK,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_AUX_C,
POWER_DOMAIN_AUX_D,
POWER_DOMAIN_GMBUS,
POWER_DOMAIN_INIT);
I915_DECL_PW_DOMAINS(chv_pwdoms_dpio_cmn_bc,
POWER_DOMAIN_PORT_DDI_LANES_B,
POWER_DOMAIN_PORT_DDI_LANES_C,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_AUX_C,
POWER_DOMAIN_INIT);
I915_DECL_PW_DOMAINS(chv_pwdoms_dpio_cmn_d,
POWER_DOMAIN_PORT_DDI_LANES_D,
POWER_DOMAIN_AUX_D,
POWER_DOMAIN_INIT);
static const struct i915_power_well_desc chv_power_wells_main[] = {
{
/*
* Pipe A power well is the new disp2d well. Pipe B and C
* power wells don't actually exist. Pipe A power well is
* required for any pipe to work.
*/
.instances = &I915_PW_INSTANCES(
I915_PW("display", &chv_pwdoms_display),
),
.ops = &chv_pipe_power_well_ops,
}, {
.instances = &I915_PW_INSTANCES(
I915_PW("dpio-common-bc", &chv_pwdoms_dpio_cmn_bc,
.vlv.idx = PUNIT_PWGT_IDX_DPIO_CMN_BC,
.id = VLV_DISP_PW_DPIO_CMN_BC),
I915_PW("dpio-common-d", &chv_pwdoms_dpio_cmn_d,
.vlv.idx = PUNIT_PWGT_IDX_DPIO_CMN_D,
.id = CHV_DISP_PW_DPIO_CMN_D),
),
.ops = &chv_dpio_cmn_power_well_ops,
},
};
static const struct i915_power_well_desc_list chv_power_wells[] = {
I915_PW
|