mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-02-08 06:16:45 -05:00
Merge branch 'linux-4.10' of git://github.com/skeggsb/linux into drm-next
- Initial atomic modesetting support. Used for "legacy" KMS interfaces, ioctl not exposed by default, but there is a commandline option to enable it. - Initial DP 1.2 MST support - Misc other code cleanups + fixes * 'linux-4.10' of git://github.com/skeggsb/linux: (64 commits) drm/nouveau/fifo/gf100-: protect channel preempt with subdev mutex drm/nouveau/gr: fallback to legacy paths during firmware lookup drm/nouveau/kms/nv50: initial support for DP 1.2 multi-stream drm/nouveau/kms/nv50: allow encoder update to be called from other modules drm/nouveau/kms/nv50: rename remaining nv50_crtc to nv50_head drm/nouveau/kms/nv50: remove code to create ctxdma for every framebuffer drm/nouveau/kms/nv50: remove code to support non-atomic page flips drm/nouveau/kms/nv50: remove code to support non-atomic connector properties drm/nouveau/kms/nv50: remove code to support non-atomic dpms drm/nouveau/kms/nv50: remove code to support non-atomic modesets drm/nouveau/kms/nv50: transition to atomic interfaces internally drm/nouveau/kms/nv50: turn mode_set_base_atomic() into a stub drm/nouveau/kms/nv50: convert encoder mode_fixup into an atomic_check() drm/nouveau/kms/nv50: clean-up encoder functions drm/nouveau/kms/nv50: ensure encoder normal power state is enabled at startup drm/nouveau/kms/nv50: prepare ctxdma interface to be usable with atomic drm/nouveau/kms/nv50: separate out cursor channel commit drm/nouveau/kms/nv50: separate out base channel commit drm/nouveau/kms/nv50: separate out vblank dmi commit drm/nouveau/kms/nv50: separate out procamp commit ...
This commit is contained in:
@@ -33,7 +33,7 @@
|
||||
#include "nouveau_connector.h"
|
||||
#include "nouveau_display.h"
|
||||
#include "nvreg.h"
|
||||
|
||||
#include "disp.h"
|
||||
|
||||
struct nouveau_plane {
|
||||
struct drm_plane base;
|
||||
|
||||
@@ -34,6 +34,8 @@ struct nv50_disp_mthd_v1 {
|
||||
#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR 0x22
|
||||
#define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT 0x23
|
||||
#define NV50_DISP_MTHD_V1_SOR_DP_PWR 0x24
|
||||
#define NV50_DISP_MTHD_V1_SOR_DP_MST_LINK 0x25
|
||||
#define NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI 0x26
|
||||
#define NV50_DISP_MTHD_V1_PIOR_PWR 0x30
|
||||
__u8 method;
|
||||
__u16 hasht;
|
||||
@@ -90,6 +92,21 @@ struct nv50_disp_sor_dp_pwr_v0 {
|
||||
__u8 pad02[6];
|
||||
};
|
||||
|
||||
struct nv50_disp_sor_dp_mst_link_v0 {
|
||||
__u8 version;
|
||||
__u8 state;
|
||||
__u8 pad02[6];
|
||||
};
|
||||
|
||||
struct nv50_disp_sor_dp_mst_vcpi_v0 {
|
||||
__u8 version;
|
||||
__u8 pad01[1];
|
||||
__u8 start_slot;
|
||||
__u8 num_slots;
|
||||
__u16 pbn;
|
||||
__u16 aligned_pbn;
|
||||
};
|
||||
|
||||
struct nv50_disp_pior_pwr_v0 {
|
||||
__u8 version;
|
||||
__u8 state;
|
||||
|
||||
@@ -66,6 +66,35 @@ void nvif_object_unmap(struct nvif_object *);
|
||||
|
||||
#define nvif_mthd(a,b,c,d) nvif_object_mthd((a), (b), (c), (d))
|
||||
|
||||
struct nvif_mclass {
|
||||
s32 oclass;
|
||||
int version;
|
||||
};
|
||||
|
||||
#define nvif_mclass(o,m) ({ \
|
||||
struct nvif_object *object = (o); \
|
||||
struct nvif_sclass *sclass; \
|
||||
const typeof(m[0]) *mclass = (m); \
|
||||
int ret = -ENODEV; \
|
||||
int cnt, i, j; \
|
||||
\
|
||||
cnt = nvif_object_sclass_get(object, &sclass); \
|
||||
if (cnt >= 0) { \
|
||||
for (i = 0; ret < 0 && mclass[i].oclass; i++) { \
|
||||
for (j = 0; j < cnt; j++) { \
|
||||
if (mclass[i].oclass == sclass[j].oclass && \
|
||||
mclass[i].version >= sclass[j].minver && \
|
||||
mclass[i].version <= sclass[j].maxver) { \
|
||||
ret = i; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
nvif_object_sclass_put(&sclass); \
|
||||
} \
|
||||
ret; \
|
||||
})
|
||||
|
||||
/*XXX*/
|
||||
#include <core/object.h>
|
||||
#define nvxx_object(a) ({ \
|
||||
|
||||
@@ -93,6 +93,7 @@ int gk104_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
|
||||
int gk20a_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
|
||||
int gm107_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
|
||||
int gm200_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
|
||||
int gm20b_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
|
||||
int gp100_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
|
||||
int gp104_fb_new(struct nvkm_device *, int, struct nvkm_fb **);
|
||||
|
||||
@@ -156,4 +157,6 @@ struct nvkm_ram_func {
|
||||
int (*prog)(struct nvkm_ram *);
|
||||
void (*tidy)(struct nvkm_ram *);
|
||||
};
|
||||
|
||||
extern const u8 gf100_pte_storage_type_map[256];
|
||||
#endif
|
||||
|
||||
@@ -333,6 +333,9 @@ get_fp_strap(struct drm_device *dev, struct nvbios *bios)
|
||||
if (bios->major_version < 5 && bios->data[0x48] & 0x4)
|
||||
return NVReadVgaCrtc5758(dev, 0, 0xf) & 0xf;
|
||||
|
||||
if (drm->device.info.family >= NV_DEVICE_INFO_V0_MAXWELL)
|
||||
return nvif_rd32(device, 0x001800) & 0x0000000f;
|
||||
else
|
||||
if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA)
|
||||
return (nvif_rd32(device, NV_PEXTDEV_BOOT_0) >> 24) & 0xf;
|
||||
else
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <linux/vga_switcheroo.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
|
||||
@@ -47,6 +48,301 @@
|
||||
#include <nvif/cl0046.h>
|
||||
#include <nvif/event.h>
|
||||
|
||||
struct drm_display_mode *
|
||||
nouveau_conn_native_mode(struct drm_connector *connector)
|
||||
{
|
||||
const struct drm_connector_helper_funcs *helper = connector->helper_private;
|
||||
struct nouveau_drm *drm = nouveau_drm(connector->dev);
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_display_mode *mode, *largest = NULL;
|
||||
int high_w = 0, high_h = 0, high_v = 0;
|
||||
|
||||
list_for_each_entry(mode, &connector->probed_modes, head) {
|
||||
mode->vrefresh = drm_mode_vrefresh(mode);
|
||||
if (helper->mode_valid(connector, mode) != MODE_OK ||
|
||||
(mode->flags & DRM_MODE_FLAG_INTERLACE))
|
||||
continue;
|
||||
|
||||
/* Use preferred mode if there is one.. */
|
||||
if (mode->type & DRM_MODE_TYPE_PREFERRED) {
|
||||
NV_DEBUG(drm, "native mode from preferred\n");
|
||||
return drm_mode_duplicate(dev, mode);
|
||||
}
|
||||
|
||||
/* Otherwise, take the resolution with the largest width, then
|
||||
* height, then vertical refresh
|
||||
*/
|
||||
if (mode->hdisplay < high_w)
|
||||
continue;
|
||||
|
||||
if (mode->hdisplay == high_w && mode->vdisplay < high_h)
|
||||
continue;
|
||||
|
||||
if (mode->hdisplay == high_w && mode->vdisplay == high_h &&
|
||||
mode->vrefresh < high_v)
|
||||
continue;
|
||||
|
||||
high_w = mode->hdisplay;
|
||||
high_h = mode->vdisplay;
|
||||
high_v = mode->vrefresh;
|
||||
largest = mode;
|
||||
}
|
||||
|
||||
NV_DEBUG(drm, "native mode from largest: %dx%d@%d\n",
|
||||
high_w, high_h, high_v);
|
||||
return largest ? drm_mode_duplicate(dev, largest) : NULL;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_conn_atomic_get_property(struct drm_connector *connector,
|
||||
const struct drm_connector_state *state,
|
||||
struct drm_property *property, u64 *val)
|
||||
{
|
||||
struct nouveau_conn_atom *asyc = nouveau_conn_atom(state);
|
||||
struct nouveau_display *disp = nouveau_display(connector->dev);
|
||||
struct drm_device *dev = connector->dev;
|
||||
|
||||
if (property == dev->mode_config.scaling_mode_property)
|
||||
*val = asyc->scaler.mode;
|
||||
else if (property == disp->underscan_property)
|
||||
*val = asyc->scaler.underscan.mode;
|
||||
else if (property == disp->underscan_hborder_property)
|
||||
*val = asyc->scaler.underscan.hborder;
|
||||
else if (property == disp->underscan_vborder_property)
|
||||
*val = asyc->scaler.underscan.vborder;
|
||||
else if (property == disp->dithering_mode)
|
||||
*val = asyc->dither.mode;
|
||||
else if (property == disp->dithering_depth)
|
||||
*val = asyc->dither.depth;
|
||||
else if (property == disp->vibrant_hue_property)
|
||||
*val = asyc->procamp.vibrant_hue;
|
||||
else if (property == disp->color_vibrance_property)
|
||||
*val = asyc->procamp.color_vibrance;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_conn_atomic_set_property(struct drm_connector *connector,
|
||||
struct drm_connector_state *state,
|
||||
struct drm_property *property, u64 val)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct nouveau_conn_atom *asyc = nouveau_conn_atom(state);
|
||||
struct nouveau_display *disp = nouveau_display(dev);
|
||||
|
||||
if (property == dev->mode_config.scaling_mode_property) {
|
||||
switch (val) {
|
||||
case DRM_MODE_SCALE_NONE:
|
||||
/* We allow 'None' for EDID modes, even on a fixed
|
||||
* panel (some exist with support for lower refresh
|
||||
* rates, which people might want to use for power-
|
||||
* saving purposes).
|
||||
*
|
||||
* Non-EDID modes will force the use of GPU scaling
|
||||
* to the native mode regardless of this setting.
|
||||
*/
|
||||
switch (connector->connector_type) {
|
||||
case DRM_MODE_CONNECTOR_LVDS:
|
||||
case DRM_MODE_CONNECTOR_eDP:
|
||||
/* ... except prior to G80, where the code
|
||||
* doesn't support such things.
|
||||
*/
|
||||
if (disp->disp.oclass < NV50_DISP)
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case DRM_MODE_SCALE_FULLSCREEN:
|
||||
case DRM_MODE_SCALE_CENTER:
|
||||
case DRM_MODE_SCALE_ASPECT:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (asyc->scaler.mode != val) {
|
||||
asyc->scaler.mode = val;
|
||||
asyc->set.scaler = true;
|
||||
}
|
||||
} else
|
||||
if (property == disp->underscan_property) {
|
||||
if (asyc->scaler.underscan.mode != val) {
|
||||
asyc->scaler.underscan.mode = val;
|
||||
asyc->set.scaler = true;
|
||||
}
|
||||
} else
|
||||
if (property == disp->underscan_hborder_property) {
|
||||
if (asyc->scaler.underscan.hborder != val) {
|
||||
asyc->scaler.underscan.hborder = val;
|
||||
asyc->set.scaler = true;
|
||||
}
|
||||
} else
|
||||
if (property == disp->underscan_vborder_property) {
|
||||
if (asyc->scaler.underscan.vborder != val) {
|
||||
asyc->scaler.underscan.vborder = val;
|
||||
asyc->set.scaler = true;
|
||||
}
|
||||
} else
|
||||
if (property == disp->dithering_mode) {
|
||||
if (asyc->dither.mode != val) {
|
||||
asyc->dither.mode = val;
|
||||
asyc->set.dither = true;
|
||||
}
|
||||
} else
|
||||
if (property == disp->dithering_depth) {
|
||||
if (asyc->dither.mode != val) {
|
||||
asyc->dither.depth = val;
|
||||
asyc->set.dither = true;
|
||||
}
|
||||
} else
|
||||
if (property == disp->vibrant_hue_property) {
|
||||
if (asyc->procamp.vibrant_hue != val) {
|
||||
asyc->procamp.vibrant_hue = val;
|
||||
asyc->set.procamp = true;
|
||||
}
|
||||
} else
|
||||
if (property == disp->color_vibrance_property) {
|
||||
if (asyc->procamp.color_vibrance != val) {
|
||||
asyc->procamp.color_vibrance = val;
|
||||
asyc->set.procamp = true;
|
||||
}
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_conn_atomic_destroy_state(struct drm_connector *connector,
|
||||
struct drm_connector_state *state)
|
||||
{
|
||||
struct nouveau_conn_atom *asyc = nouveau_conn_atom(state);
|
||||
__drm_atomic_helper_connector_destroy_state(&asyc->state);
|
||||
kfree(asyc);
|
||||
}
|
||||
|
||||
struct drm_connector_state *
|
||||
nouveau_conn_atomic_duplicate_state(struct drm_connector *connector)
|
||||
{
|
||||
struct nouveau_conn_atom *armc = nouveau_conn_atom(connector->state);
|
||||
struct nouveau_conn_atom *asyc;
|
||||
if (!(asyc = kmalloc(sizeof(*asyc), GFP_KERNEL)))
|
||||
return NULL;
|
||||
__drm_atomic_helper_connector_duplicate_state(connector, &asyc->state);
|
||||
asyc->dither = armc->dither;
|
||||
asyc->scaler = armc->scaler;
|
||||
asyc->procamp = armc->procamp;
|
||||
asyc->set.mask = 0;
|
||||
return &asyc->state;
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_conn_reset(struct drm_connector *connector)
|
||||
{
|
||||
struct nouveau_conn_atom *asyc;
|
||||
|
||||
if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL))))
|
||||
return;
|
||||
|
||||
if (connector->state)
|
||||
__drm_atomic_helper_connector_destroy_state(connector->state);
|
||||
__drm_atomic_helper_connector_reset(connector, &asyc->state);
|
||||
asyc->dither.mode = DITHERING_MODE_AUTO;
|
||||
asyc->dither.depth = DITHERING_DEPTH_AUTO;
|
||||
asyc->scaler.mode = DRM_MODE_SCALE_NONE;
|
||||
asyc->scaler.underscan.mode = UNDERSCAN_OFF;
|
||||
asyc->procamp.color_vibrance = 150;
|
||||
asyc->procamp.vibrant_hue = 90;
|
||||
|
||||
if (nouveau_display(connector->dev)->disp.oclass < NV50_DISP) {
|
||||
switch (connector->connector_type) {
|
||||
case DRM_MODE_CONNECTOR_LVDS:
|
||||
/* See note in nouveau_conn_atomic_set_property(). */
|
||||
asyc->scaler.mode = DRM_MODE_SCALE_FULLSCREEN;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_conn_attach_properties(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct nouveau_conn_atom *armc = nouveau_conn_atom(connector->state);
|
||||
struct nouveau_display *disp = nouveau_display(dev);
|
||||
|
||||
/* Init DVI-I specific properties. */
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_DVII)
|
||||
drm_object_attach_property(&connector->base, dev->mode_config.
|
||||
dvi_i_subconnector_property, 0);
|
||||
|
||||
/* Add overscan compensation options to digital outputs. */
|
||||
if (disp->underscan_property &&
|
||||
(connector->connector_type == DRM_MODE_CONNECTOR_DVID ||
|
||||
connector->connector_type == DRM_MODE_CONNECTOR_DVII ||
|
||||
connector->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
|
||||
connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort)) {
|
||||
drm_object_attach_property(&connector->base,
|
||||
disp->underscan_property,
|
||||
UNDERSCAN_OFF);
|
||||
drm_object_attach_property(&connector->base,
|
||||
disp->underscan_hborder_property, 0);
|
||||
drm_object_attach_property(&connector->base,
|
||||
disp->underscan_vborder_property, 0);
|
||||
}
|
||||
|
||||
/* Add hue and saturation options. */
|
||||
if (disp->vibrant_hue_property)
|
||||
drm_object_attach_property(&connector->base,
|
||||
disp->vibrant_hue_property,
|
||||
armc->procamp.vibrant_hue);
|
||||
if (disp->color_vibrance_property)
|
||||
drm_object_attach_property(&connector->base,
|
||||
disp->color_vibrance_property,
|
||||
armc->procamp.color_vibrance);
|
||||
|
||||
/* Scaling mode property. */
|
||||
switch (connector->connector_type) {
|
||||
case DRM_MODE_CONNECTOR_TV:
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_VGA:
|
||||
if (disp->disp.oclass < NV50_DISP)
|
||||
break; /* Can only scale on DFPs. */
|
||||
/* Fall-through. */
|
||||
default:
|
||||
drm_object_attach_property(&connector->base, dev->mode_config.
|
||||
scaling_mode_property,
|
||||
armc->scaler.mode);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Dithering properties. */
|
||||
switch (connector->connector_type) {
|
||||
case DRM_MODE_CONNECTOR_TV:
|
||||
case DRM_MODE_CONNECTOR_VGA:
|
||||
break;
|
||||
default:
|
||||
if (disp->dithering_mode) {
|
||||
drm_object_attach_property(&connector->base,
|
||||
disp->dithering_mode,
|
||||
armc->dither.mode);
|
||||
}
|
||||
if (disp->dithering_depth) {
|
||||
drm_object_attach_property(&connector->base,
|
||||
disp->dithering_depth,
|
||||
armc->dither.depth);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MODULE_PARM_DESC(tv_disable, "Disable TV-out detection");
|
||||
int nouveau_tv_disable = 0;
|
||||
module_param_named(tv_disable, nouveau_tv_disable, int, 0400);
|
||||
@@ -151,7 +447,9 @@ nouveau_connector_ddc_detect(struct drm_connector *connector)
|
||||
|
||||
if (nv_encoder->dcb->type == DCB_OUTPUT_DP) {
|
||||
int ret = nouveau_dp_detect(nv_encoder);
|
||||
if (ret == 0)
|
||||
if (ret == NOUVEAU_DP_MST)
|
||||
return NULL;
|
||||
if (ret == NOUVEAU_DP_SST)
|
||||
break;
|
||||
} else
|
||||
if ((vga_switcheroo_handler_flags() &
|
||||
@@ -465,199 +763,39 @@ static int
|
||||
nouveau_connector_set_property(struct drm_connector *connector,
|
||||
struct drm_property *property, uint64_t value)
|
||||
{
|
||||
struct nouveau_display *disp = nouveau_display(connector->dev);
|
||||
struct nouveau_conn_atom *asyc = nouveau_conn_atom(connector->state);
|
||||
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
||||
struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
|
||||
struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct nouveau_crtc *nv_crtc;
|
||||
int ret;
|
||||
|
||||
nv_crtc = NULL;
|
||||
if (connector->encoder && connector->encoder->crtc)
|
||||
nv_crtc = nouveau_crtc(connector->encoder->crtc);
|
||||
if (connector->dev->mode_config.funcs->atomic_commit)
|
||||
return drm_atomic_helper_connector_set_property(connector, property, value);
|
||||
|
||||
/* Scaling mode */
|
||||
if (property == dev->mode_config.scaling_mode_property) {
|
||||
bool modeset = false;
|
||||
ret = connector->funcs->atomic_set_property(&nv_connector->base,
|
||||
&asyc->state,
|
||||
property, value);
|
||||
if (ret) {
|
||||
if (nv_encoder && nv_encoder->dcb->type == DCB_OUTPUT_TV)
|
||||
return get_slave_funcs(encoder)->set_property(
|
||||
encoder, connector, property, value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (value) {
|
||||
case DRM_MODE_SCALE_NONE:
|
||||
/* We allow 'None' for EDID modes, even on a fixed
|
||||
* panel (some exist with support for lower refresh
|
||||
* rates, which people might want to use for power
|
||||
* saving purposes).
|
||||
*
|
||||
* Non-EDID modes will force the use of GPU scaling
|
||||
* to the native mode regardless of this setting.
|
||||
*/
|
||||
switch (nv_connector->type) {
|
||||
case DCB_CONNECTOR_LVDS:
|
||||
case DCB_CONNECTOR_LVDS_SPWG:
|
||||
case DCB_CONNECTOR_eDP:
|
||||
/* ... except prior to G80, where the code
|
||||
* doesn't support such things.
|
||||
*/
|
||||
if (disp->disp.oclass < NV50_DISP)
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DRM_MODE_SCALE_FULLSCREEN:
|
||||
case DRM_MODE_SCALE_CENTER:
|
||||
case DRM_MODE_SCALE_ASPECT:
|
||||
break;
|
||||
default:
|
||||
nv_connector->scaling_mode = asyc->scaler.mode;
|
||||
nv_connector->dithering_mode = asyc->dither.mode;
|
||||
|
||||
if (connector->encoder && connector->encoder->crtc) {
|
||||
ret = drm_crtc_helper_set_mode(connector->encoder->crtc,
|
||||
&connector->encoder->crtc->mode,
|
||||
connector->encoder->crtc->x,
|
||||
connector->encoder->crtc->y,
|
||||
NULL);
|
||||
if (!ret)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Changing between GPU and panel scaling requires a full
|
||||
* modeset
|
||||
*/
|
||||
if ((nv_connector->scaling_mode == DRM_MODE_SCALE_NONE) ||
|
||||
(value == DRM_MODE_SCALE_NONE))
|
||||
modeset = true;
|
||||
nv_connector->scaling_mode = value;
|
||||
|
||||
if (!nv_crtc)
|
||||
return 0;
|
||||
|
||||
if (modeset || !nv_crtc->set_scale) {
|
||||
ret = drm_crtc_helper_set_mode(&nv_crtc->base,
|
||||
&nv_crtc->base.mode,
|
||||
nv_crtc->base.x,
|
||||
nv_crtc->base.y, NULL);
|
||||
if (!ret)
|
||||
return -EINVAL;
|
||||
} else {
|
||||
ret = nv_crtc->set_scale(nv_crtc, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Underscan */
|
||||
if (property == disp->underscan_property) {
|
||||
if (nv_connector->underscan != value) {
|
||||
nv_connector->underscan = value;
|
||||
if (!nv_crtc || !nv_crtc->set_scale)
|
||||
return 0;
|
||||
|
||||
return nv_crtc->set_scale(nv_crtc, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (property == disp->underscan_hborder_property) {
|
||||
if (nv_connector->underscan_hborder != value) {
|
||||
nv_connector->underscan_hborder = value;
|
||||
if (!nv_crtc || !nv_crtc->set_scale)
|
||||
return 0;
|
||||
|
||||
return nv_crtc->set_scale(nv_crtc, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (property == disp->underscan_vborder_property) {
|
||||
if (nv_connector->underscan_vborder != value) {
|
||||
nv_connector->underscan_vborder = value;
|
||||
if (!nv_crtc || !nv_crtc->set_scale)
|
||||
return 0;
|
||||
|
||||
return nv_crtc->set_scale(nv_crtc, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Dithering */
|
||||
if (property == disp->dithering_mode) {
|
||||
nv_connector->dithering_mode = value;
|
||||
if (!nv_crtc || !nv_crtc->set_dither)
|
||||
return 0;
|
||||
|
||||
return nv_crtc->set_dither(nv_crtc, true);
|
||||
}
|
||||
|
||||
if (property == disp->dithering_depth) {
|
||||
nv_connector->dithering_depth = value;
|
||||
if (!nv_crtc || !nv_crtc->set_dither)
|
||||
return 0;
|
||||
|
||||
return nv_crtc->set_dither(nv_crtc, true);
|
||||
}
|
||||
|
||||
if (nv_crtc && nv_crtc->set_color_vibrance) {
|
||||
/* Hue */
|
||||
if (property == disp->vibrant_hue_property) {
|
||||
nv_crtc->vibrant_hue = value - 90;
|
||||
return nv_crtc->set_color_vibrance(nv_crtc, true);
|
||||
}
|
||||
/* Saturation */
|
||||
if (property == disp->color_vibrance_property) {
|
||||
nv_crtc->color_vibrance = value - 100;
|
||||
return nv_crtc->set_color_vibrance(nv_crtc, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (nv_encoder && nv_encoder->dcb->type == DCB_OUTPUT_TV)
|
||||
return get_slave_funcs(encoder)->set_property(
|
||||
encoder, connector, property, value);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct drm_display_mode *
|
||||
nouveau_connector_native_mode(struct drm_connector *connector)
|
||||
{
|
||||
const struct drm_connector_helper_funcs *helper = connector->helper_private;
|
||||
struct nouveau_drm *drm = nouveau_drm(connector->dev);
|
||||
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_display_mode *mode, *largest = NULL;
|
||||
int high_w = 0, high_h = 0, high_v = 0;
|
||||
|
||||
list_for_each_entry(mode, &nv_connector->base.probed_modes, head) {
|
||||
mode->vrefresh = drm_mode_vrefresh(mode);
|
||||
if (helper->mode_valid(connector, mode) != MODE_OK ||
|
||||
(mode->flags & DRM_MODE_FLAG_INTERLACE))
|
||||
continue;
|
||||
|
||||
/* Use preferred mode if there is one.. */
|
||||
if (mode->type & DRM_MODE_TYPE_PREFERRED) {
|
||||
NV_DEBUG(drm, "native mode from preferred\n");
|
||||
return drm_mode_duplicate(dev, mode);
|
||||
}
|
||||
|
||||
/* Otherwise, take the resolution with the largest width, then
|
||||
* height, then vertical refresh
|
||||
*/
|
||||
if (mode->hdisplay < high_w)
|
||||
continue;
|
||||
|
||||
if (mode->hdisplay == high_w && mode->vdisplay < high_h)
|
||||
continue;
|
||||
|
||||
if (mode->hdisplay == high_w && mode->vdisplay == high_h &&
|
||||
mode->vrefresh < high_v)
|
||||
continue;
|
||||
|
||||
high_w = mode->hdisplay;
|
||||
high_h = mode->vdisplay;
|
||||
high_v = mode->vrefresh;
|
||||
largest = mode;
|
||||
}
|
||||
|
||||
NV_DEBUG(drm, "native mode from largest: %dx%d@%d\n",
|
||||
high_w, high_h, high_v);
|
||||
return largest ? drm_mode_duplicate(dev, largest) : NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct moderec {
|
||||
@@ -805,8 +943,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
|
||||
* the list of modes.
|
||||
*/
|
||||
if (!nv_connector->native_mode)
|
||||
nv_connector->native_mode =
|
||||
nouveau_connector_native_mode(connector);
|
||||
nv_connector->native_mode = nouveau_conn_native_mode(connector);
|
||||
if (ret == 0 && nv_connector->native_mode) {
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
@@ -934,56 +1071,42 @@ nouveau_connector_helper_funcs = {
|
||||
.best_encoder = nouveau_connector_best_encoder,
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs
|
||||
nouveau_connector_funcs = {
|
||||
.dpms = drm_helper_connector_dpms,
|
||||
.detect = nouveau_connector_detect,
|
||||
.destroy = nouveau_connector_destroy,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.set_property = nouveau_connector_set_property,
|
||||
.force = nouveau_connector_force
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs
|
||||
nouveau_connector_funcs_lvds = {
|
||||
.dpms = drm_helper_connector_dpms,
|
||||
.detect = nouveau_connector_detect_lvds,
|
||||
.destroy = nouveau_connector_destroy,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.set_property = nouveau_connector_set_property,
|
||||
.force = nouveau_connector_force
|
||||
};
|
||||
|
||||
static int
|
||||
nouveau_connector_dp_dpms(struct drm_connector *connector, int mode)
|
||||
nouveau_connector_dpms(struct drm_connector *connector, int mode)
|
||||
{
|
||||
struct nouveau_encoder *nv_encoder = NULL;
|
||||
|
||||
if (connector->encoder)
|
||||
nv_encoder = nouveau_encoder(connector->encoder);
|
||||
if (nv_encoder && nv_encoder->dcb &&
|
||||
nv_encoder->dcb->type == DCB_OUTPUT_DP) {
|
||||
if (mode == DRM_MODE_DPMS_ON) {
|
||||
u8 data = DP_SET_POWER_D0;
|
||||
nvkm_wraux(nv_encoder->aux, DP_SET_POWER, &data, 1);
|
||||
usleep_range(1000, 2000);
|
||||
} else {
|
||||
u8 data = DP_SET_POWER_D3;
|
||||
nvkm_wraux(nv_encoder->aux, DP_SET_POWER, &data, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (connector->dev->mode_config.funcs->atomic_commit)
|
||||
return drm_atomic_helper_connector_dpms(connector, mode);
|
||||
return drm_helper_connector_dpms(connector, mode);
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs
|
||||
nouveau_connector_funcs_dp = {
|
||||
.dpms = nouveau_connector_dp_dpms,
|
||||
nouveau_connector_funcs = {
|
||||
.dpms = nouveau_connector_dpms,
|
||||
.reset = nouveau_conn_reset,
|
||||
.detect = nouveau_connector_detect,
|
||||
.destroy = nouveau_connector_destroy,
|
||||
.force = nouveau_connector_force,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.set_property = nouveau_connector_set_property,
|
||||
.force = nouveau_connector_force
|
||||
.destroy = nouveau_connector_destroy,
|
||||
.atomic_duplicate_state = nouveau_conn_atomic_duplicate_state,
|
||||
.atomic_destroy_state = nouveau_conn_atomic_destroy_state,
|
||||
.atomic_set_property = nouveau_conn_atomic_set_property,
|
||||
.atomic_get_property = nouveau_conn_atomic_get_property,
|
||||
};
|
||||
|
||||
static const struct drm_connector_funcs
|
||||
nouveau_connector_funcs_lvds = {
|
||||
.dpms = nouveau_connector_dpms,
|
||||
.reset = nouveau_conn_reset,
|
||||
.detect = nouveau_connector_detect_lvds,
|
||||
.force = nouveau_connector_force,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.set_property = nouveau_connector_set_property,
|
||||
.destroy = nouveau_connector_destroy,
|
||||
.atomic_duplicate_state = nouveau_conn_atomic_duplicate_state,
|
||||
.atomic_destroy_state = nouveau_conn_atomic_destroy_state,
|
||||
.atomic_set_property = nouveau_conn_atomic_set_property,
|
||||
.atomic_get_property = nouveau_conn_atomic_get_property,
|
||||
};
|
||||
|
||||
static int
|
||||
@@ -995,19 +1118,20 @@ nouveau_connector_hotplug(struct nvif_notify *notify)
|
||||
struct nouveau_drm *drm = nouveau_drm(connector->dev);
|
||||
const struct nvif_notify_conn_rep_v0 *rep = notify->data;
|
||||
const char *name = connector->name;
|
||||
struct nouveau_encoder *nv_encoder;
|
||||
|
||||
if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) {
|
||||
NV_DEBUG(drm, "service %s\n", name);
|
||||
if ((nv_encoder = find_encoder(connector, DCB_OUTPUT_DP)))
|
||||
nv50_mstm_service(nv_encoder->dp.mstm);
|
||||
} else {
|
||||
bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG);
|
||||
|
||||
NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name);
|
||||
|
||||
mutex_lock(&drm->dev->mode_config.mutex);
|
||||
if (plugged)
|
||||
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
|
||||
else
|
||||
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
|
||||
mutex_unlock(&drm->dev->mode_config.mutex);
|
||||
if ((nv_encoder = find_encoder(connector, DCB_OUTPUT_DP))) {
|
||||
if (!plugged)
|
||||
nv50_mstm_remove(nv_encoder->dp.mstm);
|
||||
}
|
||||
|
||||
drm_helper_hpd_irq_event(connector->dev);
|
||||
}
|
||||
@@ -1188,7 +1312,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
funcs = &nouveau_connector_funcs_dp;
|
||||
funcs = &nouveau_connector_funcs;
|
||||
break;
|
||||
default:
|
||||
funcs = &nouveau_connector_funcs;
|
||||
@@ -1202,38 +1326,10 @@ nouveau_connector_create(struct drm_device *dev, int index)
|
||||
drm_connector_init(dev, connector, funcs, type);
|
||||
drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
|
||||
|
||||
/* Init DVI-I specific properties */
|
||||
if (nv_connector->type == DCB_CONNECTOR_DVI_I)
|
||||
drm_object_attach_property(&connector->base, dev->mode_config.dvi_i_subconnector_property, 0);
|
||||
connector->funcs->reset(connector);
|
||||
nouveau_conn_attach_properties(connector);
|
||||
|
||||
/* Add overscan compensation options to digital outputs */
|
||||
if (disp->underscan_property &&
|
||||
(type == DRM_MODE_CONNECTOR_DVID ||
|
||||
type == DRM_MODE_CONNECTOR_DVII ||
|
||||
type == DRM_MODE_CONNECTOR_HDMIA ||
|
||||
type == DRM_MODE_CONNECTOR_DisplayPort)) {
|
||||
drm_object_attach_property(&connector->base,
|
||||
disp->underscan_property,
|
||||
UNDERSCAN_OFF);
|
||||
drm_object_attach_property(&connector->base,
|
||||
disp->underscan_hborder_property,
|
||||
0);
|
||||
drm_object_attach_property(&connector->base,
|
||||
disp->underscan_vborder_property,
|
||||
0);
|
||||
}
|
||||
|
||||
/* Add hue and saturation options */
|
||||
if (disp->vibrant_hue_property)
|
||||
drm_object_attach_property(&connector->base,
|
||||
disp->vibrant_hue_property,
|
||||
90);
|
||||
if (disp->color_vibrance_property)
|
||||
drm_object_attach_property(&connector->base,
|
||||
disp->color_vibrance_property,
|
||||
150);
|
||||
|
||||
/* default scaling mode */
|
||||
/* Default scaling mode */
|
||||
switch (nv_connector->type) {
|
||||
case DCB_CONNECTOR_LVDS:
|
||||
case DCB_CONNECTOR_LVDS_SPWG:
|
||||
@@ -1250,23 +1346,6 @@ nouveau_connector_create(struct drm_device *dev, int index)
|
||||
break;
|
||||
}
|
||||
|
||||
/* scaling mode property */
|
||||
switch (nv_connector->type) {
|
||||
case DCB_CONNECTOR_TV_0:
|
||||
case DCB_CONNECTOR_TV_1:
|
||||
case DCB_CONNECTOR_TV_3:
|
||||
break;
|
||||
case DCB_CONNECTOR_VGA:
|
||||
if (disp->disp.oclass < NV50_DISP)
|
||||
break; /* can only scale on DFPs */
|
||||
/* fall-through */
|
||||
default:
|
||||
drm_object_attach_property(&connector->base, dev->mode_config.
|
||||
scaling_mode_property,
|
||||
nv_connector->scaling_mode);
|
||||
break;
|
||||
}
|
||||
|
||||
/* dithering properties */
|
||||
switch (nv_connector->type) {
|
||||
case DCB_CONNECTOR_TV_0:
|
||||
@@ -1275,20 +1354,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
|
||||
case DCB_CONNECTOR_VGA:
|
||||
break;
|
||||
default:
|
||||
if (disp->dithering_mode) {
|
||||
nv_connector->dithering_mode = DITHERING_MODE_AUTO;
|
||||
drm_object_attach_property(&connector->base,
|
||||
disp->dithering_mode,
|
||||
nv_connector->
|
||||
dithering_mode);
|
||||
}
|
||||
if (disp->dithering_depth) {
|
||||
nv_connector->dithering_depth = DITHERING_DEPTH_AUTO;
|
||||
drm_object_attach_property(&connector->base,
|
||||
disp->dithering_depth,
|
||||
nv_connector->
|
||||
dithering_depth);
|
||||
}
|
||||
nv_connector->dithering_mode = DITHERING_MODE_AUTO;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,30 +35,6 @@
|
||||
|
||||
struct nvkm_i2c_port;
|
||||
|
||||
enum nouveau_underscan_type {
|
||||
UNDERSCAN_OFF,
|
||||
UNDERSCAN_ON,
|
||||
UNDERSCAN_AUTO,
|
||||
};
|
||||
|
||||
/* the enum values specifically defined here match nv50/nvd0 hw values, and
|
||||
* the code relies on this
|
||||
*/
|
||||
enum nouveau_dithering_mode {
|
||||
DITHERING_MODE_OFF = 0x00,
|
||||
DITHERING_MODE_ON = 0x01,
|
||||
DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
|
||||
DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
|
||||
DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
|
||||
DITHERING_MODE_AUTO
|
||||
};
|
||||
|
||||
enum nouveau_dithering_depth {
|
||||
DITHERING_DEPTH_6BPC = 0x00,
|
||||
DITHERING_DEPTH_8BPC = 0x02,
|
||||
DITHERING_DEPTH_AUTO
|
||||
};
|
||||
|
||||
struct nouveau_connector {
|
||||
struct drm_connector base;
|
||||
enum dcb_connector_type type;
|
||||
@@ -70,12 +46,7 @@ struct nouveau_connector {
|
||||
struct drm_dp_aux aux;
|
||||
|
||||
int dithering_mode;
|
||||
int dithering_depth;
|
||||
int scaling_mode;
|
||||
bool scaling_full;
|
||||
enum nouveau_underscan_type underscan;
|
||||
u32 underscan_hborder;
|
||||
u32 underscan_vborder;
|
||||
|
||||
struct nouveau_encoder *detected_encoder;
|
||||
struct edid *edid;
|
||||
@@ -109,5 +80,74 @@ nouveau_connector_create(struct drm_device *, int index);
|
||||
extern int nouveau_tv_disable;
|
||||
extern int nouveau_ignorelid;
|
||||
extern int nouveau_duallink;
|
||||
extern int nouveau_hdmimhz;
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#define nouveau_conn_atom(p) \
|
||||
container_of((p), struct nouveau_conn_atom, state)
|
||||
|
||||
struct nouveau_conn_atom {
|
||||
struct drm_connector_state state;
|
||||
|
||||
struct {
|
||||
/* The enum values specifically defined here match nv50/gf119
|
||||
* hw values, and the code relies on this.
|
||||
*/
|
||||
enum {
|
||||
DITHERING_MODE_OFF = 0x00,
|
||||
DITHERING_MODE_ON = 0x01,
|
||||
DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
|
||||
DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
|
||||
DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
|
||||
DITHERING_MODE_AUTO
|
||||
} mode;
|
||||
enum {
|
||||
DITHERING_DEPTH_6BPC = 0x00,
|
||||
DITHERING_DEPTH_8BPC = 0x02,
|
||||
DITHERING_DEPTH_AUTO
|
||||
} depth;
|
||||
} dither;
|
||||
|
||||
struct {
|
||||
int mode; /* DRM_MODE_SCALE_* */
|
||||
struct {
|
||||
enum {
|
||||
UNDERSCAN_OFF,
|
||||
UNDERSCAN_ON,
|
||||
UNDERSCAN_AUTO,
|
||||
} mode;
|
||||
u32 hborder;
|
||||
u32 vborder;
|
||||
} underscan;
|
||||
bool full;
|
||||
} scaler;
|
||||
|
||||
struct {
|
||||
int color_vibrance;
|
||||
int vibrant_hue;
|
||||
} procamp;
|
||||
|
||||
union {
|
||||
struct {
|
||||
bool dither:1;
|
||||
bool scaler:1;
|
||||
bool procamp:1;
|
||||
};
|
||||
u8 mask;
|
||||
} set;
|
||||
};
|
||||
|
||||
void nouveau_conn_attach_properties(struct drm_connector *);
|
||||
void nouveau_conn_reset(struct drm_connector *);
|
||||
struct drm_connector_state *
|
||||
nouveau_conn_atomic_duplicate_state(struct drm_connector *);
|
||||
void nouveau_conn_atomic_destroy_state(struct drm_connector *,
|
||||
struct drm_connector_state *);
|
||||
int nouveau_conn_atomic_set_property(struct drm_connector *,
|
||||
struct drm_connector_state *,
|
||||
struct drm_property *, u64);
|
||||
int nouveau_conn_atomic_get_property(struct drm_connector *,
|
||||
const struct drm_connector_state *,
|
||||
struct drm_property *, u64 *);
|
||||
struct drm_display_mode *nouveau_conn_native_mode(struct drm_connector *);
|
||||
#endif /* __NOUVEAU_CONNECTOR_H__ */
|
||||
|
||||
@@ -38,8 +38,6 @@ struct nouveau_crtc {
|
||||
uint32_t dpms_saved_fp_control;
|
||||
uint32_t fp_users;
|
||||
int saturation;
|
||||
int color_vibrance;
|
||||
int vibrant_hue;
|
||||
int sharpness;
|
||||
int last_dpms;
|
||||
|
||||
@@ -54,7 +52,6 @@ struct nouveau_crtc {
|
||||
|
||||
struct {
|
||||
struct nouveau_bo *nvbo;
|
||||
bool visible;
|
||||
uint32_t offset;
|
||||
void (*set_offset)(struct nouveau_crtc *, uint32_t offset);
|
||||
void (*set_pos)(struct nouveau_crtc *, int x, int y);
|
||||
@@ -70,10 +67,6 @@ struct nouveau_crtc {
|
||||
int depth;
|
||||
} lut;
|
||||
|
||||
int (*set_dither)(struct nouveau_crtc *crtc, bool update);
|
||||
int (*set_scale)(struct nouveau_crtc *crtc, bool update);
|
||||
int (*set_color_vibrance)(struct nouveau_crtc *crtc, bool update);
|
||||
|
||||
void (*save)(struct drm_crtc *crtc);
|
||||
void (*restore)(struct drm_crtc *crtc);
|
||||
};
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
*/
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
|
||||
#include <nvif/class.h>
|
||||
@@ -92,7 +94,7 @@ calc(int blanks, int blanke, int total, int line)
|
||||
return line;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
|
||||
ktime_t *stime, ktime_t *etime)
|
||||
{
|
||||
@@ -158,9 +160,13 @@ nouveau_display_vblstamp(struct drm_device *dev, unsigned int pipe,
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
if (nouveau_crtc(crtc)->index == pipe) {
|
||||
struct drm_display_mode *mode;
|
||||
if (dev->mode_config.funcs->atomic_commit)
|
||||
mode = &crtc->state->adjusted_mode;
|
||||
else
|
||||
mode = &crtc->hwmode;
|
||||
return drm_calc_vbltimestamp_from_scanoutpos(dev,
|
||||
pipe, max_error, time, flags,
|
||||
&crtc->hwmode);
|
||||
pipe, max_error, time, flags, mode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,10 +223,6 @@ static void
|
||||
nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
|
||||
{
|
||||
struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
|
||||
struct nouveau_display *disp = nouveau_display(drm_fb->dev);
|
||||
|
||||
if (disp->fb_dtor)
|
||||
disp->fb_dtor(drm_fb);
|
||||
|
||||
if (fb->nvbo)
|
||||
drm_gem_object_unreference_unlocked(&fb->nvbo->gem);
|
||||
@@ -245,57 +247,45 @@ static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = {
|
||||
};
|
||||
|
||||
int
|
||||
nouveau_framebuffer_init(struct drm_device *dev,
|
||||
struct nouveau_framebuffer *nv_fb,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct nouveau_bo *nvbo)
|
||||
nouveau_framebuffer_new(struct drm_device *dev,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct nouveau_bo *nvbo,
|
||||
struct nouveau_framebuffer **pfb)
|
||||
{
|
||||
struct nouveau_display *disp = nouveau_display(dev);
|
||||
struct drm_framebuffer *fb = &nv_fb->base;
|
||||
struct nouveau_framebuffer *fb;
|
||||
int ret;
|
||||
|
||||
drm_helper_mode_fill_fb_struct(fb, mode_cmd);
|
||||
nv_fb->nvbo = nvbo;
|
||||
if (!(fb = *pfb = kzalloc(sizeof(*fb), GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
|
||||
ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs);
|
||||
drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
|
||||
fb->nvbo = nvbo;
|
||||
|
||||
ret = drm_framebuffer_init(dev, &fb->base, &nouveau_framebuffer_funcs);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (disp->fb_ctor) {
|
||||
ret = disp->fb_ctor(fb);
|
||||
if (ret)
|
||||
disp->fb_dtor(fb);
|
||||
}
|
||||
|
||||
kfree(fb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct drm_framebuffer *
|
||||
struct drm_framebuffer *
|
||||
nouveau_user_framebuffer_create(struct drm_device *dev,
|
||||
struct drm_file *file_priv,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
struct nouveau_framebuffer *nouveau_fb;
|
||||
struct nouveau_framebuffer *fb;
|
||||
struct nouveau_bo *nvbo;
|
||||
struct drm_gem_object *gem;
|
||||
int ret = -ENOMEM;
|
||||
int ret;
|
||||
|
||||
gem = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
|
||||
if (!gem)
|
||||
return ERR_PTR(-ENOENT);
|
||||
nvbo = nouveau_gem_object(gem);
|
||||
|
||||
nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL);
|
||||
if (!nouveau_fb)
|
||||
goto err_unref;
|
||||
ret = nouveau_framebuffer_new(dev, mode_cmd, nvbo, &fb);
|
||||
if (ret == 0)
|
||||
return &fb->base;
|
||||
|
||||
ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem));
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
return &nouveau_fb->base;
|
||||
|
||||
err:
|
||||
kfree(nouveau_fb);
|
||||
err_unref:
|
||||
drm_gem_object_unreference_unlocked(gem);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
@@ -385,13 +375,16 @@ nouveau_display_init(struct drm_device *dev)
|
||||
}
|
||||
|
||||
void
|
||||
nouveau_display_fini(struct drm_device *dev)
|
||||
nouveau_display_fini(struct drm_device *dev, bool suspend)
|
||||
{
|
||||
struct nouveau_display *disp = nouveau_display(dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct drm_connector *connector;
|
||||
int head;
|
||||
|
||||
if (!suspend)
|
||||
drm_crtc_force_disable_all(dev);
|
||||
|
||||
/* Make sure that drm and hw vblank irqs get properly disabled. */
|
||||
for (head = 0; head < dev->mode_config.num_crtc; head++)
|
||||
drm_vblank_off(dev, head);
|
||||
@@ -530,6 +523,8 @@ nouveau_display_create(struct drm_device *dev)
|
||||
if (ret)
|
||||
goto disp_create_err;
|
||||
|
||||
drm_mode_config_reset(dev);
|
||||
|
||||
if (dev->mode_config.num_crtc) {
|
||||
ret = nouveau_display_vblank_init(dev);
|
||||
if (ret)
|
||||
@@ -556,7 +551,6 @@ nouveau_display_destroy(struct drm_device *dev)
|
||||
nouveau_display_vblank_fini(dev);
|
||||
|
||||
drm_kms_helper_poll_fini(dev);
|
||||
drm_crtc_force_disable_all(dev);
|
||||
drm_mode_config_cleanup(dev);
|
||||
|
||||
if (disp->dtor)
|
||||
@@ -568,12 +562,138 @@ nouveau_display_destroy(struct drm_device *dev)
|
||||
kfree(disp);
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_atomic_disable_connector(struct drm_atomic_state *state,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_connector_state *connector_state;
|
||||
struct drm_crtc *crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_plane_state *plane_state;
|
||||
struct drm_plane *plane;
|
||||
int ret;
|
||||
|
||||
if (!(crtc = connector->state->crtc))
|
||||
return 0;
|
||||
|
||||
connector_state = drm_atomic_get_connector_state(state, connector);
|
||||
if (IS_ERR(connector_state))
|
||||
return PTR_ERR(connector_state);
|
||||
|
||||
ret = drm_atomic_set_crtc_for_connector(connector_state, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
||||
if (IS_ERR(crtc_state))
|
||||
return PTR_ERR(crtc_state);
|
||||
|
||||
ret = drm_atomic_set_mode_for_crtc(crtc_state, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
crtc_state->active = false;
|
||||
|
||||
drm_for_each_plane_mask(plane, connector->dev, crtc_state->plane_mask) {
|
||||
plane_state = drm_atomic_get_plane_state(state, plane);
|
||||
if (IS_ERR(plane_state))
|
||||
return PTR_ERR(plane_state);
|
||||
|
||||
ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_atomic_set_fb_for_plane(plane_state, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_atomic_disable(struct drm_device *dev,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_connector *connector;
|
||||
int ret;
|
||||
|
||||
state = drm_atomic_state_alloc(dev);
|
||||
if (!state)
|
||||
return -ENOMEM;
|
||||
|
||||
state->acquire_ctx = ctx;
|
||||
|
||||
drm_for_each_connector(connector, dev) {
|
||||
ret = nouveau_atomic_disable_connector(state, connector);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
ret = drm_atomic_commit(state);
|
||||
drm_atomic_state_put(state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct drm_atomic_state *
|
||||
nouveau_atomic_suspend(struct drm_device *dev)
|
||||
{
|
||||
struct drm_modeset_acquire_ctx ctx;
|
||||
struct drm_atomic_state *state;
|
||||
int ret;
|
||||
|
||||
drm_modeset_acquire_init(&ctx, 0);
|
||||
|
||||
retry:
|
||||
ret = drm_modeset_lock_all_ctx(dev, &ctx);
|
||||
if (ret < 0) {
|
||||
state = ERR_PTR(ret);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
state = drm_atomic_helper_duplicate_state(dev, &ctx);
|
||||
if (IS_ERR(state))
|
||||
goto unlock;
|
||||
|
||||
ret = nouveau_atomic_disable(dev, &ctx);
|
||||
if (ret < 0) {
|
||||
drm_atomic_state_put(state);
|
||||
state = ERR_PTR(ret);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
unlock:
|
||||
if (PTR_ERR(state) == -EDEADLK) {
|
||||
drm_modeset_backoff(&ctx);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
drm_modeset_drop_locks(&ctx);
|
||||
drm_modeset_acquire_fini(&ctx);
|
||||
return state;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_display_suspend(struct drm_device *dev, bool runtime)
|
||||
{
|
||||
struct nouveau_display *disp = nouveau_display(dev);
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
nouveau_display_fini(dev);
|
||||
if (dev->mode_config.funcs->atomic_commit) {
|
||||
if (!runtime) {
|
||||
disp->suspend = nouveau_atomic_suspend(dev);
|
||||
if (IS_ERR(disp->suspend)) {
|
||||
int ret = PTR_ERR(disp->suspend);
|
||||
disp->suspend = NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
nouveau_display_fini(dev, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nouveau_display_fini(dev, true);
|
||||
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct nouveau_framebuffer *nouveau_fb;
|
||||
@@ -600,10 +720,20 @@ nouveau_display_suspend(struct drm_device *dev, bool runtime)
|
||||
void
|
||||
nouveau_display_resume(struct drm_device *dev, bool runtime)
|
||||
{
|
||||
struct nouveau_display *disp = nouveau_display(dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct drm_crtc *crtc;
|
||||
int ret, head;
|
||||
|
||||
if (dev->mode_config.funcs->atomic_commit) {
|
||||
nouveau_display_init(dev);
|
||||
if (disp->suspend) {
|
||||
drm_atomic_helper_resume(dev, disp->suspend);
|
||||
disp->suspend = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* re-pin fb/cursors */
|
||||
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
|
||||
struct nouveau_framebuffer *nouveau_fb;
|
||||
@@ -692,10 +822,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
if (drm->device.info.family < NV_DEVICE_INFO_V0_FERMI)
|
||||
BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
|
||||
else
|
||||
BEGIN_NVC0(chan, FermiSw, NV_SW_PAGE_FLIP, 1);
|
||||
BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
|
||||
OUT_RING (chan, 0x00000000);
|
||||
FIRE_RING (chan);
|
||||
|
||||
@@ -724,6 +851,8 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
||||
struct nouveau_channel *chan;
|
||||
struct nouveau_cli *cli;
|
||||
struct nouveau_fence *fence;
|
||||
struct nv04_display *dispnv04 = nv04_display(dev);
|
||||
int head = nouveau_crtc(crtc)->index;
|
||||
int ret;
|
||||
|
||||
chan = drm->channel;
|
||||
@@ -770,32 +899,23 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
||||
drm_crtc_vblank_get(crtc);
|
||||
|
||||
/* Emit a page flip */
|
||||
if (drm->device.info.family >= NV_DEVICE_INFO_V0_TESLA) {
|
||||
ret = nv50_display_flip_next(crtc, fb, chan, swap_interval);
|
||||
if (swap_interval) {
|
||||
ret = RING_SPACE(chan, 8);
|
||||
if (ret)
|
||||
goto fail_unreserve;
|
||||
} else {
|
||||
struct nv04_display *dispnv04 = nv04_display(dev);
|
||||
int head = nouveau_crtc(crtc)->index;
|
||||
|
||||
if (swap_interval) {
|
||||
ret = RING_SPACE(chan, 8);
|
||||
if (ret)
|
||||
goto fail_unreserve;
|
||||
|
||||
BEGIN_NV04(chan, NvSubImageBlit, 0x012c, 1);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_NV04(chan, NvSubImageBlit, 0x0134, 1);
|
||||
OUT_RING (chan, head);
|
||||
BEGIN_NV04(chan, NvSubImageBlit, 0x0100, 1);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_NV04(chan, NvSubImageBlit, 0x0130, 1);
|
||||
OUT_RING (chan, 0);
|
||||
}
|
||||
|
||||
nouveau_bo_ref(new_bo, &dispnv04->image[head]);
|
||||
BEGIN_NV04(chan, NvSubImageBlit, 0x012c, 1);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_NV04(chan, NvSubImageBlit, 0x0134, 1);
|
||||
OUT_RING (chan, head);
|
||||
BEGIN_NV04(chan, NvSubImageBlit, 0x0100, 1);
|
||||
OUT_RING (chan, 0);
|
||||
BEGIN_NV04(chan, NvSubImageBlit, 0x0130, 1);
|
||||
OUT_RING (chan, 0);
|
||||
}
|
||||
|
||||
nouveau_bo_ref(new_bo, &dispnv04->image[head]);
|
||||
|
||||
ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
|
||||
if (ret)
|
||||
goto fail_unreserve;
|
||||
@@ -843,16 +963,8 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
|
||||
|
||||
s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
|
||||
if (s->event) {
|
||||
if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
|
||||
drm_crtc_arm_vblank_event(s->crtc, s->event);
|
||||
} else {
|
||||
drm_crtc_send_vblank_event(s->crtc, s->event);
|
||||
|
||||
/* Give up ownership of vblank for page-flipped crtc */
|
||||
drm_crtc_vblank_put(s->crtc);
|
||||
}
|
||||
}
|
||||
else {
|
||||
drm_crtc_arm_vblank_event(s->crtc, s->event);
|
||||
} else {
|
||||
/* Give up ownership of vblank for page-flipped crtc */
|
||||
drm_crtc_vblank_put(s->crtc);
|
||||
}
|
||||
@@ -874,12 +986,10 @@ nouveau_flip_complete(struct nvif_notify *notify)
|
||||
struct nouveau_page_flip_state state;
|
||||
|
||||
if (!nouveau_finish_page_flip(chan, &state)) {
|
||||
if (drm->device.info.family < NV_DEVICE_INFO_V0_TESLA) {
|
||||
nv_set_crtc_base(drm->dev, drm_crtc_index(state.crtc),
|
||||
state.offset + state.crtc->y *
|
||||
state.pitch + state.crtc->x *
|
||||
state.bpp / 8);
|
||||
}
|
||||
nv_set_crtc_base(drm->dev, drm_crtc_index(state.crtc),
|
||||
state.offset + state.crtc->y *
|
||||
state.pitch + state.crtc->x *
|
||||
state.bpp / 8);
|
||||
}
|
||||
|
||||
return NVIF_NOTIFY_KEEP;
|
||||
|
||||
@@ -22,8 +22,9 @@ nouveau_framebuffer(struct drm_framebuffer *fb)
|
||||
return container_of(fb, struct nouveau_framebuffer, base);
|
||||
}
|
||||
|
||||
int nouveau_framebuffer_init(struct drm_device *, struct nouveau_framebuffer *,
|
||||
const struct drm_mode_fb_cmd2 *, struct nouveau_bo *);
|
||||
int nouveau_framebuffer_new(struct drm_device *,
|
||||
const struct drm_mode_fb_cmd2 *,
|
||||
struct nouveau_bo *, struct nouveau_framebuffer **);
|
||||
|
||||
struct nouveau_page_flip_state {
|
||||
struct list_head head;
|
||||
@@ -39,9 +40,6 @@ struct nouveau_display {
|
||||
int (*init)(struct drm_device *);
|
||||
void (*fini)(struct drm_device *);
|
||||
|
||||
int (*fb_ctor)(struct drm_framebuffer *);
|
||||
void (*fb_dtor)(struct drm_framebuffer *);
|
||||
|
||||
struct nvif_object disp;
|
||||
|
||||
struct drm_property *dithering_mode;
|
||||
@@ -52,6 +50,8 @@ struct nouveau_display {
|
||||
/* not really hue and saturation: */
|
||||
struct drm_property *vibrant_hue_property;
|
||||
struct drm_property *color_vibrance_property;
|
||||
|
||||
struct drm_atomic_state *suspend;
|
||||
};
|
||||
|
||||
static inline struct nouveau_display *
|
||||
@@ -63,7 +63,7 @@ nouveau_display(struct drm_device *dev)
|
||||
int nouveau_display_create(struct drm_device *dev);
|
||||
void nouveau_display_destroy(struct drm_device *dev);
|
||||
int nouveau_display_init(struct drm_device *dev);
|
||||
void nouveau_display_fini(struct drm_device *dev);
|
||||
void nouveau_display_fini(struct drm_device *dev, bool suspend);
|
||||
int nouveau_display_suspend(struct drm_device *dev, bool runtime);
|
||||
void nouveau_display_resume(struct drm_device *dev, bool runtime);
|
||||
int nouveau_display_vblank_enable(struct drm_device *, unsigned int);
|
||||
@@ -103,4 +103,7 @@ nouveau_backlight_exit(struct drm_device *dev) {
|
||||
}
|
||||
#endif
|
||||
|
||||
struct drm_framebuffer *
|
||||
nouveau_user_framebuffer_create(struct drm_device *, struct drm_file *,
|
||||
const struct drm_mode_fb_cmd2 *);
|
||||
#endif
|
||||
|
||||
@@ -30,6 +30,13 @@
|
||||
#include "nouveau_encoder.h"
|
||||
#include "nouveau_crtc.h"
|
||||
|
||||
#include <nvif/class.h>
|
||||
#include <nvif/cl5070.h>
|
||||
|
||||
MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream (default: enabled)");
|
||||
static int nouveau_mst = 1;
|
||||
module_param_named(mst, nouveau_mst, int, 0400);
|
||||
|
||||
static void
|
||||
nouveau_dp_probe_oui(struct drm_device *dev, struct nvkm_i2c_aux *aux, u8 *dpcd)
|
||||
{
|
||||
@@ -55,14 +62,14 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder)
|
||||
struct drm_device *dev = nv_encoder->base.base.dev;
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct nvkm_i2c_aux *aux;
|
||||
u8 *dpcd = nv_encoder->dp.dpcd;
|
||||
u8 dpcd[8];
|
||||
int ret;
|
||||
|
||||
aux = nv_encoder->aux;
|
||||
if (!aux)
|
||||
return -ENODEV;
|
||||
|
||||
ret = nvkm_rdaux(aux, DP_DPCD_REV, dpcd, 8);
|
||||
ret = nvkm_rdaux(aux, DP_DPCD_REV, dpcd, sizeof(dpcd));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -84,5 +91,11 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder)
|
||||
nv_encoder->dp.link_nr, nv_encoder->dp.link_bw);
|
||||
|
||||
nouveau_dp_probe_oui(dev, aux, dpcd);
|
||||
return 0;
|
||||
|
||||
ret = nv50_mstm_detect(nv_encoder->dp.mstm, dpcd, nouveau_mst);
|
||||
if (ret == 1)
|
||||
return NOUVEAU_DP_MST;
|
||||
if (ret == 0)
|
||||
return NOUVEAU_DP_SST;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -519,7 +519,7 @@ nouveau_drm_unload(struct drm_device *dev)
|
||||
nouveau_debugfs_fini(drm);
|
||||
|
||||
if (dev->mode_config.num_crtc)
|
||||
nouveau_display_fini(dev);
|
||||
nouveau_display_fini(dev, false);
|
||||
nouveau_display_destroy(dev);
|
||||
|
||||
nouveau_bios_takedown(dev);
|
||||
@@ -1037,6 +1037,7 @@ static void nouveau_display_options(void)
|
||||
DRM_DEBUG_DRIVER("... modeset : %d\n", nouveau_modeset);
|
||||
DRM_DEBUG_DRIVER("... runpm : %d\n", nouveau_runtime_pm);
|
||||
DRM_DEBUG_DRIVER("... vram_pushbuf : %d\n", nouveau_vram_pushbuf);
|
||||
DRM_DEBUG_DRIVER("... hdmimhz : %d\n", nouveau_hdmimhz);
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops nouveau_pm_ops = {
|
||||
|
||||
@@ -204,6 +204,10 @@ void nouveau_drm_device_remove(struct drm_device *dev);
|
||||
if (unlikely(drm_debug & DRM_UT_DRIVER)) \
|
||||
NV_PRINTK(info, &(drm)->client, f, ##a); \
|
||||
} while(0)
|
||||
#define NV_ATOMIC(drm,f,a...) do { \
|
||||
if (unlikely(drm_debug & DRM_UT_ATOMIC)) \
|
||||
NV_PRINTK(info, &(drm)->client, f, ##a); \
|
||||
} while(0)
|
||||
|
||||
extern int nouveau_modeset;
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <subdev/bios/dcb.h>
|
||||
|
||||
#include <drm/drm_encoder_slave.h>
|
||||
#include <drm/drm_dp_mst_helper.h>
|
||||
#include "dispnv04/disp.h"
|
||||
|
||||
#define NV_DPMS_CLEARED 0x80
|
||||
@@ -57,15 +58,16 @@ struct nouveau_encoder {
|
||||
|
||||
union {
|
||||
struct {
|
||||
u8 dpcd[8];
|
||||
struct nv50_mstm *mstm;
|
||||
int link_nr;
|
||||
int link_bw;
|
||||
u32 datarate;
|
||||
} dp;
|
||||
};
|
||||
|
||||
void (*enc_save)(struct drm_encoder *encoder);
|
||||
void (*enc_restore)(struct drm_encoder *encoder);
|
||||
void (*update)(struct nouveau_encoder *, u8 head,
|
||||
struct drm_display_mode *, u8 proto, u8 depth);
|
||||
};
|
||||
|
||||
struct nouveau_encoder *
|
||||
@@ -90,9 +92,17 @@ get_slave_funcs(struct drm_encoder *enc)
|
||||
}
|
||||
|
||||
/* nouveau_dp.c */
|
||||
enum nouveau_dp_status {
|
||||
NOUVEAU_DP_SST,
|
||||
NOUVEAU_DP_MST,
|
||||
};
|
||||
|
||||
int nouveau_dp_detect(struct nouveau_encoder *);
|
||||
|
||||
struct nouveau_connector *
|
||||
nouveau_encoder_connector_get(struct nouveau_encoder *encoder);
|
||||
|
||||
int nv50_mstm_detect(struct nv50_mstm *, u8 dpcd[8], int allow);
|
||||
void nv50_mstm_remove(struct nv50_mstm *);
|
||||
void nv50_mstm_service(struct nv50_mstm *);
|
||||
#endif /* __NOUVEAU_ENCODER_H__ */
|
||||
|
||||
@@ -58,7 +58,7 @@ static void
|
||||
nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
|
||||
{
|
||||
struct nouveau_fbdev *fbcon = info->par;
|
||||
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
|
||||
struct nvif_device *device = &drm->device;
|
||||
int ret;
|
||||
|
||||
@@ -90,7 +90,7 @@ static void
|
||||
nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image)
|
||||
{
|
||||
struct nouveau_fbdev *fbcon = info->par;
|
||||
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
|
||||
struct nvif_device *device = &drm->device;
|
||||
int ret;
|
||||
|
||||
@@ -122,7 +122,7 @@ static void
|
||||
nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
|
||||
{
|
||||
struct nouveau_fbdev *fbcon = info->par;
|
||||
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
|
||||
struct nvif_device *device = &drm->device;
|
||||
int ret;
|
||||
|
||||
@@ -154,7 +154,7 @@ static int
|
||||
nouveau_fbcon_sync(struct fb_info *info)
|
||||
{
|
||||
struct nouveau_fbdev *fbcon = info->par;
|
||||
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
|
||||
struct nouveau_channel *chan = drm->channel;
|
||||
int ret;
|
||||
|
||||
@@ -181,7 +181,7 @@ static int
|
||||
nouveau_fbcon_open(struct fb_info *info, int user)
|
||||
{
|
||||
struct nouveau_fbdev *fbcon = info->par;
|
||||
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
|
||||
int ret = pm_runtime_get_sync(drm->dev->dev);
|
||||
if (ret < 0 && ret != -EACCES)
|
||||
return ret;
|
||||
@@ -192,7 +192,7 @@ static int
|
||||
nouveau_fbcon_release(struct fb_info *info, int user)
|
||||
{
|
||||
struct nouveau_fbdev *fbcon = info->par;
|
||||
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
|
||||
pm_runtime_put(drm->dev->dev);
|
||||
return 0;
|
||||
}
|
||||
@@ -333,16 +333,15 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
|
||||
{
|
||||
struct nouveau_fbdev *fbcon =
|
||||
container_of(helper, struct nouveau_fbdev, helper);
|
||||
struct drm_device *dev = fbcon->dev;
|
||||
struct drm_device *dev = fbcon->helper.dev;
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct nvif_device *device = &drm->device;
|
||||
struct fb_info *info;
|
||||
struct drm_framebuffer *fb;
|
||||
struct nouveau_framebuffer *nouveau_fb;
|
||||
struct nouveau_framebuffer *fb;
|
||||
struct nouveau_channel *chan;
|
||||
struct nouveau_bo *nvbo;
|
||||
struct drm_mode_fb_cmd2 mode_cmd;
|
||||
int size, ret;
|
||||
int ret;
|
||||
|
||||
mode_cmd.width = sizes->surface_width;
|
||||
mode_cmd.height = sizes->surface_height;
|
||||
@@ -353,16 +352,17 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
|
||||
mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
|
||||
sizes->surface_depth);
|
||||
|
||||
size = mode_cmd.pitches[0] * mode_cmd.height;
|
||||
size = roundup(size, PAGE_SIZE);
|
||||
|
||||
ret = nouveau_gem_new(dev, size, 0, NOUVEAU_GEM_DOMAIN_VRAM,
|
||||
0, 0x0000, &nvbo);
|
||||
ret = nouveau_gem_new(dev, mode_cmd.pitches[0] * mode_cmd.height,
|
||||
0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, &nvbo);
|
||||
if (ret) {
|
||||
NV_ERROR(drm, "failed to allocate framebuffer\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = nouveau_framebuffer_new(dev, &mode_cmd, nvbo, &fb);
|
||||
if (ret)
|
||||
goto out_unref;
|
||||
|
||||
ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM, false);
|
||||
if (ret) {
|
||||
NV_ERROR(drm, "failed to pin fb: %d\n", ret);
|
||||
@@ -377,8 +377,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
|
||||
|
||||
chan = nouveau_nofbaccel ? NULL : drm->channel;
|
||||
if (chan && device->info.family >= NV_DEVICE_INFO_V0_TESLA) {
|
||||
ret = nouveau_bo_vma_add(nvbo, drm->client.vm,
|
||||
&fbcon->nouveau_fb.vma);
|
||||
ret = nouveau_bo_vma_add(nvbo, drm->client.vm, &fb->vma);
|
||||
if (ret) {
|
||||
NV_ERROR(drm, "failed to map fb into chan: %d\n", ret);
|
||||
chan = NULL;
|
||||
@@ -394,13 +393,8 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
|
||||
|
||||
info->par = fbcon;
|
||||
|
||||
nouveau_framebuffer_init(dev, &fbcon->nouveau_fb, &mode_cmd, nvbo);
|
||||
|
||||
nouveau_fb = &fbcon->nouveau_fb;
|
||||
fb = &nouveau_fb->base;
|
||||
|
||||
/* setup helper */
|
||||
fbcon->helper.fb = fb;
|
||||
fbcon->helper.fb = &fb->base;
|
||||
|
||||
strcpy(info->fix.id, "nouveaufb");
|
||||
if (!chan)
|
||||
@@ -411,14 +405,14 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
|
||||
FBINFO_HWACCEL_IMAGEBLIT;
|
||||
info->flags |= FBINFO_CAN_FORCE_OUTPUT;
|
||||
info->fbops = &nouveau_fbcon_sw_ops;
|
||||
info->fix.smem_start = nvbo->bo.mem.bus.base +
|
||||
nvbo->bo.mem.bus.offset;
|
||||
info->fix.smem_len = size;
|
||||
info->fix.smem_start = fb->nvbo->bo.mem.bus.base +
|
||||
fb->nvbo->bo.mem.bus.offset;
|
||||
info->fix.smem_len = fb->nvbo->bo.mem.num_pages << PAGE_SHIFT;
|
||||
|
||||
info->screen_base = nvbo_kmap_obj_iovirtual(nouveau_fb->nvbo);
|
||||
info->screen_size = size;
|
||||
info->screen_base = nvbo_kmap_obj_iovirtual(fb->nvbo);
|
||||
info->screen_size = fb->nvbo->bo.mem.num_pages << PAGE_SHIFT;
|
||||
|
||||
drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
|
||||
drm_fb_helper_fill_fix(info, fb->base.pitches[0], fb->base.depth);
|
||||
drm_fb_helper_fill_var(info, &fbcon->helper, sizes->fb_width, sizes->fb_height);
|
||||
|
||||
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
|
||||
@@ -429,20 +423,19 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
|
||||
|
||||
/* To allow resizeing without swapping buffers */
|
||||
NV_INFO(drm, "allocated %dx%d fb: 0x%llx, bo %p\n",
|
||||
nouveau_fb->base.width, nouveau_fb->base.height,
|
||||
nvbo->bo.offset, nvbo);
|
||||
fb->base.width, fb->base.height, fb->nvbo->bo.offset, nvbo);
|
||||
|
||||
vga_switcheroo_client_fb_set(dev->pdev, info);
|
||||
return 0;
|
||||
|
||||
out_unlock:
|
||||
if (chan)
|
||||
nouveau_bo_vma_del(nvbo, &fbcon->nouveau_fb.vma);
|
||||
nouveau_bo_unmap(nvbo);
|
||||
nouveau_bo_vma_del(fb->nvbo, &fb->vma);
|
||||
nouveau_bo_unmap(fb->nvbo);
|
||||
out_unpin:
|
||||
nouveau_bo_unpin(nvbo);
|
||||
nouveau_bo_unpin(fb->nvbo);
|
||||
out_unref:
|
||||
nouveau_bo_ref(NULL, &nvbo);
|
||||
nouveau_bo_ref(NULL, &fb->nvbo);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@@ -458,28 +451,26 @@ nouveau_fbcon_output_poll_changed(struct drm_device *dev)
|
||||
static int
|
||||
nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon)
|
||||
{
|
||||
struct nouveau_framebuffer *nouveau_fb = &fbcon->nouveau_fb;
|
||||
struct nouveau_framebuffer *nouveau_fb = nouveau_framebuffer(fbcon->helper.fb);
|
||||
|
||||
drm_fb_helper_unregister_fbi(&fbcon->helper);
|
||||
drm_fb_helper_release_fbi(&fbcon->helper);
|
||||
drm_fb_helper_fini(&fbcon->helper);
|
||||
|
||||
if (nouveau_fb->nvbo) {
|
||||
nouveau_bo_unmap(nouveau_fb->nvbo);
|
||||
nouveau_bo_vma_del(nouveau_fb->nvbo, &nouveau_fb->vma);
|
||||
nouveau_bo_unmap(nouveau_fb->nvbo);
|
||||
nouveau_bo_unpin(nouveau_fb->nvbo);
|
||||
drm_gem_object_unreference_unlocked(&nouveau_fb->nvbo->gem);
|
||||
nouveau_fb->nvbo = NULL;
|
||||
drm_framebuffer_unreference(&nouveau_fb->base);
|
||||
}
|
||||
drm_fb_helper_fini(&fbcon->helper);
|
||||
drm_framebuffer_unregister_private(&nouveau_fb->base);
|
||||
drm_framebuffer_cleanup(&nouveau_fb->base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nouveau_fbcon_gpu_lockup(struct fb_info *info)
|
||||
{
|
||||
struct nouveau_fbdev *fbcon = info->par;
|
||||
struct nouveau_drm *drm = nouveau_drm(fbcon->dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(fbcon->helper.dev);
|
||||
|
||||
NV_ERROR(drm, "GPU lockup - switching to software fbcon\n");
|
||||
info->flags |= FBINFO_HWACCEL_DISABLED;
|
||||
@@ -522,7 +513,6 @@ nouveau_fbcon_init(struct drm_device *dev)
|
||||
if (!fbcon)
|
||||
return -ENOMEM;
|
||||
|
||||
fbcon->dev = dev;
|
||||
drm->fbcon = fbcon;
|
||||
|
||||
drm_fb_helper_prepare(dev, &fbcon->helper, &nouveau_fbcon_helper_funcs);
|
||||
@@ -545,7 +535,8 @@ nouveau_fbcon_init(struct drm_device *dev)
|
||||
preferred_bpp = 32;
|
||||
|
||||
/* disable all the possible outputs/crtcs before entering KMS mode */
|
||||
drm_helper_disable_unused_functions(dev);
|
||||
if (!dev->mode_config.funcs->atomic_commit)
|
||||
drm_helper_disable_unused_functions(dev);
|
||||
|
||||
ret = drm_fb_helper_initial_config(&fbcon->helper, preferred_bpp);
|
||||
if (ret)
|
||||
|
||||
@@ -33,8 +33,6 @@
|
||||
|
||||
struct nouveau_fbdev {
|
||||
struct drm_fb_helper helper;
|
||||
struct nouveau_framebuffer nouveau_fb;
|
||||
struct drm_device *dev;
|
||||
unsigned int saved_flags;
|
||||
struct nvif_object surf2d;
|
||||
struct nvif_object clip;
|
||||
|
||||
@@ -586,5 +586,5 @@ static const struct dma_fence_ops nouveau_fence_ops_uevent = {
|
||||
.enable_signaling = nouveau_fence_enable_signaling,
|
||||
.signaled = nouveau_fence_is_signaled,
|
||||
.wait = dma_fence_default_wait,
|
||||
.release = NULL
|
||||
.release = nouveau_fence_release
|
||||
};
|
||||
|
||||
@@ -92,7 +92,6 @@ struct nv84_fence_chan {
|
||||
struct nouveau_fence_chan base;
|
||||
struct nvkm_vma vma;
|
||||
struct nvkm_vma vma_gart;
|
||||
struct nvkm_vma dispc_vma[4];
|
||||
};
|
||||
|
||||
struct nv84_fence_priv {
|
||||
@@ -102,7 +101,6 @@ struct nv84_fence_priv {
|
||||
u32 *suspend;
|
||||
};
|
||||
|
||||
u64 nv84_fence_crtc(struct nouveau_channel *, int);
|
||||
int nv84_fence_context_new(struct nouveau_channel *);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -369,7 +369,7 @@ validate_init(struct nouveau_channel *chan, struct drm_file *file_priv,
|
||||
{
|
||||
struct nouveau_cli *cli = nouveau_cli(file_priv);
|
||||
int trycnt = 0;
|
||||
int ret, i;
|
||||
int ret = -EINVAL, i;
|
||||
struct nouveau_bo *res_bo = NULL;
|
||||
LIST_HEAD(gart_list);
|
||||
LIST_HEAD(vram_list);
|
||||
|
||||
@@ -30,7 +30,7 @@ int
|
||||
nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
|
||||
{
|
||||
struct nouveau_fbdev *nfbdev = info->par;
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
|
||||
struct nouveau_channel *chan = drm->channel;
|
||||
int ret;
|
||||
|
||||
@@ -50,7 +50,7 @@ int
|
||||
nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
|
||||
{
|
||||
struct nouveau_fbdev *nfbdev = info->par;
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
|
||||
struct nouveau_channel *chan = drm->channel;
|
||||
int ret;
|
||||
|
||||
@@ -77,7 +77,7 @@ int
|
||||
nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
|
||||
{
|
||||
struct nouveau_fbdev *nfbdev = info->par;
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
|
||||
struct nouveau_channel *chan = drm->channel;
|
||||
uint32_t fg;
|
||||
uint32_t bg;
|
||||
@@ -133,7 +133,7 @@ int
|
||||
nv04_fbcon_accel_init(struct fb_info *info)
|
||||
{
|
||||
struct nouveau_fbdev *nfbdev = info->par;
|
||||
struct drm_device *dev = nfbdev->dev;
|
||||
struct drm_device *dev = nfbdev->helper.dev;
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct nouveau_channel *chan = drm->channel;
|
||||
struct nvif_device *device = &drm->device;
|
||||
|
||||
@@ -57,16 +57,13 @@ void
|
||||
nv10_fence_context_del(struct nouveau_channel *chan)
|
||||
{
|
||||
struct nv10_fence_chan *fctx = chan->fence;
|
||||
int i;
|
||||
nouveau_fence_context_del(&fctx->base);
|
||||
for (i = 0; i < ARRAY_SIZE(fctx->head); i++)
|
||||
nvif_object_fini(&fctx->head[i]);
|
||||
nvif_object_fini(&fctx->sema);
|
||||
chan->fence = NULL;
|
||||
nouveau_fence_context_free(&fctx->base);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
nv10_fence_context_new(struct nouveau_channel *chan)
|
||||
{
|
||||
struct nv10_fence_chan *fctx;
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
struct nv10_fence_chan {
|
||||
struct nouveau_fence_chan base;
|
||||
struct nvif_object sema;
|
||||
struct nvif_object head[4];
|
||||
};
|
||||
|
||||
struct nv10_fence_priv {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -35,11 +35,4 @@ int nv50_display_create(struct drm_device *);
|
||||
void nv50_display_destroy(struct drm_device *);
|
||||
int nv50_display_init(struct drm_device *);
|
||||
void nv50_display_fini(struct drm_device *);
|
||||
|
||||
void nv50_display_flip_stop(struct drm_crtc *);
|
||||
int nv50_display_flip_next(struct drm_crtc *, struct drm_framebuffer *,
|
||||
struct nouveau_channel *, u32 swap_interval);
|
||||
|
||||
struct nouveau_bo *nv50_display_crtc_sema(struct drm_device *, int head);
|
||||
|
||||
#endif /* __NV50_DISPLAY_H__ */
|
||||
|
||||
@@ -30,7 +30,7 @@ int
|
||||
nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
|
||||
{
|
||||
struct nouveau_fbdev *nfbdev = info->par;
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
|
||||
struct nouveau_channel *chan = drm->channel;
|
||||
int ret;
|
||||
|
||||
@@ -65,7 +65,7 @@ int
|
||||
nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
|
||||
{
|
||||
struct nouveau_fbdev *nfbdev = info->par;
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
|
||||
struct nouveau_channel *chan = drm->channel;
|
||||
int ret;
|
||||
|
||||
@@ -93,7 +93,7 @@ int
|
||||
nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
|
||||
{
|
||||
struct nouveau_fbdev *nfbdev = info->par;
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
|
||||
struct nouveau_channel *chan = drm->channel;
|
||||
uint32_t dwords, *data = (uint32_t *)image->data;
|
||||
uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
|
||||
@@ -148,8 +148,8 @@ int
|
||||
nv50_fbcon_accel_init(struct fb_info *info)
|
||||
{
|
||||
struct nouveau_fbdev *nfbdev = info->par;
|
||||
struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb;
|
||||
struct drm_device *dev = nfbdev->dev;
|
||||
struct nouveau_framebuffer *fb = nouveau_framebuffer(nfbdev->helper.fb);
|
||||
struct drm_device *dev = nfbdev->helper.dev;
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct nouveau_channel *chan = drm->channel;
|
||||
int ret, format;
|
||||
|
||||
@@ -35,13 +35,12 @@
|
||||
static int
|
||||
nv50_fence_context_new(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->drm->dev;
|
||||
struct nv10_fence_priv *priv = chan->drm->fence;
|
||||
struct nv10_fence_chan *fctx;
|
||||
struct ttm_mem_reg *mem = &priv->bo->bo.mem;
|
||||
u32 start = mem->start * PAGE_SIZE;
|
||||
u32 limit = start + mem->size - 1;
|
||||
int ret, i;
|
||||
int ret;
|
||||
|
||||
fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
|
||||
if (!fctx)
|
||||
@@ -60,23 +59,6 @@ nv50_fence_context_new(struct nouveau_channel *chan)
|
||||
.limit = limit,
|
||||
}, sizeof(struct nv_dma_v0),
|
||||
&fctx->sema);
|
||||
|
||||
/* dma objects for display sync channel semaphore blocks */
|
||||
for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) {
|
||||
struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i);
|
||||
u32 start = bo->bo.mem.start * PAGE_SIZE;
|
||||
u32 limit = start + bo->bo.mem.size - 1;
|
||||
|
||||
ret = nvif_object_init(&chan->user, NvEvoSema0 + i,
|
||||
NV_DMA_IN_MEMORY, &(struct nv_dma_v0) {
|
||||
.target = NV_DMA_V0_TARGET_VRAM,
|
||||
.access = NV_DMA_V0_ACCESS_RDWR,
|
||||
.start = start,
|
||||
.limit = limit,
|
||||
}, sizeof(struct nv_dma_v0),
|
||||
&fctx->head[i]);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
nv10_fence_context_del(chan);
|
||||
return ret;
|
||||
|
||||
@@ -28,13 +28,6 @@
|
||||
|
||||
#include "nv50_display.h"
|
||||
|
||||
u64
|
||||
nv84_fence_crtc(struct nouveau_channel *chan, int crtc)
|
||||
{
|
||||
struct nv84_fence_chan *fctx = chan->fence;
|
||||
return fctx->dispc_vma[crtc].offset;
|
||||
}
|
||||
|
||||
static int
|
||||
nv84_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
|
||||
{
|
||||
@@ -110,15 +103,8 @@ nv84_fence_read(struct nouveau_channel *chan)
|
||||
static void
|
||||
nv84_fence_context_del(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->drm->dev;
|
||||
struct nv84_fence_priv *priv = chan->drm->fence;
|
||||
struct nv84_fence_chan *fctx = chan->fence;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev->mode_config.num_crtc; i++) {
|
||||
struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i);
|
||||
nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]);
|
||||
}
|
||||
|
||||
nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence);
|
||||
nouveau_bo_vma_del(priv->bo, &fctx->vma_gart);
|
||||
@@ -134,7 +120,7 @@ nv84_fence_context_new(struct nouveau_channel *chan)
|
||||
struct nouveau_cli *cli = (void *)chan->user.client;
|
||||
struct nv84_fence_priv *priv = chan->drm->fence;
|
||||
struct nv84_fence_chan *fctx;
|
||||
int ret, i;
|
||||
int ret;
|
||||
|
||||
fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL);
|
||||
if (!fctx)
|
||||
@@ -154,12 +140,6 @@ nv84_fence_context_new(struct nouveau_channel *chan)
|
||||
&fctx->vma_gart);
|
||||
}
|
||||
|
||||
/* map display semaphore buffers into channel's vm */
|
||||
for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) {
|
||||
struct nouveau_bo *bo = nv50_display_crtc_sema(chan->drm->dev, i);
|
||||
ret = nouveau_bo_vma_add(bo, cli->vm, &fctx->dispc_vma[i]);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
nv84_fence_context_del(chan);
|
||||
return ret;
|
||||
|
||||
@@ -30,7 +30,7 @@ int
|
||||
nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
|
||||
{
|
||||
struct nouveau_fbdev *nfbdev = info->par;
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
|
||||
struct nouveau_channel *chan = drm->channel;
|
||||
int ret;
|
||||
|
||||
@@ -65,7 +65,7 @@ int
|
||||
nvc0_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
|
||||
{
|
||||
struct nouveau_fbdev *nfbdev = info->par;
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
|
||||
struct nouveau_channel *chan = drm->channel;
|
||||
int ret;
|
||||
|
||||
@@ -93,7 +93,7 @@ int
|
||||
nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
|
||||
{
|
||||
struct nouveau_fbdev *nfbdev = info->par;
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
|
||||
struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
|
||||
struct nouveau_channel *chan = drm->channel;
|
||||
uint32_t dwords, *data = (uint32_t *)image->data;
|
||||
uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
|
||||
@@ -148,8 +148,8 @@ int
|
||||
nvc0_fbcon_accel_init(struct fb_info *info)
|
||||
{
|
||||
struct nouveau_fbdev *nfbdev = info->par;
|
||||
struct drm_device *dev = nfbdev->dev;
|
||||
struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb;
|
||||
struct drm_device *dev = nfbdev->helper.dev;
|
||||
struct nouveau_framebuffer *fb = nouveau_framebuffer(nfbdev->helper.fb);
|
||||
struct nouveau_drm *drm = nouveau_drm(dev);
|
||||
struct nouveau_channel *chan = drm->channel;
|
||||
int ret, format;
|
||||
|
||||
@@ -55,7 +55,7 @@ nvif_client_fini(struct nvif_client *client)
|
||||
}
|
||||
}
|
||||
|
||||
const struct nvif_driver *
|
||||
static const struct nvif_driver *
|
||||
nvif_drivers[] = {
|
||||
#ifdef __KERNEL__
|
||||
&nvif_driver_nvkm,
|
||||
|
||||
@@ -155,10 +155,8 @@ nvif_notify_fini(struct nvif_notify *notify)
|
||||
int ret = nvif_notify_put(notify);
|
||||
if (ret >= 0 && object) {
|
||||
ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
|
||||
if (ret == 0) {
|
||||
notify->object = NULL;
|
||||
kfree((void *)notify->data);
|
||||
}
|
||||
notify->object = NULL;
|
||||
kfree((void *)notify->data);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gf100_ce_data[] = {
|
||||
static uint32_t gf100_ce_data[] = {
|
||||
/* 0x0000: ctx_object */
|
||||
0x00000000,
|
||||
/* 0x0004: ctx_query_address_high */
|
||||
@@ -171,7 +171,7 @@ uint32_t gf100_ce_data[] = {
|
||||
0x00000800,
|
||||
};
|
||||
|
||||
uint32_t gf100_ce_code[] = {
|
||||
static uint32_t gf100_ce_code[] = {
|
||||
/* 0x0000: main */
|
||||
0x04fe04bd,
|
||||
0x3517f000,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gt215_ce_data[] = {
|
||||
static uint32_t gt215_ce_data[] = {
|
||||
/* 0x0000: ctx_object */
|
||||
0x00000000,
|
||||
/* 0x0004: ctx_dma */
|
||||
@@ -183,7 +183,7 @@ uint32_t gt215_ce_data[] = {
|
||||
0x00000800,
|
||||
};
|
||||
|
||||
uint32_t gt215_ce_code[] = {
|
||||
static uint32_t gt215_ce_code[] = {
|
||||
/* 0x0000: main */
|
||||
0x04fe04bd,
|
||||
0x3517f000,
|
||||
|
||||
@@ -1852,7 +1852,7 @@ nvf1_chipset = {
|
||||
.fb = gk104_fb_new,
|
||||
.fuse = gf100_fuse_new,
|
||||
.gpio = gk104_gpio_new,
|
||||
.i2c = gf119_i2c_new,
|
||||
.i2c = gk104_i2c_new,
|
||||
.ibus = gk104_ibus_new,
|
||||
.iccsense = gf100_iccsense_new,
|
||||
.imem = nv50_instmem_new,
|
||||
@@ -1966,7 +1966,7 @@ nv117_chipset = {
|
||||
.fb = gm107_fb_new,
|
||||
.fuse = gm107_fuse_new,
|
||||
.gpio = gk104_gpio_new,
|
||||
.i2c = gf119_i2c_new,
|
||||
.i2c = gk104_i2c_new,
|
||||
.ibus = gk104_ibus_new,
|
||||
.iccsense = gf100_iccsense_new,
|
||||
.imem = nv50_instmem_new,
|
||||
@@ -2000,7 +2000,7 @@ nv118_chipset = {
|
||||
.fb = gm107_fb_new,
|
||||
.fuse = gm107_fuse_new,
|
||||
.gpio = gk104_gpio_new,
|
||||
.i2c = gf119_i2c_new,
|
||||
.i2c = gk104_i2c_new,
|
||||
.ibus = gk104_ibus_new,
|
||||
.iccsense = gf100_iccsense_new,
|
||||
.imem = nv50_instmem_new,
|
||||
@@ -2131,7 +2131,7 @@ nv12b_chipset = {
|
||||
.bar = gk20a_bar_new,
|
||||
.bus = gf100_bus_new,
|
||||
.clk = gm20b_clk_new,
|
||||
.fb = gk20a_fb_new,
|
||||
.fb = gm20b_fb_new,
|
||||
.fuse = gm107_fuse_new,
|
||||
.ibus = gk20a_ibus_new,
|
||||
.imem = gk20a_instmem_new,
|
||||
|
||||
@@ -102,7 +102,7 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
|
||||
|
||||
if (iommu_present(&platform_bus_type)) {
|
||||
tdev->iommu.domain = iommu_domain_alloc(&platform_bus_type);
|
||||
if (IS_ERR(tdev->iommu.domain))
|
||||
if (!tdev->iommu.domain)
|
||||
goto error;
|
||||
|
||||
/*
|
||||
|
||||
@@ -326,7 +326,7 @@ nvkm_udevice = {
|
||||
.sclass = nvkm_udevice_child_get,
|
||||
};
|
||||
|
||||
int
|
||||
static int
|
||||
nvkm_udevice_new(const struct nvkm_oclass *oclass, void *data, u32 size,
|
||||
struct nvkm_object **pobject)
|
||||
{
|
||||
|
||||
@@ -153,7 +153,7 @@ nv50_disp_chan_uevent = {
|
||||
.fini = nv50_disp_chan_uevent_fini,
|
||||
};
|
||||
|
||||
int
|
||||
static int
|
||||
nv50_disp_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data)
|
||||
{
|
||||
struct nv50_disp_chan *chan = nv50_disp_chan(object);
|
||||
@@ -163,7 +163,7 @@ nv50_disp_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
nv50_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data)
|
||||
{
|
||||
struct nv50_disp_chan *chan = nv50_disp_chan(object);
|
||||
@@ -173,7 +173,7 @@ nv50_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type,
|
||||
struct nvkm_event **pevent)
|
||||
{
|
||||
@@ -189,7 +189,7 @@ nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
nv50_disp_chan_map(struct nvkm_object *object, u64 *addr, u32 *size)
|
||||
{
|
||||
struct nv50_disp_chan *chan = nv50_disp_chan(object);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#include <nvif/class.h>
|
||||
|
||||
const struct nv50_disp_mthd_list
|
||||
static const struct nv50_disp_mthd_list
|
||||
g94_disp_core_mthd_sor = {
|
||||
.mthd = 0x0040,
|
||||
.addr = 0x000008,
|
||||
@@ -43,8 +43,8 @@ g94_disp_core_chan_mthd = {
|
||||
.prev = 0x000004,
|
||||
.data = {
|
||||
{ "Global", 1, &nv50_disp_core_mthd_base },
|
||||
{ "DAC", 3, &g84_disp_core_mthd_dac },
|
||||
{ "SOR", 4, &g94_disp_core_mthd_sor },
|
||||
{ "DAC", 3, &g84_disp_core_mthd_dac },
|
||||
{ "SOR", 4, &g94_disp_core_mthd_sor },
|
||||
{ "PIOR", 3, &nv50_disp_core_mthd_pior },
|
||||
{ "HEAD", 2, &g84_disp_core_mthd_head },
|
||||
{}
|
||||
|
||||
@@ -59,7 +59,7 @@ gp104_disp_core_init(struct nv50_disp_dmac *chan)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct nv50_disp_dmac_func
|
||||
static const struct nv50_disp_dmac_func
|
||||
gp104_disp_core_func = {
|
||||
.init = gp104_disp_core_init,
|
||||
.fini = gf119_disp_core_fini,
|
||||
|
||||
@@ -319,9 +319,8 @@ static const struct dp_rates {
|
||||
};
|
||||
|
||||
void
|
||||
nvkm_dp_train(struct work_struct *w)
|
||||
nvkm_dp_train(struct nvkm_output_dp *outp)
|
||||
{
|
||||
struct nvkm_output_dp *outp = container_of(w, typeof(*outp), lt.work);
|
||||
struct nv50_disp *disp = nv50_disp(outp->base.disp);
|
||||
const struct dp_rates *cfg = nvkm_dp_rates;
|
||||
struct dp_state _dp = {
|
||||
@@ -353,9 +352,6 @@ nvkm_dp_train(struct work_struct *w)
|
||||
}
|
||||
cfg--;
|
||||
|
||||
/* disable link interrupt handling during link training */
|
||||
nvkm_notify_put(&outp->irq);
|
||||
|
||||
/* ensure sink is not in a low-power state */
|
||||
if (!nvkm_rdaux(outp->aux, DPCD_SC00, &pwr, 1)) {
|
||||
if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) {
|
||||
@@ -400,9 +396,6 @@ nvkm_dp_train(struct work_struct *w)
|
||||
|
||||
dp_link_train_fini(dp);
|
||||
|
||||
/* signal completion and enable link interrupt handling */
|
||||
OUTP_DBG(&outp->base, "training complete");
|
||||
atomic_set(&outp->lt.done, 1);
|
||||
wake_up(&outp->lt.wait);
|
||||
nvkm_notify_get(&outp->irq);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef __NVKM_DISP_DPORT_H__
|
||||
#define __NVKM_DISP_DPORT_H__
|
||||
#include <core/os.h>
|
||||
struct nvkm_output_dp;
|
||||
|
||||
/* DPCD Receiver Capabilities */
|
||||
#define DPCD_RC00_DPCD_REV 0x00000
|
||||
@@ -77,5 +77,5 @@
|
||||
#define DPCD_SC00_SET_POWER_D0 0x01
|
||||
#define DPCD_SC00_SET_POWER_D3 0x03
|
||||
|
||||
void nvkm_dp_train(struct work_struct *);
|
||||
void nvkm_dp_train(struct nvkm_output_dp *);
|
||||
#endif
|
||||
|
||||
@@ -203,17 +203,20 @@ gf119_disp_intr_unk2_0(struct nv50_disp *disp, int head)
|
||||
/* see note in nv50_disp_intr_unk20_0() */
|
||||
if (outp && outp->info.type == DCB_OUTPUT_DP) {
|
||||
struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
|
||||
struct nvbios_init init = {
|
||||
.subdev = subdev,
|
||||
.bios = subdev->device->bios,
|
||||
.outp = &outp->info,
|
||||
.crtc = head,
|
||||
.offset = outpdp->info.script[4],
|
||||
.execute = 1,
|
||||
};
|
||||
if (!outpdp->lt.mst) {
|
||||
struct nvbios_init init = {
|
||||
.subdev = subdev,
|
||||
.bios = subdev->device->bios,
|
||||
.outp = &outp->info,
|
||||
.crtc = head,
|
||||
.offset = outpdp->info.script[4],
|
||||
.execute = 1,
|
||||
};
|
||||
|
||||
nvbios_exec(&init);
|
||||
atomic_set(&outpdp->lt.done, 0);
|
||||
nvkm_notify_put(&outpdp->irq);
|
||||
nvbios_exec(&init);
|
||||
atomic_set(&outpdp->lt.done, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,7 +317,7 @@ gf119_disp_intr_unk2_2(struct nv50_disp *disp, int head)
|
||||
break;
|
||||
}
|
||||
|
||||
if (nvkm_output_dp_train(outp, pclk, true))
|
||||
if (nvkm_output_dp_train(outp, pclk))
|
||||
OUTP_ERR(outp, "link not trained before attach");
|
||||
} else {
|
||||
if (disp->func->sor.magic)
|
||||
|
||||
@@ -590,6 +590,7 @@ nv50_disp_intr_unk20_0(struct nv50_disp *disp, int head)
|
||||
.execute = 1,
|
||||
};
|
||||
|
||||
nvkm_notify_put(&outpdp->irq);
|
||||
nvbios_exec(&init);
|
||||
atomic_set(&outpdp->lt.done, 0);
|
||||
}
|
||||
@@ -779,7 +780,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp *disp, int head)
|
||||
break;
|
||||
}
|
||||
|
||||
if (nvkm_output_dp_train(outp, datarate / soff, true))
|
||||
if (nvkm_output_dp_train(outp, datarate / soff))
|
||||
OUTP_ERR(outp, "link not trained before attach");
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include <nvif/event.h>
|
||||
|
||||
int
|
||||
nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait)
|
||||
nvkm_output_dp_train(struct nvkm_output *base, u32 datarate)
|
||||
{
|
||||
struct nvkm_output_dp *outp = nvkm_output_dp(base);
|
||||
bool retrain = true;
|
||||
@@ -39,6 +39,8 @@ nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait)
|
||||
u32 linkrate;
|
||||
int ret, i;
|
||||
|
||||
mutex_lock(&outp->mutex);
|
||||
|
||||
/* check that the link is trained at a high enough rate */
|
||||
ret = nvkm_rdaux(outp->aux, DPCD_LC00_LINK_BW_SET, link, 2);
|
||||
if (ret) {
|
||||
@@ -88,19 +90,10 @@ nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait)
|
||||
outp->dpcd[DPCD_RC02] =
|
||||
outp->base.info.dpconf.link_nr;
|
||||
}
|
||||
atomic_set(&outp->lt.done, 0);
|
||||
schedule_work(&outp->lt.work);
|
||||
} else {
|
||||
nvkm_notify_get(&outp->irq);
|
||||
}
|
||||
|
||||
if (wait) {
|
||||
if (!wait_event_timeout(outp->lt.wait,
|
||||
atomic_read(&outp->lt.done),
|
||||
msecs_to_jiffies(2000)))
|
||||
ret = -ETIMEDOUT;
|
||||
nvkm_dp_train(outp);
|
||||
}
|
||||
|
||||
mutex_unlock(&outp->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -118,7 +111,7 @@ nvkm_output_dp_enable(struct nvkm_output_dp *outp, bool enable)
|
||||
|
||||
if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dpcd,
|
||||
sizeof(outp->dpcd))) {
|
||||
nvkm_output_dp_train(&outp->base, 0, true);
|
||||
nvkm_output_dp_train(&outp->base, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -165,10 +158,10 @@ nvkm_output_dp_irq(struct nvkm_notify *notify)
|
||||
};
|
||||
|
||||
OUTP_DBG(&outp->base, "IRQ: %d", line->mask);
|
||||
nvkm_output_dp_train(&outp->base, 0, true);
|
||||
nvkm_output_dp_train(&outp->base, 0);
|
||||
|
||||
nvkm_event_send(&disp->hpd, rep.mask, conn->index, &rep, sizeof(rep));
|
||||
return NVKM_NOTIFY_DROP;
|
||||
return NVKM_NOTIFY_KEEP;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -177,7 +170,6 @@ nvkm_output_dp_fini(struct nvkm_output *base)
|
||||
struct nvkm_output_dp *outp = nvkm_output_dp(base);
|
||||
nvkm_notify_put(&outp->hpd);
|
||||
nvkm_notify_put(&outp->irq);
|
||||
flush_work(&outp->lt.work);
|
||||
nvkm_output_dp_enable(outp, false);
|
||||
}
|
||||
|
||||
@@ -187,6 +179,7 @@ nvkm_output_dp_init(struct nvkm_output *base)
|
||||
struct nvkm_output_dp *outp = nvkm_output_dp(base);
|
||||
nvkm_notify_put(&outp->base.conn->hpd);
|
||||
nvkm_output_dp_enable(outp, true);
|
||||
nvkm_notify_get(&outp->irq);
|
||||
nvkm_notify_get(&outp->hpd);
|
||||
}
|
||||
|
||||
@@ -238,11 +231,6 @@ nvkm_output_dp_ctor(const struct nvkm_output_dp_func *func,
|
||||
OUTP_DBG(&outp->base, "bios dp %02x %02x %02x %02x",
|
||||
outp->version, hdr, cnt, len);
|
||||
|
||||
/* link training */
|
||||
INIT_WORK(&outp->lt.work, nvkm_dp_train);
|
||||
init_waitqueue_head(&outp->lt.wait);
|
||||
atomic_set(&outp->lt.done, 0);
|
||||
|
||||
/* link maintenance */
|
||||
ret = nvkm_notify_init(NULL, &i2c->event, nvkm_output_dp_irq, true,
|
||||
&(struct nvkm_i2c_ntfy_req) {
|
||||
@@ -257,6 +245,9 @@ nvkm_output_dp_ctor(const struct nvkm_output_dp_func *func,
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_init(&outp->mutex);
|
||||
atomic_set(&outp->lt.done, 0);
|
||||
|
||||
/* hotplug detect, replaces gpio-based mechanism with aux events */
|
||||
ret = nvkm_notify_init(NULL, &i2c->event, nvkm_output_dp_hpd, true,
|
||||
&(struct nvkm_i2c_ntfy_req) {
|
||||
|
||||
@@ -29,10 +29,10 @@ struct nvkm_output_dp {
|
||||
bool present;
|
||||
u8 dpcd[16];
|
||||
|
||||
struct mutex mutex;
|
||||
struct {
|
||||
struct work_struct work;
|
||||
wait_queue_head_t wait;
|
||||
atomic_t done;
|
||||
bool mst;
|
||||
} lt;
|
||||
};
|
||||
|
||||
@@ -41,9 +41,11 @@ struct nvkm_output_dp_func {
|
||||
int (*lnk_pwr)(struct nvkm_output_dp *, int nr);
|
||||
int (*lnk_ctl)(struct nvkm_output_dp *, int nr, int bw, bool ef);
|
||||
int (*drv_ctl)(struct nvkm_output_dp *, int ln, int vs, int pe, int pc);
|
||||
void (*vcpi)(struct nvkm_output_dp *, int head, u8 start_slot,
|
||||
u8 num_slots, u16 pbn, u16 aligned_pbn);
|
||||
};
|
||||
|
||||
int nvkm_output_dp_train(struct nvkm_output *, u32 rate, bool wait);
|
||||
int nvkm_output_dp_train(struct nvkm_output *, u32 rate);
|
||||
|
||||
int nvkm_output_dp_ctor(const struct nvkm_output_dp_func *, struct nvkm_disp *,
|
||||
int index, struct dcb_output *, struct nvkm_i2c_aux *,
|
||||
@@ -63,6 +65,7 @@ int gf119_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
|
||||
struct nvkm_output **);
|
||||
int gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *, int, int, bool);
|
||||
int gf119_sor_dp_drv_ctl(struct nvkm_output_dp *, int, int, int, int);
|
||||
void gf119_sor_dp_vcpi(struct nvkm_output_dp *, int, u8, u8, u16, u16);
|
||||
|
||||
int gm107_sor_dp_new(struct nvkm_disp *, int, struct dcb_output *,
|
||||
struct nvkm_output **);
|
||||
|
||||
@@ -66,7 +66,7 @@ nv50_disp_root_scanoutpos(NV50_DISP_MTHD_V0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
|
||||
{
|
||||
union {
|
||||
@@ -173,13 +173,56 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
|
||||
return 0;
|
||||
} else
|
||||
if (args->v0.state != 0) {
|
||||
nvkm_output_dp_train(&outpdp->base, 0, true);
|
||||
nvkm_output_dp_train(&outpdp->base, 0);
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case NV50_DISP_MTHD_V1_SOR_DP_MST_LINK: {
|
||||
struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
|
||||
union {
|
||||
struct nv50_disp_sor_dp_mst_link_v0 v0;
|
||||
} *args = data;
|
||||
int ret = -ENOSYS;
|
||||
nvif_ioctl(object, "disp sor dp mst link size %d\n", size);
|
||||
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
|
||||
nvif_ioctl(object, "disp sor dp mst link vers %d state %d\n",
|
||||
args->v0.version, args->v0.state);
|
||||
if (outpdp->lt.mst != !!args->v0.state) {
|
||||
outpdp->lt.mst = !!args->v0.state;
|
||||
atomic_set(&outpdp->lt.done, 0);
|
||||
nvkm_output_dp_train(&outpdp->base, 0);
|
||||
}
|
||||
return 0;
|
||||
} else
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI: {
|
||||
struct nvkm_output_dp *outpdp = nvkm_output_dp(outp);
|
||||
union {
|
||||
struct nv50_disp_sor_dp_mst_vcpi_v0 v0;
|
||||
} *args = data;
|
||||
int ret = -ENOSYS;
|
||||
nvif_ioctl(object, "disp sor dp mst vcpi size %d\n", size);
|
||||
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
|
||||
nvif_ioctl(object, "disp sor dp mst vcpi vers %d "
|
||||
"slot %02x/%02x pbn %04x/%04x\n",
|
||||
args->v0.version, args->v0.start_slot,
|
||||
args->v0.num_slots, args->v0.pbn,
|
||||
args->v0.aligned_pbn);
|
||||
if (!outpdp->func->vcpi)
|
||||
return -ENODEV;
|
||||
outpdp->func->vcpi(outpdp, head, args->v0.start_slot,
|
||||
args->v0.num_slots, args->v0.pbn,
|
||||
args->v0.aligned_pbn);
|
||||
return 0;
|
||||
} else
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
case NV50_DISP_MTHD_V1_PIOR_PWR:
|
||||
if (!func->pior.power)
|
||||
return -ENODEV;
|
||||
|
||||
@@ -56,11 +56,13 @@ gf119_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef)
|
||||
|
||||
clksor |= bw << 18;
|
||||
dpctrl |= ((1 << nr) - 1) << 16;
|
||||
if (outp->lt.mst)
|
||||
dpctrl |= 0x40000000;
|
||||
if (ef)
|
||||
dpctrl |= 0x00004000;
|
||||
|
||||
nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor);
|
||||
nvkm_mask(device, 0x61c10c + loff, 0x001f4000, dpctrl);
|
||||
nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -101,12 +103,24 @@ gf119_sor_dp_drv_ctl(struct nvkm_output_dp *outp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
gf119_sor_dp_vcpi(struct nvkm_output_dp *outp, int head, u8 slot,
|
||||
u8 slot_nr, u16 pbn, u16 aligned)
|
||||
{
|
||||
struct nvkm_device *device = outp->base.disp->engine.subdev.device;
|
||||
const u32 hoff = head * 0x800;
|
||||
|
||||
nvkm_mask(device, 0x616588 + hoff, 0x00003f3f, (slot_nr << 8) | slot);
|
||||
nvkm_mask(device, 0x61658c + hoff, 0xffffffff, (aligned << 16) | pbn);
|
||||
}
|
||||
|
||||
static const struct nvkm_output_dp_func
|
||||
gf119_sor_dp_func = {
|
||||
.pattern = gf119_sor_dp_pattern,
|
||||
.lnk_pwr = g94_sor_dp_lnk_pwr,
|
||||
.lnk_ctl = gf119_sor_dp_lnk_ctl,
|
||||
.drv_ctl = gf119_sor_dp_drv_ctl,
|
||||
.vcpi = gf119_sor_dp_vcpi,
|
||||
};
|
||||
|
||||
int
|
||||
|
||||
@@ -43,6 +43,7 @@ gm107_sor_dp_func = {
|
||||
.lnk_pwr = g94_sor_dp_lnk_pwr,
|
||||
.lnk_ctl = gf119_sor_dp_lnk_ctl,
|
||||
.drv_ctl = gf119_sor_dp_drv_ctl,
|
||||
.vcpi = gf119_sor_dp_vcpi,
|
||||
};
|
||||
|
||||
int
|
||||
|
||||
@@ -120,6 +120,7 @@ gm200_sor_dp_func = {
|
||||
.lnk_pwr = gm200_sor_dp_lnk_pwr,
|
||||
.lnk_ctl = gf119_sor_dp_lnk_ctl,
|
||||
.drv_ctl = gm200_sor_dp_drv_ctl,
|
||||
.vcpi = gf119_sor_dp_vcpi,
|
||||
};
|
||||
|
||||
int
|
||||
|
||||
@@ -129,7 +129,7 @@ g84_fifo_chan_engine_fini(struct nvkm_fifo_chan *base,
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
static int
|
||||
g84_fifo_chan_engine_init(struct nvkm_fifo_chan *base,
|
||||
struct nvkm_engine *engine)
|
||||
{
|
||||
@@ -170,7 +170,7 @@ g84_fifo_chan_engine_ctor(struct nvkm_fifo_chan *base,
|
||||
return nvkm_object_bind(object, NULL, 0, &chan->engn[engn]);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
g84_fifo_chan_object_ctor(struct nvkm_fifo_chan *base,
|
||||
struct nvkm_object *object)
|
||||
{
|
||||
|
||||
@@ -60,6 +60,7 @@ gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
|
||||
struct nvkm_gpuobj *inst = chan->base.inst;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&subdev->mutex);
|
||||
nvkm_wr32(device, 0x002634, chan->base.chid);
|
||||
if (nvkm_msec(device, 2000,
|
||||
if (nvkm_rd32(device, 0x002634) == chan->base.chid)
|
||||
@@ -67,10 +68,12 @@ gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
|
||||
) < 0) {
|
||||
nvkm_error(subdev, "channel %d [%s] kick timeout\n",
|
||||
chan->base.chid, chan->base.object.client->name);
|
||||
ret = -EBUSY;
|
||||
if (suspend)
|
||||
return ret;
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
mutex_unlock(&subdev->mutex);
|
||||
|
||||
if (ret && suspend)
|
||||
return ret;
|
||||
|
||||
if (offset) {
|
||||
nvkm_kmap(inst);
|
||||
|
||||
@@ -40,7 +40,9 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
|
||||
struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
|
||||
struct nvkm_device *device = subdev->device;
|
||||
struct nvkm_client *client = chan->base.object.client;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&subdev->mutex);
|
||||
nvkm_wr32(device, 0x002634, chan->base.chid);
|
||||
if (nvkm_msec(device, 2000,
|
||||
if (!(nvkm_rd32(device, 0x002634) & 0x00100000))
|
||||
@@ -48,10 +50,10 @@ gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
|
||||
) < 0) {
|
||||
nvkm_error(subdev, "channel %d [%s] kick timeout\n",
|
||||
chan->base.chid, client->name);
|
||||
return -EBUSY;
|
||||
ret = -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
mutex_unlock(&subdev->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32
|
||||
|
||||
@@ -218,7 +218,7 @@ gf117_grctx_generate_attrib(struct gf100_grctx *info)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
gf117_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
|
||||
{
|
||||
struct nvkm_device *device = gr->base.engine.subdev.device;
|
||||
|
||||
@@ -933,7 +933,7 @@ gm107_grctx_generate_attrib(struct gf100_grctx *info)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
gm107_grctx_generate_tpcid(struct gf100_gr *gr)
|
||||
{
|
||||
struct nvkm_device *device = gr->base.engine.subdev.device;
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
#define CP_SEEK_2 0x00c800ff
|
||||
|
||||
#include "ctxnv40.h"
|
||||
#include "nv50.h"
|
||||
|
||||
#include <subdev/fb.h>
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gf100_grgpc_data[] = {
|
||||
static uint32_t gf100_grgpc_data[] = {
|
||||
/* 0x0000: gpc_mmio_list_head */
|
||||
0x00000064,
|
||||
/* 0x0004: gpc_mmio_list_tail */
|
||||
@@ -36,7 +36,7 @@ uint32_t gf100_grgpc_data[] = {
|
||||
0x00000000,
|
||||
};
|
||||
|
||||
uint32_t gf100_grgpc_code[] = {
|
||||
static uint32_t gf100_grgpc_code[] = {
|
||||
0x03a10ef5,
|
||||
/* 0x0004: queue_put */
|
||||
0x9800d898,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gf117_grgpc_data[] = {
|
||||
static uint32_t gf117_grgpc_data[] = {
|
||||
/* 0x0000: gpc_mmio_list_head */
|
||||
0x0000006c,
|
||||
/* 0x0004: gpc_mmio_list_tail */
|
||||
@@ -40,7 +40,7 @@ uint32_t gf117_grgpc_data[] = {
|
||||
0x00000000,
|
||||
};
|
||||
|
||||
uint32_t gf117_grgpc_code[] = {
|
||||
static uint32_t gf117_grgpc_code[] = {
|
||||
0x03a10ef5,
|
||||
/* 0x0004: queue_put */
|
||||
0x9800d898,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gk104_grgpc_data[] = {
|
||||
static uint32_t gk104_grgpc_data[] = {
|
||||
/* 0x0000: gpc_mmio_list_head */
|
||||
0x0000006c,
|
||||
/* 0x0004: gpc_mmio_list_tail */
|
||||
@@ -40,7 +40,7 @@ uint32_t gk104_grgpc_data[] = {
|
||||
0x00000000,
|
||||
};
|
||||
|
||||
uint32_t gk104_grgpc_code[] = {
|
||||
static uint32_t gk104_grgpc_code[] = {
|
||||
0x03a10ef5,
|
||||
/* 0x0004: queue_put */
|
||||
0x9800d898,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gk110_grgpc_data[] = {
|
||||
static uint32_t gk110_grgpc_data[] = {
|
||||
/* 0x0000: gpc_mmio_list_head */
|
||||
0x0000006c,
|
||||
/* 0x0004: gpc_mmio_list_tail */
|
||||
@@ -40,7 +40,7 @@ uint32_t gk110_grgpc_data[] = {
|
||||
0x00000000,
|
||||
};
|
||||
|
||||
uint32_t gk110_grgpc_code[] = {
|
||||
static uint32_t gk110_grgpc_code[] = {
|
||||
0x03a10ef5,
|
||||
/* 0x0004: queue_put */
|
||||
0x9800d898,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gk208_grgpc_data[] = {
|
||||
static uint32_t gk208_grgpc_data[] = {
|
||||
/* 0x0000: gpc_mmio_list_head */
|
||||
0x0000006c,
|
||||
/* 0x0004: gpc_mmio_list_tail */
|
||||
@@ -40,7 +40,7 @@ uint32_t gk208_grgpc_data[] = {
|
||||
0x00000000,
|
||||
};
|
||||
|
||||
uint32_t gk208_grgpc_code[] = {
|
||||
static uint32_t gk208_grgpc_code[] = {
|
||||
0x03140ef5,
|
||||
/* 0x0004: queue_put */
|
||||
0x9800d898,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gm107_grgpc_data[] = {
|
||||
static uint32_t gm107_grgpc_data[] = {
|
||||
/* 0x0000: gpc_mmio_list_head */
|
||||
0x0000006c,
|
||||
/* 0x0004: gpc_mmio_list_tail */
|
||||
@@ -40,7 +40,7 @@ uint32_t gm107_grgpc_data[] = {
|
||||
0x00000000,
|
||||
};
|
||||
|
||||
uint32_t gm107_grgpc_code[] = {
|
||||
static uint32_t gm107_grgpc_code[] = {
|
||||
0x03410ef5,
|
||||
/* 0x0004: queue_put */
|
||||
0x9800d898,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gf100_grhub_data[] = {
|
||||
static uint32_t gf100_grhub_data[] = {
|
||||
/* 0x0000: hub_mmio_list_head */
|
||||
0x00000300,
|
||||
/* 0x0004: hub_mmio_list_tail */
|
||||
@@ -205,7 +205,7 @@ uint32_t gf100_grhub_data[] = {
|
||||
0x0417e91c,
|
||||
};
|
||||
|
||||
uint32_t gf100_grhub_code[] = {
|
||||
static uint32_t gf100_grhub_code[] = {
|
||||
0x039b0ef5,
|
||||
/* 0x0004: queue_put */
|
||||
0x9800d898,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gf117_grhub_data[] = {
|
||||
static uint32_t gf117_grhub_data[] = {
|
||||
/* 0x0000: hub_mmio_list_head */
|
||||
0x00000300,
|
||||
/* 0x0004: hub_mmio_list_tail */
|
||||
@@ -205,7 +205,7 @@ uint32_t gf117_grhub_data[] = {
|
||||
0x0417e91c,
|
||||
};
|
||||
|
||||
uint32_t gf117_grhub_code[] = {
|
||||
static uint32_t gf117_grhub_code[] = {
|
||||
0x039b0ef5,
|
||||
/* 0x0004: queue_put */
|
||||
0x9800d898,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gk104_grhub_data[] = {
|
||||
static uint32_t gk104_grhub_data[] = {
|
||||
/* 0x0000: hub_mmio_list_head */
|
||||
0x00000300,
|
||||
/* 0x0004: hub_mmio_list_tail */
|
||||
@@ -205,7 +205,7 @@ uint32_t gk104_grhub_data[] = {
|
||||
0x0417e91c,
|
||||
};
|
||||
|
||||
uint32_t gk104_grhub_code[] = {
|
||||
static uint32_t gk104_grhub_code[] = {
|
||||
0x039b0ef5,
|
||||
/* 0x0004: queue_put */
|
||||
0x9800d898,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gk110_grhub_data[] = {
|
||||
static uint32_t gk110_grhub_data[] = {
|
||||
/* 0x0000: hub_mmio_list_head */
|
||||
0x00000300,
|
||||
/* 0x0004: hub_mmio_list_tail */
|
||||
@@ -205,7 +205,7 @@ uint32_t gk110_grhub_data[] = {
|
||||
0x0417e91c,
|
||||
};
|
||||
|
||||
uint32_t gk110_grhub_code[] = {
|
||||
static uint32_t gk110_grhub_code[] = {
|
||||
0x039b0ef5,
|
||||
/* 0x0004: queue_put */
|
||||
0x9800d898,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gk208_grhub_data[] = {
|
||||
static uint32_t gk208_grhub_data[] = {
|
||||
/* 0x0000: hub_mmio_list_head */
|
||||
0x00000300,
|
||||
/* 0x0004: hub_mmio_list_tail */
|
||||
@@ -205,7 +205,7 @@ uint32_t gk208_grhub_data[] = {
|
||||
0x0417e91c,
|
||||
};
|
||||
|
||||
uint32_t gk208_grhub_code[] = {
|
||||
static uint32_t gk208_grhub_code[] = {
|
||||
0x030e0ef5,
|
||||
/* 0x0004: queue_put */
|
||||
0x9800d898,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gm107_grhub_data[] = {
|
||||
static uint32_t gm107_grhub_data[] = {
|
||||
/* 0x0000: hub_mmio_list_head */
|
||||
0x00000300,
|
||||
/* 0x0004: hub_mmio_list_tail */
|
||||
@@ -205,7 +205,7 @@ uint32_t gm107_grhub_data[] = {
|
||||
0x0417e91c,
|
||||
};
|
||||
|
||||
uint32_t gm107_grhub_code[] = {
|
||||
static uint32_t gm107_grhub_code[] = {
|
||||
0x030e0ef5,
|
||||
/* 0x0004: queue_put */
|
||||
0x9800d898,
|
||||
|
||||
@@ -1384,7 +1384,7 @@ gf100_gr_intr(struct nvkm_gr *base)
|
||||
nvkm_fifo_chan_put(device->fifo, flags, &chan);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
gf100_gr_init_fw(struct gf100_gr *gr, u32 fuc_base,
|
||||
struct gf100_gr_fuc *code, struct gf100_gr_fuc *data)
|
||||
{
|
||||
@@ -1701,7 +1701,7 @@ gf100_gr_oneinit(struct nvkm_gr *base)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
gf100_gr_init_(struct nvkm_gr *base)
|
||||
{
|
||||
struct gf100_gr *gr = gf100_gr(base);
|
||||
@@ -1755,6 +1755,50 @@ gf100_gr_ = {
|
||||
.object_get = gf100_gr_object_get,
|
||||
};
|
||||
|
||||
int
|
||||
gf100_gr_ctor_fw_legacy(struct gf100_gr *gr, const char *fwname,
|
||||
struct gf100_gr_fuc *fuc, int ret)
|
||||
{
|
||||
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
|
||||
struct nvkm_device *device = subdev->device;
|
||||
const struct firmware *fw;
|
||||
char f[32];
|
||||
|
||||
/* see if this firmware has a legacy path */
|
||||
if (!strcmp(fwname, "fecs_inst"))
|
||||
fwname = "fuc409c";
|
||||
else if (!strcmp(fwname, "fecs_data"))
|
||||
fwname = "fuc409d";
|
||||
else if (!strcmp(fwname, "gpccs_inst"))
|
||||
fwname = "fuc41ac";
|
||||
else if (!strcmp(fwname, "gpccs_data"))
|
||||
fwname = "fuc41ad";
|
||||
else {
|
||||
/* nope, let's just return the error we got */
|
||||
nvkm_error(subdev, "failed to load %s\n", fwname);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* yes, try to load from the legacy path */
|
||||
nvkm_debug(subdev, "%s: falling back to legacy path\n", fwname);
|
||||
|
||||
snprintf(f, sizeof(f), "nouveau/nv%02x_%s", device->chipset, fwname);
|
||||
ret = request_firmware(&fw, f, device->dev);
|
||||
if (ret) {
|
||||
snprintf(f, sizeof(f), "nouveau/%s", fwname);
|
||||
ret = request_firmware(&fw, f, device->dev);
|
||||
if (ret) {
|
||||
nvkm_error(subdev, "failed to load %s\n", fwname);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
fuc->size = fw->size;
|
||||
fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
|
||||
release_firmware(fw);
|
||||
return (fuc->data != NULL) ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
int
|
||||
gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname,
|
||||
struct gf100_gr_fuc *fuc)
|
||||
@@ -1765,10 +1809,8 @@ gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname,
|
||||
int ret;
|
||||
|
||||
ret = nvkm_firmware_get(device, fwname, &fw);
|
||||
if (ret) {
|
||||
nvkm_error(subdev, "failed to load %s\n", fwname);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
return gf100_gr_ctor_fw_legacy(gr, fwname, fuc, ret);
|
||||
|
||||
fuc->size = fw->size;
|
||||
fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL);
|
||||
|
||||
@@ -102,7 +102,7 @@ gf117_gr_pack_mmio[] = {
|
||||
|
||||
#include "fuc/hubgf117.fuc3.h"
|
||||
|
||||
struct gf100_gr_ucode
|
||||
static struct gf100_gr_ucode
|
||||
gf117_gr_fecs_ucode = {
|
||||
.code.data = gf117_grhub_code,
|
||||
.code.size = sizeof(gf117_grhub_code),
|
||||
@@ -112,7 +112,7 @@ gf117_gr_fecs_ucode = {
|
||||
|
||||
#include "fuc/gpcgf117.fuc3.h"
|
||||
|
||||
struct gf100_gr_ucode
|
||||
static struct gf100_gr_ucode
|
||||
gf117_gr_gpccs_ucode = {
|
||||
.code.data = gf117_grgpc_code,
|
||||
.code.size = sizeof(gf117_grgpc_code),
|
||||
|
||||
@@ -308,7 +308,7 @@ gm107_gr_init_bios(struct gf100_gr *gr)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
gm107_gr_init(struct gf100_gr *gr)
|
||||
{
|
||||
struct nvkm_device *device = gr->base.engine.subdev.device;
|
||||
|
||||
@@ -71,7 +71,7 @@ nvkm_perfdom_find(struct nvkm_pm *pm, int di)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct nvkm_perfsig *
|
||||
static struct nvkm_perfsig *
|
||||
nvkm_perfsig_find(struct nvkm_pm *pm, u8 di, u8 si, struct nvkm_perfdom **pdom)
|
||||
{
|
||||
struct nvkm_perfdom *dom = *pdom;
|
||||
@@ -699,7 +699,7 @@ nvkm_pm_oclass_get(struct nvkm_oclass *oclass, int index,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
nvkm_perfsrc_new(struct nvkm_pm *pm, struct nvkm_perfsig *sig,
|
||||
const struct nvkm_specsrc *spec)
|
||||
{
|
||||
|
||||
@@ -102,7 +102,7 @@ gf100_pm_gpc[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
const struct nvkm_specdom
|
||||
static const struct nvkm_specdom
|
||||
gf100_pm_part[] = {
|
||||
{ 0xe0, (const struct nvkm_specsig[]) {
|
||||
{ 0x0f, "part00_pbfb_00", gf100_pbfb_sources },
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t g98_sec_data[] = {
|
||||
static uint32_t g98_sec_data[] = {
|
||||
/* 0x0000: ctx_dma */
|
||||
/* 0x0000: ctx_dma_query */
|
||||
0x00000000,
|
||||
@@ -150,7 +150,7 @@ uint32_t g98_sec_data[] = {
|
||||
0x00000000,
|
||||
};
|
||||
|
||||
uint32_t g98_sec_code[] = {
|
||||
static uint32_t g98_sec_code[] = {
|
||||
0x17f004bd,
|
||||
0x0010fe35,
|
||||
0xf10004fe,
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include <subdev/bios/bit.h>
|
||||
#include <subdev/bios/fan.h>
|
||||
|
||||
u16
|
||||
static u16
|
||||
nvbios_fan_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
|
||||
{
|
||||
struct bit_entry bit_P;
|
||||
@@ -52,7 +52,7 @@ nvbios_fan_table(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
|
||||
return 0x0000;
|
||||
}
|
||||
|
||||
u16
|
||||
static u16
|
||||
nvbios_fan_entry(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr,
|
||||
u8 *cnt, u8 *len)
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ struct nvbios_source {
|
||||
bool rw;
|
||||
bool ignore_checksum;
|
||||
bool no_pcir;
|
||||
bool require_checksum;
|
||||
};
|
||||
|
||||
int nvbios_extend(struct nvkm_bios *, u32 length);
|
||||
|
||||
@@ -86,9 +86,12 @@ shadow_image(struct nvkm_bios *bios, int idx, u32 offset, struct shadow *mthd)
|
||||
nvbios_checksum(&bios->data[image.base], image.size)) {
|
||||
nvkm_debug(subdev, "%08x: checksum failed\n",
|
||||
image.base);
|
||||
if (mthd->func->rw)
|
||||
if (!mthd->func->require_checksum) {
|
||||
if (mthd->func->rw)
|
||||
score += 1;
|
||||
score += 1;
|
||||
score += 1;
|
||||
} else
|
||||
return 0;
|
||||
} else {
|
||||
score += 3;
|
||||
}
|
||||
|
||||
@@ -99,6 +99,7 @@ nvbios_acpi_fast = {
|
||||
.init = acpi_init,
|
||||
.read = acpi_read_fast,
|
||||
.rw = false,
|
||||
.require_checksum = true,
|
||||
};
|
||||
|
||||
const struct nvbios_source
|
||||
|
||||
@@ -180,7 +180,7 @@ gt215_clk_read(struct nvkm_clk *base, enum nv_clk_src src)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
gt215_clk_info(struct nvkm_clk *base, int idx, u32 khz,
|
||||
struct gt215_clk_info *info)
|
||||
{
|
||||
|
||||
@@ -24,6 +24,7 @@ nvkm-y += nvkm/subdev/fb/gk104.o
|
||||
nvkm-y += nvkm/subdev/fb/gk20a.o
|
||||
nvkm-y += nvkm/subdev/fb/gm107.o
|
||||
nvkm-y += nvkm/subdev/fb/gm200.o
|
||||
nvkm-y += nvkm/subdev/fb/gm20b.o
|
||||
nvkm-y += nvkm/subdev/fb/gp100.o
|
||||
nvkm-y += nvkm/subdev/fb/gp104.o
|
||||
|
||||
|
||||
@@ -16,4 +16,8 @@ void gf100_fb_init(struct nvkm_fb *);
|
||||
void gf100_fb_intr(struct nvkm_fb *);
|
||||
|
||||
void gp100_fb_init(struct nvkm_fb *);
|
||||
|
||||
void gm200_fb_init_page(struct nvkm_fb *fb);
|
||||
void gm200_fb_init(struct nvkm_fb *base);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
@@ -20,27 +20,21 @@
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "priv.h"
|
||||
#include "gf100.h"
|
||||
|
||||
#include <core/memory.h>
|
||||
|
||||
static void
|
||||
gk20a_fb_init(struct nvkm_fb *fb)
|
||||
{
|
||||
struct nvkm_device *device = fb->subdev.device;
|
||||
nvkm_wr32(device, 0x100cc8, nvkm_memory_addr(fb->mmu_wr) >> 8);
|
||||
nvkm_wr32(device, 0x100ccc, nvkm_memory_addr(fb->mmu_rd) >> 8);
|
||||
}
|
||||
|
||||
/* GK20A's FB is similar to GF100's, but without the ability to allocate VRAM */
|
||||
static const struct nvkm_fb_func
|
||||
gk20a_fb = {
|
||||
.dtor = gf100_fb_dtor,
|
||||
.oneinit = gf100_fb_oneinit,
|
||||
.init = gk20a_fb_init,
|
||||
.init = gf100_fb_init,
|
||||
.init_page = gf100_fb_init_page,
|
||||
.intr = gf100_fb_intr,
|
||||
.memtype_valid = gf100_fb_memtype_valid,
|
||||
};
|
||||
|
||||
int
|
||||
gk20a_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb)
|
||||
{
|
||||
return nvkm_fb_new_(&gk20a_fb, device, index, pfb);
|
||||
return gf100_fb_new_(&gk20a_fb, device, index, pfb);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ gm200_fb_init_page(struct nvkm_fb *fb)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
gm200_fb_init(struct nvkm_fb *base)
|
||||
{
|
||||
struct gf100_fb *fb = gf100_fb(base);
|
||||
|
||||
40
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c
Normal file
40
drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* 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 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 "priv.h"
|
||||
#include "gf100.h"
|
||||
|
||||
/* GM20B's FB is similar to GM200, but without the ability to allocate VRAM */
|
||||
static const struct nvkm_fb_func
|
||||
gm20b_fb = {
|
||||
.dtor = gf100_fb_dtor,
|
||||
.oneinit = gf100_fb_oneinit,
|
||||
.init = gm200_fb_init,
|
||||
.init_page = gm200_fb_init_page,
|
||||
.intr = gf100_fb_intr,
|
||||
.memtype_valid = gf100_fb_memtype_valid,
|
||||
};
|
||||
|
||||
int
|
||||
gm20b_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb)
|
||||
{
|
||||
return gf100_fb_new_(&gm20b_fb, device, index, pfb);
|
||||
}
|
||||
@@ -420,8 +420,6 @@ gf100_ram_tidy(struct nvkm_ram *base)
|
||||
ram_exec(&ram->fuc, false);
|
||||
}
|
||||
|
||||
extern const u8 gf100_pte_storage_type_map[256];
|
||||
|
||||
void
|
||||
gf100_ram_put(struct nvkm_ram *ram, struct nvkm_mem **pmem)
|
||||
{
|
||||
|
||||
@@ -95,7 +95,7 @@ struct gt215_ram {
|
||||
struct gt215_ltrain ltrain;
|
||||
};
|
||||
|
||||
void
|
||||
static void
|
||||
gt215_link_train_calc(u32 *vals, struct gt215_ltrain *train)
|
||||
{
|
||||
int i, lo, hi;
|
||||
@@ -149,7 +149,7 @@ gt215_link_train_calc(u32 *vals, struct gt215_ltrain *train)
|
||||
/*
|
||||
* Link training for (at least) DDR3
|
||||
*/
|
||||
int
|
||||
static int
|
||||
gt215_link_train(struct gt215_ram *ram)
|
||||
{
|
||||
struct gt215_ltrain *train = &ram->ltrain;
|
||||
@@ -267,7 +267,7 @@ gt215_link_train(struct gt215_ram *ram)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
gt215_link_train_init(struct gt215_ram *ram)
|
||||
{
|
||||
static const u32 pattern[16] = {
|
||||
@@ -333,7 +333,7 @@ gt215_link_train_init(struct gt215_ram *ram)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
gt215_link_train_fini(struct gt215_ram *ram)
|
||||
{
|
||||
if (ram->ltrain.mem)
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* Ben Skeggs
|
||||
*/
|
||||
#include "priv.h"
|
||||
#include "ram.h"
|
||||
|
||||
struct ramxlat {
|
||||
int id;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
* Roy Spliet <rspliet@eclipso.eu>
|
||||
*/
|
||||
#include "priv.h"
|
||||
#include "ram.h"
|
||||
|
||||
struct ramxlat {
|
||||
int id;
|
||||
|
||||
@@ -37,7 +37,7 @@ gk104_gpio_intr_stat(struct nvkm_gpio *gpio, u32 *hi, u32 *lo)
|
||||
nvkm_wr32(device, 0x00dc80, intr1);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
gk104_gpio_intr_mask(struct nvkm_gpio *gpio, u32 type, u32 mask, u32 data)
|
||||
{
|
||||
struct nvkm_device *device = gpio->subdev.device;
|
||||
|
||||
@@ -74,7 +74,7 @@ nvkm_i2c_aux_i2c_func(struct i2c_adapter *adap)
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
|
||||
}
|
||||
|
||||
const struct i2c_algorithm
|
||||
static const struct i2c_algorithm
|
||||
nvkm_i2c_aux_i2c_algo = {
|
||||
.master_xfer = nvkm_i2c_aux_i2c_xfer,
|
||||
.functionality = nvkm_i2c_aux_i2c_func
|
||||
|
||||
@@ -79,7 +79,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
|
||||
struct g94_i2c_aux *aux = g94_i2c_aux(obj);
|
||||
struct nvkm_device *device = aux->base.pad->i2c->subdev.device;
|
||||
const u32 base = aux->ch * 0x50;
|
||||
u32 ctrl, stat, timeout, retries;
|
||||
u32 ctrl, stat, timeout, retries = 0;
|
||||
u32 xbuf[4] = {};
|
||||
int ret, i;
|
||||
|
||||
@@ -111,7 +111,7 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
|
||||
nvkm_wr32(device, 0x00e4e0 + base, addr);
|
||||
|
||||
/* (maybe) retry transaction a number of times on failure... */
|
||||
for (retries = 0; !ret && retries < 32; retries++) {
|
||||
do {
|
||||
/* reset, and delay a while if this is a retry */
|
||||
nvkm_wr32(device, 0x00e4e4 + base, 0x80000000 | ctrl);
|
||||
nvkm_wr32(device, 0x00e4e4 + base, 0x00000000 | ctrl);
|
||||
@@ -131,20 +131,20 @@ g94_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
|
||||
goto out;
|
||||
}
|
||||
} while (ctrl & 0x00010000);
|
||||
ret = 1;
|
||||
ret = 0;
|
||||
|
||||
/* read status, and check if transaction completed ok */
|
||||
stat = nvkm_mask(device, 0x00e4e8 + base, 0, 0);
|
||||
if ((stat & 0x000f0000) == 0x00080000 ||
|
||||
(stat & 0x000f0000) == 0x00020000)
|
||||
ret = retry ? 0 : 1;
|
||||
ret = 1;
|
||||
if ((stat & 0x00000100))
|
||||
ret = -ETIMEDOUT;
|
||||
if ((stat & 0x00000e00))
|
||||
ret = -EIO;
|
||||
|
||||
AUX_TRACE(&aux->base, "%02d %08x %08x", retries, ctrl, stat);
|
||||
}
|
||||
} while (ret && retry && retries++ < 32);
|
||||
|
||||
if (type & 1) {
|
||||
for (i = 0; i < 16; i += 4) {
|
||||
|
||||
@@ -79,7 +79,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
|
||||
struct gm200_i2c_aux *aux = gm200_i2c_aux(obj);
|
||||
struct nvkm_device *device = aux->base.pad->i2c->subdev.device;
|
||||
const u32 base = aux->ch * 0x50;
|
||||
u32 ctrl, stat, timeout, retries;
|
||||
u32 ctrl, stat, timeout, retries = 0;
|
||||
u32 xbuf[4] = {};
|
||||
int ret, i;
|
||||
|
||||
@@ -111,7 +111,7 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
|
||||
nvkm_wr32(device, 0x00d950 + base, addr);
|
||||
|
||||
/* (maybe) retry transaction a number of times on failure... */
|
||||
for (retries = 0; !ret && retries < 32; retries++) {
|
||||
do {
|
||||
/* reset, and delay a while if this is a retry */
|
||||
nvkm_wr32(device, 0x00d954 + base, 0x80000000 | ctrl);
|
||||
nvkm_wr32(device, 0x00d954 + base, 0x00000000 | ctrl);
|
||||
@@ -131,20 +131,20 @@ gm200_i2c_aux_xfer(struct nvkm_i2c_aux *obj, bool retry,
|
||||
goto out;
|
||||
}
|
||||
} while (ctrl & 0x00010000);
|
||||
ret = 1;
|
||||
ret = 0;
|
||||
|
||||
/* read status, and check if transaction completed ok */
|
||||
stat = nvkm_mask(device, 0x00d958 + base, 0, 0);
|
||||
if ((stat & 0x000f0000) == 0x00080000 ||
|
||||
(stat & 0x000f0000) == 0x00020000)
|
||||
ret = retry ? 0 : 1;
|
||||
ret = 1;
|
||||
if ((stat & 0x00000100))
|
||||
ret = -ETIMEDOUT;
|
||||
if ((stat & 0x00000e00))
|
||||
ret = -EIO;
|
||||
|
||||
AUX_TRACE(&aux->base, "%02d %08x %08x", retries, ctrl, stat);
|
||||
}
|
||||
} while (ret && retry && retries++ < 32);
|
||||
|
||||
if (type & 1) {
|
||||
for (i = 0; i < 16; i += 4) {
|
||||
|
||||
@@ -288,7 +288,8 @@ nvkm_iccsense_init(struct nvkm_subdev *subdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nvkm_subdev_func iccsense_func = {
|
||||
static const struct nvkm_subdev_func
|
||||
iccsense_func = {
|
||||
.oneinit = nvkm_iccsense_oneinit,
|
||||
.init = nvkm_iccsense_init,
|
||||
.dtor = nvkm_iccsense_dtor,
|
||||
|
||||
@@ -104,7 +104,7 @@ nvkm_instobj_dtor(struct nvkm_memory *memory)
|
||||
return iobj;
|
||||
}
|
||||
|
||||
const struct nvkm_memory_func
|
||||
static const struct nvkm_memory_func
|
||||
nvkm_instobj_func = {
|
||||
.dtor = nvkm_instobj_dtor,
|
||||
.target = nvkm_instobj_target,
|
||||
@@ -156,7 +156,7 @@ nvkm_instobj_wr32_slow(struct nvkm_memory *memory, u64 offset, u32 data)
|
||||
return nvkm_wo32(iobj->parent, offset, data);
|
||||
}
|
||||
|
||||
const struct nvkm_memory_func
|
||||
static const struct nvkm_memory_func
|
||||
nvkm_instobj_func_slow = {
|
||||
.dtor = nvkm_instobj_dtor,
|
||||
.target = nvkm_instobj_target,
|
||||
|
||||
@@ -34,7 +34,7 @@ g84_mc_reset[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
const struct nvkm_mc_map
|
||||
static const struct nvkm_mc_map
|
||||
g84_mc_intr[] = {
|
||||
{ 0x04000000, NVKM_ENGINE_DISP },
|
||||
{ 0x00020000, NVKM_ENGINE_VP },
|
||||
|
||||
@@ -250,6 +250,10 @@ nvkm_mxm_new_(struct nvkm_device *device, int index, struct nvkm_mxm **pmxm)
|
||||
}
|
||||
|
||||
nvkm_info(&mxm->subdev, "BIOS version %d.%d\n", ver >> 4, ver & 0x0f);
|
||||
nvkm_debug(&mxm->subdev, "module flags: %02x\n",
|
||||
nvbios_rd08(bios, data + 0x01));
|
||||
nvkm_debug(&mxm->subdev, "config flags: %02x\n",
|
||||
nvbios_rd08(bios, data + 0x02));
|
||||
|
||||
if (mxm_shadow(mxm, ver)) {
|
||||
nvkm_warn(&mxm->subdev, "failed to locate valid SIS\n");
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gf100_pmu_data[] = {
|
||||
static uint32_t gf100_pmu_data[] = {
|
||||
/* 0x0000: proc_kern */
|
||||
0x52544e49,
|
||||
0x00000000,
|
||||
@@ -916,7 +916,7 @@ uint32_t gf100_pmu_data[] = {
|
||||
0x00000000,
|
||||
};
|
||||
|
||||
uint32_t gf100_pmu_code[] = {
|
||||
static uint32_t gf100_pmu_code[] = {
|
||||
0x03920ef5,
|
||||
/* 0x0004: rd32 */
|
||||
0x07a007f1,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gf119_pmu_data[] = {
|
||||
static uint32_t gf119_pmu_data[] = {
|
||||
/* 0x0000: proc_kern */
|
||||
0x52544e49,
|
||||
0x00000000,
|
||||
@@ -915,7 +915,7 @@ uint32_t gf119_pmu_data[] = {
|
||||
0x00000000,
|
||||
};
|
||||
|
||||
uint32_t gf119_pmu_code[] = {
|
||||
static uint32_t gf119_pmu_code[] = {
|
||||
0x03410ef5,
|
||||
/* 0x0004: rd32 */
|
||||
0x07a007f1,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gk208_pmu_data[] = {
|
||||
static uint32_t gk208_pmu_data[] = {
|
||||
/* 0x0000: proc_kern */
|
||||
0x52544e49,
|
||||
0x00000000,
|
||||
@@ -915,7 +915,7 @@ uint32_t gk208_pmu_data[] = {
|
||||
0x00000000,
|
||||
};
|
||||
|
||||
uint32_t gk208_pmu_code[] = {
|
||||
static uint32_t gk208_pmu_code[] = {
|
||||
0x02f90ef5,
|
||||
/* 0x0004: rd32 */
|
||||
0xf607a040,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
uint32_t gt215_pmu_data[] = {
|
||||
static uint32_t gt215_pmu_data[] = {
|
||||
/* 0x0000: proc_kern */
|
||||
0x52544e49,
|
||||
0x00000000,
|
||||
@@ -916,7 +916,7 @@ uint32_t gt215_pmu_data[] = {
|
||||
0x00000000,
|
||||
};
|
||||
|
||||
uint32_t gt215_pmu_code[] = {
|
||||
static uint32_t gt215_pmu_code[] = {
|
||||
0x03920ef5,
|
||||
/* 0x0004: rd32 */
|
||||
0x07a007f1,
|
||||
|
||||
@@ -24,17 +24,8 @@
|
||||
#include "priv.h"
|
||||
#include "fuc/gt215.fuc3.h"
|
||||
|
||||
static void
|
||||
gt215_pmu_reset(struct nvkm_pmu *pmu)
|
||||
{
|
||||
struct nvkm_device *device = pmu->subdev.device;
|
||||
nvkm_mask(device, 0x022210, 0x00000001, 0x00000000);
|
||||
nvkm_mask(device, 0x022210, 0x00000001, 0x00000001);
|
||||
}
|
||||
|
||||
static const struct nvkm_pmu_func
|
||||
gt215_pmu = {
|
||||
.reset = gt215_pmu_reset,
|
||||
.code.data = gt215_pmu_code,
|
||||
.code.size = sizeof(gt215_pmu_code),
|
||||
.data.data = gt215_pmu_data,
|
||||
|
||||
@@ -8,8 +8,6 @@ int nvkm_pmu_new_(const struct nvkm_pmu_func *, struct nvkm_device *,
|
||||
int index, struct nvkm_pmu **);
|
||||
|
||||
struct nvkm_pmu_func {
|
||||
void (*reset)(struct nvkm_pmu *);
|
||||
|
||||
struct {
|
||||
u32 *data;
|
||||
u32 size;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user