Home | History | Annotate | Line # | Download | only in dispnv50
      1 /*	$NetBSD: nouveau_dispnv50_wndwc57e.c,v 1.3 2021/12/19 10:49:47 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright 2018 Red Hat Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 #include <sys/cdefs.h>
     25 __KERNEL_RCSID(0, "$NetBSD: nouveau_dispnv50_wndwc57e.c,v 1.3 2021/12/19 10:49:47 riastradh Exp $");
     26 
     27 #include "wndw.h"
     28 #include "atom.h"
     29 
     30 #include <drm/drm_atomic_helper.h>
     31 #include <drm/drm_plane_helper.h>
     32 #include <nouveau_bo.h>
     33 
     34 #include <nvif/clc37e.h>
     35 
     36 static void
     37 wndwc57e_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
     38 {
     39 	u32 *push;
     40 
     41 	if (!(push = evo_wait(&wndw->wndw, 17)))
     42 		return;
     43 
     44 	evo_mthd(push, 0x0308, 1);
     45 	evo_data(push, asyw->image.mode << 4 | asyw->image.interval);
     46 	evo_mthd(push, 0x0224, 4);
     47 	evo_data(push, asyw->image.h << 16 | asyw->image.w);
     48 	evo_data(push, asyw->image.layout << 4 | asyw->image.blockh);
     49 	evo_data(push, asyw->image.colorspace << 8 |
     50 		       asyw->image.format);
     51 	evo_data(push, asyw->image.blocks[0] | (asyw->image.pitch[0] >> 6));
     52 	evo_mthd(push, 0x0240, 1);
     53 	evo_data(push, asyw->image.handle[0]);
     54 	evo_mthd(push, 0x0260, 1);
     55 	evo_data(push, asyw->image.offset[0] >> 8);
     56 	evo_mthd(push, 0x0290, 1);
     57 	evo_data(push, (asyw->state.src_y >> 16) << 16 |
     58 		       (asyw->state.src_x >> 16));
     59 	evo_mthd(push, 0x0298, 1);
     60 	evo_data(push, (asyw->state.src_h >> 16) << 16 |
     61 		       (asyw->state.src_w >> 16));
     62 	evo_mthd(push, 0x02a4, 1);
     63 	evo_data(push, asyw->state.crtc_h << 16 |
     64 		       asyw->state.crtc_w);
     65 	evo_kick(push, &wndw->wndw);
     66 }
     67 
     68 static void
     69 wndwc57e_csc_clr(struct nv50_wndw *wndw)
     70 {
     71 	u32 *push;
     72 	if ((push = evo_wait(&wndw->wndw, 13))) {
     73 		 evo_mthd(push, 0x0400, 12);
     74 		 evo_data(push, 0x00010000);
     75 		 evo_data(push, 0x00000000);
     76 		 evo_data(push, 0x00000000);
     77 		 evo_data(push, 0x00000000);
     78 		 evo_data(push, 0x00000000);
     79 		 evo_data(push, 0x00010000);
     80 		 evo_data(push, 0x00000000);
     81 		 evo_data(push, 0x00000000);
     82 		 evo_data(push, 0x00000000);
     83 		 evo_data(push, 0x00000000);
     84 		 evo_data(push, 0x00010000);
     85 		 evo_data(push, 0x00000000);
     86 		 evo_kick(push, &wndw->wndw);
     87 	}
     88 }
     89 
     90 static void
     91 wndwc57e_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
     92 {
     93 	u32 *push, i;
     94 	if ((push = evo_wait(&wndw->wndw, 13))) {
     95 		 evo_mthd(push, 0x0400, 12);
     96 		 for (i = 0; i < 12; i++)
     97 			  evo_data(push, asyw->csc.matrix[i]);
     98 		 evo_kick(push, &wndw->wndw);
     99 	}
    100 }
    101 
    102 static void
    103 wndwc57e_ilut_clr(struct nv50_wndw *wndw)
    104 {
    105 	u32 *push;
    106 	if ((push = evo_wait(&wndw->wndw, 2))) {
    107 		evo_mthd(push, 0x0444, 1);
    108 		evo_data(push, 0x00000000);
    109 		evo_kick(push, &wndw->wndw);
    110 	}
    111 }
    112 
    113 static void
    114 wndwc57e_ilut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
    115 {
    116 	u32 *push;
    117 	if ((push = evo_wait(&wndw->wndw, 4))) {
    118 		evo_mthd(push, 0x0440, 3);
    119 		evo_data(push, asyw->xlut.i.size << 8 |
    120 			       asyw->xlut.i.mode << 2 |
    121 			       asyw->xlut.i.output_mode);
    122 		evo_data(push, asyw->xlut.handle);
    123 		evo_data(push, asyw->xlut.i.offset >> 8);
    124 		evo_kick(push, &wndw->wndw);
    125 	}
    126 }
    127 
    128 static u16
    129 fixedU0_16_FP16(u16 fixed)
    130 {
    131         int sign = 0, exp = 0, man = 0;
    132         if (fixed) {
    133                 while (--exp && !(fixed & 0x8000))
    134                         fixed <<= 1;
    135                 man = ((fixed << 1) & 0xffc0) >> 6;
    136                 exp += 15;
    137         }
    138         return (sign << 15) | (exp << 10) | man;
    139 }
    140 
    141 #ifdef __NetBSD__
    142 #define	__iomem		__lut_iomem
    143 #define	readw(p)	atomic_load_relaxed((const __iomem uint16_t *)(p))
    144 #define	writew(v,p)	atomic_store_relaxed((__iomem uint16_t *)(p), (v))
    145 #endif
    146 
    147 static void
    148 wndwc57e_ilut_load(struct drm_color_lut *in, int size, void __iomem *mem)
    149 {
    150 	memset_io(mem, 0x00, 0x20); /* VSS header. */
    151 	mem += 0x20;
    152 
    153 	for (; size--; in++, mem += 0x08) {
    154 		u16 r = fixedU0_16_FP16(drm_color_lut_extract(in->  red, 16));
    155 		u16 g = fixedU0_16_FP16(drm_color_lut_extract(in->green, 16));
    156 		u16 b = fixedU0_16_FP16(drm_color_lut_extract(in-> blue, 16));
    157 		writew(r, mem + 0);
    158 		writew(g, mem + 2);
    159 		writew(b, mem + 4);
    160 	}
    161 
    162 	/* INTERPOLATE modes require a "next" entry to interpolate with,
    163 	 * so we replicate the last entry to deal with this for now.
    164 	 */
    165 	writew(readw(mem - 8), mem + 0);
    166 	writew(readw(mem - 6), mem + 2);
    167 	writew(readw(mem - 4), mem + 4);
    168 }
    169 
    170 static bool
    171 wndwc57e_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size)
    172 {
    173 	if (size = size ? size : 1024, size != 256 && size != 1024)
    174 		return false;
    175 
    176 	if (size == 256) {
    177 		asyw->xlut.i.mode = 1; /* DIRECT8. */
    178 	} else {
    179 		asyw->xlut.i.mode = 2; /* DIRECT10. */
    180 	}
    181 	asyw->xlut.i.size = 4 /* VSS header. */ + size + 1 /* Entries. */;
    182 	asyw->xlut.i.output_mode = 0; /* INTERPOLATE_DISABLE. */
    183 	asyw->xlut.i.load = wndwc57e_ilut_load;
    184 	return true;
    185 }
    186 
    187 static const struct nv50_wndw_func
    188 wndwc57e = {
    189 	.acquire = wndwc37e_acquire,
    190 	.release = wndwc37e_release,
    191 	.sema_set = wndwc37e_sema_set,
    192 	.sema_clr = wndwc37e_sema_clr,
    193 	.ntfy_set = wndwc37e_ntfy_set,
    194 	.ntfy_clr = wndwc37e_ntfy_clr,
    195 	.ntfy_reset = corec37d_ntfy_init,
    196 	.ntfy_wait_begun = base507c_ntfy_wait_begun,
    197 	.ilut = wndwc57e_ilut,
    198 	.ilut_identity = true,
    199 	.ilut_size = 1024,
    200 	.xlut_set = wndwc57e_ilut_set,
    201 	.xlut_clr = wndwc57e_ilut_clr,
    202 	.csc = base907c_csc,
    203 	.csc_set = wndwc57e_csc_set,
    204 	.csc_clr = wndwc57e_csc_clr,
    205 	.image_set = wndwc57e_image_set,
    206 	.image_clr = wndwc37e_image_clr,
    207 	.blend_set = wndwc37e_blend_set,
    208 	.update = wndwc37e_update,
    209 };
    210 
    211 int
    212 wndwc57e_new(struct nouveau_drm *drm, enum drm_plane_type type, int index,
    213 	     s32 oclass, struct nv50_wndw **pwndw)
    214 {
    215 	return wndwc37e_new_(&wndwc57e, drm, type, index, oclass,
    216 			     BIT(index >> 1), pwndw);
    217 }
    218