summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/nouveau/dispnv50/head.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/nouveau/dispnv50/head.c')
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/head.c58
1 files changed, 35 insertions, 23 deletions
diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c
index 929d93b1677e..d9d64602947d 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/head.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/head.c
@@ -81,18 +81,17 @@ nv50_head_atomic_check_dither(struct nv50_head_atom *armh,
struct nv50_head_atom *asyh,
struct nouveau_conn_atom *asyc)
{
- struct drm_connector *connector = asyc->state.connector;
u32 mode = 0x00;
if (asyc->dither.mode == DITHERING_MODE_AUTO) {
- if (asyh->base.depth > connector->display_info.bpc * 3)
+ if (asyh->base.depth > asyh->or.bpc * 3)
mode = DITHERING_MODE_DYNAMIC2X2;
} else {
mode = asyc->dither.mode;
}
if (asyc->dither.depth == DITHERING_DEPTH_AUTO) {
- if (connector->display_info.bpc >= 8)
+ if (asyh->or.bpc >= 8)
mode |= DITHERING_DEPTH_8BPC;
} else {
mode |= asyc->dither.depth;
@@ -214,6 +213,7 @@ nv50_head_atomic_check_lut(struct nv50_head *head,
{
struct nv50_disp *disp = nv50_disp(head->base.base.dev);
struct drm_property_blob *olut = asyh->state.gamma_lut;
+ int size;
/* Determine whether core output LUT should be enabled. */
if (olut) {
@@ -230,14 +230,23 @@ nv50_head_atomic_check_lut(struct nv50_head *head,
}
}
- if (!olut && !head->func->olut_identity) {
- asyh->olut.handle = 0;
- return 0;
+ if (!olut) {
+ if (!head->func->olut_identity) {
+ asyh->olut.handle = 0;
+ return 0;
+ }
+ size = 0;
+ } else {
+ size = drm_color_lut_size(olut);
}
+ if (!head->func->olut(head, asyh, size)) {
+ DRM_DEBUG_KMS("Invalid olut\n");
+ return -EINVAL;
+ }
asyh->olut.handle = disp->core->chan.vram.handle;
asyh->olut.buffer = !asyh->olut.buffer;
- head->func->olut(head, asyh);
+
return 0;
}
@@ -474,53 +483,56 @@ nv50_head_func = {
.atomic_destroy_state = nv50_head_atomic_destroy_state,
};
-int
+struct nv50_head *
nv50_head_create(struct drm_device *dev, int index)
{
struct nouveau_drm *drm = nouveau_drm(dev);
struct nv50_disp *disp = nv50_disp(dev);
struct nv50_head *head;
- struct nv50_wndw *curs, *wndw;
+ struct nv50_wndw *base, *ovly, *curs;
struct drm_crtc *crtc;
int ret;
head = kzalloc(sizeof(*head), GFP_KERNEL);
if (!head)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
head->func = disp->core->func->head;
head->base.index = index;
if (disp->disp->object.oclass < GV100_DISP) {
- ret = nv50_ovly_new(drm, head->base.index, &wndw);
- ret = nv50_base_new(drm, head->base.index, &wndw);
+ ret = nv50_base_new(drm, head->base.index, &base);
+ ret = nv50_ovly_new(drm, head->base.index, &ovly);
} else {
- ret = nv50_wndw_new(drm, DRM_PLANE_TYPE_OVERLAY,
- head->base.index * 2 + 1, &wndw);
ret = nv50_wndw_new(drm, DRM_PLANE_TYPE_PRIMARY,
- head->base.index * 2 + 0, &wndw);
+ head->base.index * 2 + 0, &base);
+ ret = nv50_wndw_new(drm, DRM_PLANE_TYPE_OVERLAY,
+ head->base.index * 2 + 1, &ovly);
}
if (ret == 0)
ret = nv50_curs_new(drm, head->base.index, &curs);
if (ret) {
kfree(head);
- return ret;
+ return ERR_PTR(ret);
}
crtc = &head->base.base;
- drm_crtc_init_with_planes(dev, crtc, &wndw->plane, &curs->plane,
+ drm_crtc_init_with_planes(dev, crtc, &base->plane, &curs->plane,
&nv50_head_func, "head-%d", head->base.index);
drm_crtc_helper_add(crtc, &nv50_head_help);
+ /* Keep the legacy gamma size at 256 to avoid compatibility issues */
drm_mode_crtc_set_gamma_size(crtc, 256);
+ drm_crtc_enable_color_mgmt(crtc, base->func->ilut_size,
+ disp->disp->object.oclass >= GF110_DISP,
+ head->func->olut_size);
if (head->func->olut_set) {
ret = nv50_lut_init(disp, &drm->client.mmu, &head->olut);
- if (ret)
- goto out;
+ if (ret) {
+ nv50_head_destroy(crtc);
+ return ERR_PTR(ret);
+ }
}
-out:
- if (ret)
- nv50_head_destroy(crtc);
- return ret;
+ return head;
}
OpenPOWER on IntegriCloud