0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022 #include "head.h"
0023 #include "atom.h"
0024 #include "core.h"
0025
0026 #include <nvif/pushc37b.h>
0027
0028 #include <nvhw/class/clc37d.h>
0029
0030 static int
0031 headc37d_or(struct nv50_head *head, struct nv50_head_atom *asyh)
0032 {
0033 struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
0034 const int i = head->base.index;
0035 u8 depth;
0036 int ret;
0037
0038
0039
0040
0041 switch (asyh->or.depth) {
0042 case 6: depth = 5; break;
0043 case 5: depth = 4; break;
0044 case 2: depth = 1; break;
0045 case 0: depth = 4; break;
0046 default:
0047 depth = asyh->or.depth;
0048 WARN_ON(1);
0049 break;
0050 }
0051
0052 if ((ret = PUSH_WAIT(push, 2)))
0053 return ret;
0054
0055 PUSH_MTHD(push, NVC37D, HEAD_SET_CONTROL_OUTPUT_RESOURCE(i),
0056 NVVAL(NVC37D, HEAD_SET_CONTROL_OUTPUT_RESOURCE, CRC_MODE, asyh->or.crc_raster) |
0057 NVVAL(NVC37D, HEAD_SET_CONTROL_OUTPUT_RESOURCE, HSYNC_POLARITY, asyh->or.nhsync) |
0058 NVVAL(NVC37D, HEAD_SET_CONTROL_OUTPUT_RESOURCE, VSYNC_POLARITY, asyh->or.nvsync) |
0059 NVVAL(NVC37D, HEAD_SET_CONTROL_OUTPUT_RESOURCE, PIXEL_DEPTH, depth) |
0060 NVDEF(NVC37D, HEAD_SET_CONTROL_OUTPUT_RESOURCE, COLOR_SPACE_OVERRIDE, DISABLE));
0061 return 0;
0062 }
0063
0064 static int
0065 headc37d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh)
0066 {
0067 struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
0068 const int i = head->base.index;
0069 int ret;
0070
0071 if ((ret = PUSH_WAIT(push, 2)))
0072 return ret;
0073
0074 PUSH_MTHD(push, NVC37D, HEAD_SET_PROCAMP(i),
0075 NVDEF(NVC37D, HEAD_SET_PROCAMP, COLOR_SPACE, RGB) |
0076 NVDEF(NVC37D, HEAD_SET_PROCAMP, CHROMA_LPF, DISABLE) |
0077 NVVAL(NVC37D, HEAD_SET_PROCAMP, SAT_COS, asyh->procamp.sat.cos) |
0078 NVVAL(NVC37D, HEAD_SET_PROCAMP, SAT_SINE, asyh->procamp.sat.sin) |
0079 NVDEF(NVC37D, HEAD_SET_PROCAMP, DYNAMIC_RANGE, VESA) |
0080 NVDEF(NVC37D, HEAD_SET_PROCAMP, RANGE_COMPRESSION, DISABLE) |
0081 NVDEF(NVC37D, HEAD_SET_PROCAMP, BLACK_LEVEL, GRAPHICS));
0082 return 0;
0083 }
0084
0085 int
0086 headc37d_dither(struct nv50_head *head, struct nv50_head_atom *asyh)
0087 {
0088 struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
0089 const int i = head->base.index;
0090 int ret;
0091
0092 if ((ret = PUSH_WAIT(push, 2)))
0093 return ret;
0094
0095 PUSH_MTHD(push, NVC37D, HEAD_SET_DITHER_CONTROL(i),
0096 NVVAL(NVC37D, HEAD_SET_DITHER_CONTROL, ENABLE, asyh->dither.enable) |
0097 NVVAL(NVC37D, HEAD_SET_DITHER_CONTROL, BITS, asyh->dither.bits) |
0098 NVDEF(NVC37D, HEAD_SET_DITHER_CONTROL, OFFSET_ENABLE, DISABLE) |
0099 NVVAL(NVC37D, HEAD_SET_DITHER_CONTROL, MODE, asyh->dither.mode) |
0100 NVVAL(NVC37D, HEAD_SET_DITHER_CONTROL, PHASE, 0));
0101 return 0;
0102 }
0103
0104 int
0105 headc37d_curs_clr(struct nv50_head *head)
0106 {
0107 struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
0108 const int i = head->base.index;
0109 int ret;
0110
0111 if ((ret = PUSH_WAIT(push, 4)))
0112 return ret;
0113
0114 PUSH_MTHD(push, NVC37D, HEAD_SET_CONTROL_CURSOR(i),
0115 NVDEF(NVC37D, HEAD_SET_CONTROL_CURSOR, ENABLE, DISABLE) |
0116 NVDEF(NVC37D, HEAD_SET_CONTROL_CURSOR, FORMAT, A8R8G8B8));
0117
0118 PUSH_MTHD(push, NVC37D, HEAD_SET_CONTEXT_DMA_CURSOR(i, 0), 0x00000000);
0119 return 0;
0120 }
0121
0122 int
0123 headc37d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh)
0124 {
0125 struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
0126 const int i = head->base.index;
0127 int ret;
0128
0129 if ((ret = PUSH_WAIT(push, 7)))
0130 return ret;
0131
0132 PUSH_MTHD(push, NVC37D, HEAD_SET_CONTROL_CURSOR(i),
0133 NVDEF(NVC37D, HEAD_SET_CONTROL_CURSOR, ENABLE, ENABLE) |
0134 NVVAL(NVC37D, HEAD_SET_CONTROL_CURSOR, FORMAT, asyh->curs.format) |
0135 NVVAL(NVC37D, HEAD_SET_CONTROL_CURSOR, SIZE, asyh->curs.layout) |
0136 NVVAL(NVC37D, HEAD_SET_CONTROL_CURSOR, HOT_SPOT_X, 0) |
0137 NVVAL(NVC37D, HEAD_SET_CONTROL_CURSOR, HOT_SPOT_Y, 0) |
0138 NVDEF(NVC37D, HEAD_SET_CONTROL_CURSOR, DE_GAMMA, NONE),
0139
0140 HEAD_SET_CONTROL_CURSOR_COMPOSITION(i),
0141 NVVAL(NVC37D, HEAD_SET_CONTROL_CURSOR_COMPOSITION, K1, 0xff) |
0142 NVDEF(NVC37D, HEAD_SET_CONTROL_CURSOR_COMPOSITION, CURSOR_COLOR_FACTOR_SELECT,
0143 K1) |
0144 NVDEF(NVC37D, HEAD_SET_CONTROL_CURSOR_COMPOSITION, VIEWPORT_COLOR_FACTOR_SELECT,
0145 NEG_K1_TIMES_SRC) |
0146 NVDEF(NVC37D, HEAD_SET_CONTROL_CURSOR_COMPOSITION, MODE, BLEND));
0147
0148 PUSH_MTHD(push, NVC37D, HEAD_SET_CONTEXT_DMA_CURSOR(i, 0), asyh->curs.handle);
0149 PUSH_MTHD(push, NVC37D, HEAD_SET_OFFSET_CURSOR(i, 0), asyh->curs.offset >> 8);
0150 return 0;
0151 }
0152
0153 int
0154 headc37d_curs_format(struct nv50_head *head, struct nv50_wndw_atom *asyw,
0155 struct nv50_head_atom *asyh)
0156 {
0157 asyh->curs.format = asyw->image.format;
0158 return 0;
0159 }
0160
0161 static int
0162 headc37d_olut_clr(struct nv50_head *head)
0163 {
0164 struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
0165 const int i = head->base.index;
0166 int ret;
0167
0168 if ((ret = PUSH_WAIT(push, 2)))
0169 return ret;
0170
0171 PUSH_MTHD(push, NVC37D, HEAD_SET_CONTEXT_DMA_OUTPUT_LUT(i), 0x00000000);
0172 return 0;
0173 }
0174
0175 static int
0176 headc37d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
0177 {
0178 struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
0179 const int i = head->base.index;
0180 int ret;
0181
0182 if ((ret = PUSH_WAIT(push, 4)))
0183 return ret;
0184
0185 PUSH_MTHD(push, NVC37D, HEAD_SET_CONTROL_OUTPUT_LUT(i),
0186 NVVAL(NVC37D, HEAD_SET_CONTROL_OUTPUT_LUT, SIZE, asyh->olut.size) |
0187 NVVAL(NVC37D, HEAD_SET_CONTROL_OUTPUT_LUT, RANGE, asyh->olut.range) |
0188 NVVAL(NVC37D, HEAD_SET_CONTROL_OUTPUT_LUT, OUTPUT_MODE, asyh->olut.output_mode),
0189
0190 HEAD_SET_OFFSET_OUTPUT_LUT(i), asyh->olut.offset >> 8,
0191 HEAD_SET_CONTEXT_DMA_OUTPUT_LUT(i), asyh->olut.handle);
0192 return 0;
0193 }
0194
0195 static bool
0196 headc37d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size)
0197 {
0198 if (size != 256 && size != 1024)
0199 return false;
0200
0201 asyh->olut.size = size == 1024 ? NVC37D_HEAD_SET_CONTROL_OUTPUT_LUT_SIZE_SIZE_1025 :
0202 NVC37D_HEAD_SET_CONTROL_OUTPUT_LUT_SIZE_SIZE_257;
0203 asyh->olut.range = NVC37D_HEAD_SET_CONTROL_OUTPUT_LUT_RANGE_UNITY;
0204 asyh->olut.output_mode = NVC37D_HEAD_SET_CONTROL_OUTPUT_LUT_OUTPUT_MODE_INTERPOLATE;
0205 asyh->olut.load = head907d_olut_load;
0206 return true;
0207 }
0208
0209 static int
0210 headc37d_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
0211 {
0212 struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
0213 struct nv50_head_mode *m = &asyh->mode;
0214 const int i = head->base.index;
0215 int ret;
0216
0217 if ((ret = PUSH_WAIT(push, 15)))
0218 return ret;
0219
0220 PUSH_MTHD(push, NVC37D, HEAD_SET_RASTER_SIZE(i),
0221 NVVAL(NVC37D, HEAD_SET_RASTER_SIZE, WIDTH, m->h.active) |
0222 NVVAL(NVC37D, HEAD_SET_RASTER_SIZE, HEIGHT, m->v.active),
0223
0224 HEAD_SET_RASTER_SYNC_END(i),
0225 NVVAL(NVC37D, HEAD_SET_RASTER_SYNC_END, X, m->h.synce) |
0226 NVVAL(NVC37D, HEAD_SET_RASTER_SYNC_END, Y, m->v.synce),
0227
0228 HEAD_SET_RASTER_BLANK_END(i),
0229 NVVAL(NVC37D, HEAD_SET_RASTER_BLANK_END, X, m->h.blanke) |
0230 NVVAL(NVC37D, HEAD_SET_RASTER_BLANK_END, Y, m->v.blanke),
0231
0232 HEAD_SET_RASTER_BLANK_START(i),
0233 NVVAL(NVC37D, HEAD_SET_RASTER_BLANK_START, X, m->h.blanks) |
0234 NVVAL(NVC37D, HEAD_SET_RASTER_BLANK_START, Y, m->v.blanks));
0235
0236
0237 PUSH_NVSQ(push, NVC37D, 0x2074 + (i * 0x400), m->v.blank2e << 16 | m->v.blank2s);
0238 PUSH_NVSQ(push, NVC37D, 0x2008 + (i * 0x400), m->interlace);
0239
0240 PUSH_MTHD(push, NVC37D, HEAD_SET_PIXEL_CLOCK_FREQUENCY(i),
0241 NVVAL(NVC37D, HEAD_SET_PIXEL_CLOCK_FREQUENCY, HERTZ, m->clock * 1000));
0242
0243 PUSH_MTHD(push, NVC37D, HEAD_SET_PIXEL_CLOCK_FREQUENCY_MAX(i),
0244 NVVAL(NVC37D, HEAD_SET_PIXEL_CLOCK_FREQUENCY_MAX, HERTZ, m->clock * 1000));
0245
0246
0247 PUSH_MTHD(push, NVC37D, HEAD_SET_HEAD_USAGE_BOUNDS(i),
0248 NVDEF(NVC37D, HEAD_SET_HEAD_USAGE_BOUNDS, CURSOR, USAGE_W256_H256) |
0249 NVDEF(NVC37D, HEAD_SET_HEAD_USAGE_BOUNDS, OUTPUT_LUT, USAGE_1025) |
0250 NVDEF(NVC37D, HEAD_SET_HEAD_USAGE_BOUNDS, UPSCALING_ALLOWED, TRUE));
0251 return 0;
0252 }
0253
0254 int
0255 headc37d_view(struct nv50_head *head, struct nv50_head_atom *asyh)
0256 {
0257 struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push;
0258 const int i = head->base.index;
0259 int ret;
0260
0261 if ((ret = PUSH_WAIT(push, 4)))
0262 return ret;
0263
0264 PUSH_MTHD(push, NVC37D, HEAD_SET_VIEWPORT_SIZE_IN(i),
0265 NVVAL(NVC37D, HEAD_SET_VIEWPORT_SIZE_IN, WIDTH, asyh->view.iW) |
0266 NVVAL(NVC37D, HEAD_SET_VIEWPORT_SIZE_IN, HEIGHT, asyh->view.iH));
0267
0268 PUSH_MTHD(push, NVC37D, HEAD_SET_VIEWPORT_SIZE_OUT(i),
0269 NVVAL(NVC37D, HEAD_SET_VIEWPORT_SIZE_OUT, WIDTH, asyh->view.oW) |
0270 NVVAL(NVC37D, HEAD_SET_VIEWPORT_SIZE_OUT, HEIGHT, asyh->view.oH));
0271 return 0;
0272 }
0273
0274 void
0275 headc37d_static_wndw_map(struct nv50_head *head, struct nv50_head_atom *asyh)
0276 {
0277 int i, end;
0278
0279 for (i = head->base.index * 2, end = i + 2; i < end; i++)
0280 asyh->wndw.owned |= BIT(i);
0281 }
0282
0283 const struct nv50_head_func
0284 headc37d = {
0285 .view = headc37d_view,
0286 .mode = headc37d_mode,
0287 .olut = headc37d_olut,
0288 .ilut_check = head907d_ilut_check,
0289 .olut_size = 1024,
0290 .olut_set = headc37d_olut_set,
0291 .olut_clr = headc37d_olut_clr,
0292 .curs_layout = head917d_curs_layout,
0293 .curs_format = headc37d_curs_format,
0294 .curs_set = headc37d_curs_set,
0295 .curs_clr = headc37d_curs_clr,
0296 .dither = headc37d_dither,
0297 .procamp = headc37d_procamp,
0298 .or = headc37d_or,
0299 .static_wndw_map = headc37d_static_wndw_map,
0300 };