提交 7e91833d 编写于 作者: B Ben Skeggs

drm/nouveau/kms/nv50: separate out dither commit

This commit separates the calculation of EVO state from the commit, in
order to make the same code useful for atomic modesetting.

The legacy interfaces have been wrapped on top of them.
Signed-off-by: NBen Skeggs <bskeggs@redhat.com>
上级 c4e6812c
...@@ -139,6 +139,12 @@ struct nv50_head_atom { ...@@ -139,6 +139,12 @@ struct nv50_head_atom {
u8 cpp; u8 cpp;
} ovly; } ovly;
struct {
bool enable:1;
u8 bits:2;
u8 mode:4;
} dither;
union { union {
struct { struct {
bool core:1; bool core:1;
...@@ -155,6 +161,7 @@ struct nv50_head_atom { ...@@ -155,6 +161,7 @@ struct nv50_head_atom {
bool mode:1; bool mode:1;
bool base:1; bool base:1;
bool ovly:1; bool ovly:1;
bool dither:1;
}; };
u16 mask; u16 mask;
} set; } set;
...@@ -798,6 +805,26 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -798,6 +805,26 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
/****************************************************************************** /******************************************************************************
* Head * Head
*****************************************************************************/ *****************************************************************************/
static void
nv50_head_dither(struct nv50_head *head, struct nv50_head_atom *asyh)
{
struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->mast.base;
u32 *push;
if ((push = evo_wait(core, 2))) {
if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA)
evo_mthd(push, 0x08a0 + (head->base.index * 0x0400), 1);
else
if (core->base.user.oclass < GK104_DISP_CORE_CHANNEL_DMA)
evo_mthd(push, 0x0490 + (head->base.index * 0x0300), 1);
else
evo_mthd(push, 0x04a0 + (head->base.index * 0x0300), 1);
evo_data(push, (asyh->dither.mode << 3) |
(asyh->dither.bits << 1) |
asyh->dither.enable);
evo_kick(push, core);
}
}
static void static void
nv50_head_ovly(struct nv50_head *head, struct nv50_head_atom *asyh) nv50_head_ovly(struct nv50_head *head, struct nv50_head_atom *asyh)
{ {
...@@ -1121,6 +1148,35 @@ nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh) ...@@ -1121,6 +1148,35 @@ nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
if (asyh->set.curs ) nv50_head_curs_set(head, asyh); if (asyh->set.curs ) nv50_head_curs_set(head, asyh);
if (asyh->set.base ) nv50_head_base (head, asyh); if (asyh->set.base ) nv50_head_base (head, asyh);
if (asyh->set.ovly ) nv50_head_ovly (head, asyh); if (asyh->set.ovly ) nv50_head_ovly (head, asyh);
if (asyh->set.dither ) nv50_head_dither (head, asyh);
}
static void
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)
mode = DITHERING_MODE_DYNAMIC2X2;
} else {
mode = asyc->dither.mode;
}
if (asyc->dither.depth == DITHERING_DEPTH_AUTO) {
if (connector->display_info.bpc >= 8)
mode |= DITHERING_DEPTH_8BPC;
} else {
mode |= asyc->dither.depth;
}
asyh->dither.enable = mode;
asyh->dither.bits = mode >> 1;
asyh->dither.mode = mode >> 3;
asyh->set.dither = true;
} }
static void static void
...@@ -1330,45 +1386,28 @@ static int ...@@ -1330,45 +1386,28 @@ static int
nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update) nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update)
{ {
struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev); struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
struct nv50_head *head = nv50_head(&nv_crtc->base);
struct nv50_head_atom *asyh = &head->asy;
struct nouveau_connector *nv_connector; struct nouveau_connector *nv_connector;
struct drm_connector *connector; struct nouveau_conn_atom asyc;
u32 *push, mode = 0x00; u32 *push;
nv_connector = nouveau_crtc_connector_get(nv_crtc); nv_connector = nouveau_crtc_connector_get(nv_crtc);
connector = &nv_connector->base;
if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) {
if (nv_crtc->base.primary->fb->depth > connector->display_info.bpc * 3)
mode = DITHERING_MODE_DYNAMIC2X2;
} else {
mode = nv_connector->dithering_mode;
}
if (nv_connector->dithering_depth == DITHERING_DEPTH_AUTO) {
if (connector->display_info.bpc >= 8)
mode |= DITHERING_DEPTH_8BPC;
} else {
mode |= nv_connector->dithering_depth;
}
push = evo_wait(mast, 4); asyc.state.connector = &nv_connector->base;
if (push) { asyc.dither.mode = nv_connector->dithering_mode;
if (nv50_vers(mast) < GF110_DISP_CORE_CHANNEL_DMA) { asyc.dither.depth = nv_connector->dithering_depth;
evo_mthd(push, 0x08a0 + (nv_crtc->index * 0x0400), 1); asyh->state.crtc = &nv_crtc->base;
evo_data(push, mode); nv50_head_atomic_check(&head->base.base, &asyh->state);
} else nv50_head_atomic_check_dither(&head->arm, asyh, &asyc);
if (nv50_vers(mast) < GK104_DISP_CORE_CHANNEL_DMA) { nv50_head_flush_set(head, asyh);
evo_mthd(push, 0x0490 + (nv_crtc->index * 0x0300), 1);
evo_data(push, mode);
} else {
evo_mthd(push, 0x04a0 + (nv_crtc->index * 0x0300), 1);
evo_data(push, mode);
}
if (update) { if (update) {
if ((push = evo_wait(mast, 2))) {
evo_mthd(push, 0x0080, 1); evo_mthd(push, 0x0080, 1);
evo_data(push, 0x00000000); evo_data(push, 0x00000000);
evo_kick(push, mast);
} }
evo_kick(push, mast);
} }
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册