18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2018 Red Hat Inc. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 128c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 158c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 168c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 178c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 188c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 198c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 208c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ci#include <drm/drm_connector.h> 238c2ecf20Sopenharmony_ci#include <drm/drm_mode_config.h> 248c2ecf20Sopenharmony_ci#include <drm/drm_vblank.h> 258c2ecf20Sopenharmony_ci#include "nouveau_drv.h" 268c2ecf20Sopenharmony_ci#include "nouveau_bios.h" 278c2ecf20Sopenharmony_ci#include "nouveau_connector.h" 288c2ecf20Sopenharmony_ci#include "head.h" 298c2ecf20Sopenharmony_ci#include "core.h" 308c2ecf20Sopenharmony_ci#include "crc.h" 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#include <nvif/push507c.h> 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#include <nvhw/class/cl907d.h> 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ciint 378c2ecf20Sopenharmony_cihead907d_or(struct nv50_head *head, struct nv50_head_atom *asyh) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; 408c2ecf20Sopenharmony_ci const int i = head->base.index; 418c2ecf20Sopenharmony_ci int ret; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci if ((ret = PUSH_WAIT(push, 3))) 448c2ecf20Sopenharmony_ci return ret; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_CONTROL_OUTPUT_RESOURCE(i), 478c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_CONTROL_OUTPUT_RESOURCE, CRC_MODE, asyh->or.crc_raster) | 488c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_CONTROL_OUTPUT_RESOURCE, HSYNC_POLARITY, asyh->or.nhsync) | 498c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_CONTROL_OUTPUT_RESOURCE, VSYNC_POLARITY, asyh->or.nvsync) | 508c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_CONTROL_OUTPUT_RESOURCE, PIXEL_DEPTH, asyh->or.depth), 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci HEAD_SET_CONTROL(i), 0x31ec6000 | head->base.index << 25 | 538c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_CONTROL, STRUCTURE, asyh->mode.interlace)); 548c2ecf20Sopenharmony_ci return 0; 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ciint 588c2ecf20Sopenharmony_cihead907d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; 618c2ecf20Sopenharmony_ci const int i = head->base.index; 628c2ecf20Sopenharmony_ci int ret; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci if ((ret = PUSH_WAIT(push, 2))) 658c2ecf20Sopenharmony_ci return ret; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_PROCAMP(i), 688c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_PROCAMP, COLOR_SPACE, RGB) | 698c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_PROCAMP, CHROMA_LPF, AUTO) | 708c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_PROCAMP, SAT_COS, asyh->procamp.sat.cos) | 718c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_PROCAMP, SAT_SINE, asyh->procamp.sat.sin) | 728c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_PROCAMP, DYNAMIC_RANGE, VESA) | 738c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_PROCAMP, RANGE_COMPRESSION, DISABLE)); 748c2ecf20Sopenharmony_ci return 0; 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistatic int 788c2ecf20Sopenharmony_cihead907d_dither(struct nv50_head *head, struct nv50_head_atom *asyh) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; 818c2ecf20Sopenharmony_ci const int i = head->base.index; 828c2ecf20Sopenharmony_ci int ret; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci if ((ret = PUSH_WAIT(push, 2))) 858c2ecf20Sopenharmony_ci return ret; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_DITHER_CONTROL(i), 888c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_DITHER_CONTROL, ENABLE, asyh->dither.enable) | 898c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_DITHER_CONTROL, BITS, asyh->dither.bits) | 908c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_DITHER_CONTROL, MODE, asyh->dither.mode) | 918c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_DITHER_CONTROL, PHASE, 0)); 928c2ecf20Sopenharmony_ci return 0; 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ciint 968c2ecf20Sopenharmony_cihead907d_ovly(struct nv50_head *head, struct nv50_head_atom *asyh) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; 998c2ecf20Sopenharmony_ci const int i = head->base.index; 1008c2ecf20Sopenharmony_ci u32 bounds = 0; 1018c2ecf20Sopenharmony_ci int ret; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci if (asyh->ovly.cpp) { 1048c2ecf20Sopenharmony_ci switch (asyh->ovly.cpp) { 1058c2ecf20Sopenharmony_ci case 8: bounds |= NVDEF(NV907D, HEAD_SET_OVERLAY_USAGE_BOUNDS, PIXEL_DEPTH, BPP_64); break; 1068c2ecf20Sopenharmony_ci case 4: bounds |= NVDEF(NV907D, HEAD_SET_OVERLAY_USAGE_BOUNDS, PIXEL_DEPTH, BPP_32); break; 1078c2ecf20Sopenharmony_ci case 2: bounds |= NVDEF(NV907D, HEAD_SET_OVERLAY_USAGE_BOUNDS, PIXEL_DEPTH, BPP_16); break; 1088c2ecf20Sopenharmony_ci default: 1098c2ecf20Sopenharmony_ci WARN_ON(1); 1108c2ecf20Sopenharmony_ci break; 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci bounds |= NVDEF(NV907D, HEAD_SET_OVERLAY_USAGE_BOUNDS, USABLE, TRUE); 1138c2ecf20Sopenharmony_ci } else { 1148c2ecf20Sopenharmony_ci bounds |= NVDEF(NV907D, HEAD_SET_OVERLAY_USAGE_BOUNDS, PIXEL_DEPTH, BPP_16); 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci if ((ret = PUSH_WAIT(push, 2))) 1188c2ecf20Sopenharmony_ci return ret; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_OVERLAY_USAGE_BOUNDS(i), bounds); 1218c2ecf20Sopenharmony_ci return 0; 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic int 1258c2ecf20Sopenharmony_cihead907d_base(struct nv50_head *head, struct nv50_head_atom *asyh) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; 1288c2ecf20Sopenharmony_ci const int i = head->base.index; 1298c2ecf20Sopenharmony_ci u32 bounds = 0; 1308c2ecf20Sopenharmony_ci int ret; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci if (asyh->base.cpp) { 1338c2ecf20Sopenharmony_ci switch (asyh->base.cpp) { 1348c2ecf20Sopenharmony_ci case 8: bounds |= NVDEF(NV907D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, PIXEL_DEPTH, BPP_64); break; 1358c2ecf20Sopenharmony_ci case 4: bounds |= NVDEF(NV907D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, PIXEL_DEPTH, BPP_32); break; 1368c2ecf20Sopenharmony_ci case 2: bounds |= NVDEF(NV907D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, PIXEL_DEPTH, BPP_16); break; 1378c2ecf20Sopenharmony_ci case 1: bounds |= NVDEF(NV907D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, PIXEL_DEPTH, BPP_8); break; 1388c2ecf20Sopenharmony_ci default: 1398c2ecf20Sopenharmony_ci WARN_ON(1); 1408c2ecf20Sopenharmony_ci break; 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci bounds |= NVDEF(NV907D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS, USABLE, TRUE); 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci if ((ret = PUSH_WAIT(push, 2))) 1468c2ecf20Sopenharmony_ci return ret; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_BASE_CHANNEL_USAGE_BOUNDS(i), bounds); 1498c2ecf20Sopenharmony_ci return 0; 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ciint 1538c2ecf20Sopenharmony_cihead907d_curs_clr(struct nv50_head *head) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; 1568c2ecf20Sopenharmony_ci const int i = head->base.index; 1578c2ecf20Sopenharmony_ci int ret; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci if ((ret = PUSH_WAIT(push, 4))) 1608c2ecf20Sopenharmony_ci return ret; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_CONTROL_CURSOR(i), 1638c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_CONTROL_CURSOR, ENABLE, DISABLE) | 1648c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_CONTROL_CURSOR, FORMAT, A8R8G8B8) | 1658c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_CONTROL_CURSOR, SIZE, W64_H64)); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_CONTEXT_DMA_CURSOR(i), 0x00000000); 1688c2ecf20Sopenharmony_ci return 0; 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ciint 1728c2ecf20Sopenharmony_cihead907d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; 1758c2ecf20Sopenharmony_ci const int i = head->base.index; 1768c2ecf20Sopenharmony_ci int ret; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci if ((ret = PUSH_WAIT(push, 5))) 1798c2ecf20Sopenharmony_ci return ret; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_CONTROL_CURSOR(i), 1828c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_CONTROL_CURSOR, ENABLE, ENABLE) | 1838c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_CONTROL_CURSOR, FORMAT, asyh->curs.format) | 1848c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_CONTROL_CURSOR, SIZE, asyh->curs.layout) | 1858c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_CONTROL_CURSOR, HOT_SPOT_X, 0) | 1868c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_CONTROL_CURSOR, HOT_SPOT_Y, 0) | 1878c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_CONTROL_CURSOR, COMPOSITION, ALPHA_BLEND), 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci HEAD_SET_OFFSET_CURSOR(i), asyh->curs.offset >> 8); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_CONTEXT_DMA_CURSOR(i), asyh->curs.handle); 1928c2ecf20Sopenharmony_ci return 0; 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ciint 1968c2ecf20Sopenharmony_cihead907d_core_clr(struct nv50_head *head) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; 1998c2ecf20Sopenharmony_ci const int i = head->base.index; 2008c2ecf20Sopenharmony_ci int ret; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci if ((ret = PUSH_WAIT(push, 2))) 2038c2ecf20Sopenharmony_ci return ret; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_CONTEXT_DMAS_ISO(i), 0x00000000); 2068c2ecf20Sopenharmony_ci return 0; 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ciint 2108c2ecf20Sopenharmony_cihead907d_core_set(struct nv50_head *head, struct nv50_head_atom *asyh) 2118c2ecf20Sopenharmony_ci{ 2128c2ecf20Sopenharmony_ci struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; 2138c2ecf20Sopenharmony_ci const int i = head->base.index; 2148c2ecf20Sopenharmony_ci int ret; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci if ((ret = PUSH_WAIT(push, 9))) 2178c2ecf20Sopenharmony_ci return ret; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_OFFSET(i), 2208c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_OFFSET, ORIGIN, asyh->core.offset >> 8)); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_SIZE(i), 2238c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_SIZE, WIDTH, asyh->core.w) | 2248c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_SIZE, HEIGHT, asyh->core.h), 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci HEAD_SET_STORAGE(i), 2278c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_STORAGE, BLOCK_HEIGHT, asyh->core.blockh) | 2288c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_STORAGE, PITCH, asyh->core.pitch >> 8) | 2298c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_STORAGE, PITCH, asyh->core.blocks) | 2308c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_STORAGE, MEMORY_LAYOUT, asyh->core.layout), 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci HEAD_SET_PARAMS(i), 2338c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_PARAMS, FORMAT, asyh->core.format) | 2348c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_PARAMS, SUPER_SAMPLE, X1_AA) | 2358c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_PARAMS, GAMMA, LINEAR), 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci HEAD_SET_CONTEXT_DMAS_ISO(i), 2388c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_CONTEXT_DMAS_ISO, HANDLE, asyh->core.handle)); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_VIEWPORT_POINT_IN(i), 2418c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_VIEWPORT_POINT_IN, X, asyh->core.x) | 2428c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_VIEWPORT_POINT_IN, Y, asyh->core.y)); 2438c2ecf20Sopenharmony_ci return 0; 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ciint 2478c2ecf20Sopenharmony_cihead907d_olut_clr(struct nv50_head *head) 2488c2ecf20Sopenharmony_ci{ 2498c2ecf20Sopenharmony_ci struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; 2508c2ecf20Sopenharmony_ci const int i = head->base.index; 2518c2ecf20Sopenharmony_ci int ret; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci if ((ret = PUSH_WAIT(push, 4))) 2548c2ecf20Sopenharmony_ci return ret; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_OUTPUT_LUT_LO(i), 2578c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_OUTPUT_LUT_LO, ENABLE, DISABLE)); 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_CONTEXT_DMA_LUT(i), 0x00000000); 2608c2ecf20Sopenharmony_ci return 0; 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ciint 2648c2ecf20Sopenharmony_cihead907d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; 2678c2ecf20Sopenharmony_ci const int i = head->base.index; 2688c2ecf20Sopenharmony_ci int ret; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci if ((ret = PUSH_WAIT(push, 5))) 2718c2ecf20Sopenharmony_ci return ret; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_OUTPUT_LUT_LO(i), 2748c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_OUTPUT_LUT_LO, ENABLE, ENABLE) | 2758c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_OUTPUT_LUT_LO, MODE, asyh->olut.mode) | 2768c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_OUTPUT_LUT_LO, NEVER_YIELD_TO_BASE, DISABLE), 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci HEAD_SET_OUTPUT_LUT_HI(i), 2798c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_OUTPUT_LUT_HI, ORIGIN, asyh->olut.offset >> 8)); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_CONTEXT_DMA_LUT(i), asyh->olut.handle); 2828c2ecf20Sopenharmony_ci return 0; 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_civoid 2868c2ecf20Sopenharmony_cihead907d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci for (; size--; in++, mem += 8) { 2898c2ecf20Sopenharmony_ci writew(drm_color_lut_extract(in-> red, 14) + 0x6000, mem + 0); 2908c2ecf20Sopenharmony_ci writew(drm_color_lut_extract(in->green, 14) + 0x6000, mem + 2); 2918c2ecf20Sopenharmony_ci writew(drm_color_lut_extract(in-> blue, 14) + 0x6000, mem + 4); 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci /* INTERPOLATE modes require a "next" entry to interpolate with, 2958c2ecf20Sopenharmony_ci * so we replicate the last entry to deal with this for now. 2968c2ecf20Sopenharmony_ci */ 2978c2ecf20Sopenharmony_ci writew(readw(mem - 8), mem + 0); 2988c2ecf20Sopenharmony_ci writew(readw(mem - 6), mem + 2); 2998c2ecf20Sopenharmony_ci writew(readw(mem - 4), mem + 4); 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cibool 3038c2ecf20Sopenharmony_cihead907d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci if (size != 256 && size != 1024) 3068c2ecf20Sopenharmony_ci return false; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci if (size == 1024) 3098c2ecf20Sopenharmony_ci asyh->olut.mode = NV907D_HEAD_SET_OUTPUT_LUT_LO_MODE_INTERPOLATE_1025_UNITY_RANGE; 3108c2ecf20Sopenharmony_ci else 3118c2ecf20Sopenharmony_ci asyh->olut.mode = NV907D_HEAD_SET_OUTPUT_LUT_LO_MODE_INTERPOLATE_257_UNITY_RANGE; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci asyh->olut.load = head907d_olut_load; 3148c2ecf20Sopenharmony_ci return true; 3158c2ecf20Sopenharmony_ci} 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ciint 3188c2ecf20Sopenharmony_cihead907d_mode(struct nv50_head *head, struct nv50_head_atom *asyh) 3198c2ecf20Sopenharmony_ci{ 3208c2ecf20Sopenharmony_ci struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; 3218c2ecf20Sopenharmony_ci struct nv50_head_mode *m = &asyh->mode; 3228c2ecf20Sopenharmony_ci const int i = head->base.index; 3238c2ecf20Sopenharmony_ci int ret; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci if ((ret = PUSH_WAIT(push, 14))) 3268c2ecf20Sopenharmony_ci return ret; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_OVERSCAN_COLOR(i), 3298c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_OVERSCAN_COLOR, RED, 0) | 3308c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_OVERSCAN_COLOR, GRN, 0) | 3318c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_OVERSCAN_COLOR, BLU, 0), 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci HEAD_SET_RASTER_SIZE(i), 3348c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_RASTER_SIZE, WIDTH, m->h.active) | 3358c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_RASTER_SIZE, HEIGHT, m->v.active), 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci HEAD_SET_RASTER_SYNC_END(i), 3388c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_RASTER_SYNC_END, X, m->h.synce) | 3398c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_RASTER_SYNC_END, Y, m->v.synce), 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci HEAD_SET_RASTER_BLANK_END(i), 3428c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_RASTER_BLANK_END, X, m->h.blanke) | 3438c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_RASTER_BLANK_END, Y, m->v.blanke), 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci HEAD_SET_RASTER_BLANK_START(i), 3468c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_RASTER_BLANK_START, X, m->h.blanks) | 3478c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_RASTER_BLANK_START, Y, m->v.blanks), 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci HEAD_SET_RASTER_VERT_BLANK2(i), 3508c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_RASTER_VERT_BLANK2, YSTART, m->v.blank2s) | 3518c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_RASTER_VERT_BLANK2, YEND, m->v.blank2e)); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_DEFAULT_BASE_COLOR(i), 3548c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_DEFAULT_BASE_COLOR, RED, 0) | 3558c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_DEFAULT_BASE_COLOR, GREEN, 0) | 3568c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_DEFAULT_BASE_COLOR, BLUE, 0), 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci HEAD_SET_CRC_CONTROL(i), 3598c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_CRC_CONTROL, CONTROLLING_CHANNEL, CORE) | 3608c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_CRC_CONTROL, EXPECT_BUFFER_COLLAPSE, FALSE) | 3618c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_CRC_CONTROL, TIMESTAMP_MODE, FALSE) | 3628c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_CRC_CONTROL, PRIMARY_OUTPUT, NONE) | 3638c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_CRC_CONTROL, SECONDARY_OUTPUT, NONE)); 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_PIXEL_CLOCK_FREQUENCY(i), 3668c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_PIXEL_CLOCK_FREQUENCY, HERTZ, m->clock * 1000) | 3678c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_PIXEL_CLOCK_FREQUENCY, ADJ1000DIV1001, FALSE), 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci HEAD_SET_PIXEL_CLOCK_CONFIGURATION(i), 3708c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_PIXEL_CLOCK_CONFIGURATION, MODE, CLK_CUSTOM) | 3718c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_PIXEL_CLOCK_CONFIGURATION, NOT_DRIVER, FALSE) | 3728c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_PIXEL_CLOCK_CONFIGURATION, ENABLE_HOPPING, FALSE), 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci HEAD_SET_PIXEL_CLOCK_FREQUENCY_MAX(i), 3758c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_PIXEL_CLOCK_FREQUENCY_MAX, HERTZ, m->clock * 1000) | 3768c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_PIXEL_CLOCK_FREQUENCY_MAX, ADJ1000DIV1001, FALSE)); 3778c2ecf20Sopenharmony_ci return 0; 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ciint 3818c2ecf20Sopenharmony_cihead907d_view(struct nv50_head *head, struct nv50_head_atom *asyh) 3828c2ecf20Sopenharmony_ci{ 3838c2ecf20Sopenharmony_ci struct nvif_push *push = nv50_disp(head->base.base.dev)->core->chan.push; 3848c2ecf20Sopenharmony_ci const int i = head->base.index; 3858c2ecf20Sopenharmony_ci int ret; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci if ((ret = PUSH_WAIT(push, 8))) 3888c2ecf20Sopenharmony_ci return ret; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_CONTROL_OUTPUT_SCALER(i), 3918c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_CONTROL_OUTPUT_SCALER, VERTICAL_TAPS, TAPS_1) | 3928c2ecf20Sopenharmony_ci NVDEF(NV907D, HEAD_SET_CONTROL_OUTPUT_SCALER, HORIZONTAL_TAPS, TAPS_1) | 3938c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_CONTROL_OUTPUT_SCALER, HRESPONSE_BIAS, 0) | 3948c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_CONTROL_OUTPUT_SCALER, VRESPONSE_BIAS, 0)); 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_VIEWPORT_SIZE_IN(i), 3978c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_VIEWPORT_SIZE_IN, WIDTH, asyh->view.iW) | 3988c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_VIEWPORT_SIZE_IN, HEIGHT, asyh->view.iH)); 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci PUSH_MTHD(push, NV907D, HEAD_SET_VIEWPORT_SIZE_OUT(i), 4018c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_VIEWPORT_SIZE_OUT, WIDTH, asyh->view.oW) | 4028c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_VIEWPORT_SIZE_OUT, HEIGHT, asyh->view.oH), 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci HEAD_SET_VIEWPORT_SIZE_OUT_MIN(i), 4058c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_VIEWPORT_SIZE_OUT_MIN, WIDTH, asyh->view.oW) | 4068c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_VIEWPORT_SIZE_OUT_MIN, HEIGHT, asyh->view.oH), 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci HEAD_SET_VIEWPORT_SIZE_OUT_MAX(i), 4098c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_VIEWPORT_SIZE_OUT_MAX, WIDTH, asyh->view.oW) | 4108c2ecf20Sopenharmony_ci NVVAL(NV907D, HEAD_SET_VIEWPORT_SIZE_OUT_MAX, HEIGHT, asyh->view.oH)); 4118c2ecf20Sopenharmony_ci return 0; 4128c2ecf20Sopenharmony_ci} 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ciconst struct nv50_head_func 4158c2ecf20Sopenharmony_cihead907d = { 4168c2ecf20Sopenharmony_ci .view = head907d_view, 4178c2ecf20Sopenharmony_ci .mode = head907d_mode, 4188c2ecf20Sopenharmony_ci .olut = head907d_olut, 4198c2ecf20Sopenharmony_ci .olut_size = 1024, 4208c2ecf20Sopenharmony_ci .olut_set = head907d_olut_set, 4218c2ecf20Sopenharmony_ci .olut_clr = head907d_olut_clr, 4228c2ecf20Sopenharmony_ci .core_calc = head507d_core_calc, 4238c2ecf20Sopenharmony_ci .core_set = head907d_core_set, 4248c2ecf20Sopenharmony_ci .core_clr = head907d_core_clr, 4258c2ecf20Sopenharmony_ci .curs_layout = head507d_curs_layout, 4268c2ecf20Sopenharmony_ci .curs_format = head507d_curs_format, 4278c2ecf20Sopenharmony_ci .curs_set = head907d_curs_set, 4288c2ecf20Sopenharmony_ci .curs_clr = head907d_curs_clr, 4298c2ecf20Sopenharmony_ci .base = head907d_base, 4308c2ecf20Sopenharmony_ci .ovly = head907d_ovly, 4318c2ecf20Sopenharmony_ci .dither = head907d_dither, 4328c2ecf20Sopenharmony_ci .procamp = head907d_procamp, 4338c2ecf20Sopenharmony_ci .or = head907d_or, 4348c2ecf20Sopenharmony_ci}; 435